MLIR: lib/Analysis/Presburger/Matrix.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
12 #include "llvm/Support/MathExtras.h"
13 #include "llvm/Support/raw_ostream.h"
14 #include
15 #include
16 #include
17
18 using namespace mlir;
19 using namespace presburger;
20
21 template
23 unsigned reservedColumns)
24 : nRows(rows), nColumns(columns),
25 nReservedColumns(std::max(nColumns, reservedColumns)),
26 data(nRows * nReservedColumns) {
28 }
29
30
31
32 template
34 if (nRows != m.getNumRows())
35 return false;
36 if (nColumns != m.getNumColumns())
37 return false;
38
39 for (unsigned i = 0; i < nRows; i++)
40 if (getRow(i) != m.getRow(i))
41 return false;
42
43 return true;
44 }
45
46 template
48 Matrix matrix(dimension, dimension);
49 for (unsigned i = 0; i < dimension; ++i)
50 matrix(i, i) = 1;
51 return matrix;
52 }
53
54 template
56 return data.capacity() / nReservedColumns;
57 }
58
59 template
61 data.reserve(rows * nReservedColumns);
62 }
63
64 template
66 resizeVertically(nRows + 1);
67 return nRows - 1;
68 }
69
70 template
72 assert(elems.size() == nColumns && "elems must match row length!");
73 unsigned row = appendExtraRow();
74 for (unsigned col = 0; col < nColumns; ++col)
75 at(row, col) = elems[col];
76 return row;
77 }
79 template
82 for (unsigned row = 0; row < nRows; ++row)
83 for (unsigned col = 0; col < nColumns; ++col)
84 transp(col, row) = at(row, col);
85
86 return transp;
87 }
88
89 template
91 if (newNColumns < nColumns)
92 removeColumns(newNColumns, nColumns - newNColumns);
93 if (newNColumns > nColumns)
94 insertColumns(nColumns, newNColumns - nColumns);
95 }
96
97 template
99 resizeHorizontally(newNColumns);
100 resizeVertically(newNRows);
102
103 template
105 nRows = newNRows;
106 data.resize(nRows * nReservedColumns);
107 }
108
109 template
111 assert((row < getNumRows() && otherRow < getNumRows()) &&
112 "Given row out of bounds");
113 if (row == otherRow)
114 return;
115 for (unsigned col = 0; col < nColumns; col++)
116 std::swap(at(row, col), at(otherRow, col));
119 template
121 assert((column < getNumColumns() && otherColumn < getNumColumns()) &&
122 "Given column out of bounds");
123 if (column == otherColumn)
124 return;
125 for (unsigned row = 0; row < nRows; row++)
126 std::swap(at(row, column), at(row, otherColumn));
127 }
128
129 template
131 return {&data[row * nReservedColumns], nColumns};
132 }
134 template
136 return {&data[row * nReservedColumns], nColumns};
137 }
139 template
141 assert(elems.size() == getNumColumns() &&
142 "elems size must match row length!");
143 for (unsigned i = 0, e = getNumColumns(); i < e; ++i)
144 at(row, i) = elems[i];
145 }
146
147 template
149 insertColumns(pos, 1);
151 template
153 if (count == 0)
154 return;
155 assert(pos <= nColumns);
156 unsigned oldNReservedColumns = nReservedColumns;
157 if (nColumns + count > nReservedColumns) {
158 nReservedColumns = llvm::NextPowerOf2(nColumns + count);
159 data.resize(nRows * nReservedColumns);
160 }
161 nColumns += count;
162
163 for (int ri = nRows - 1; ri >= 0; --ri) {
164 for (int ci = nReservedColumns - 1; ci >= 0; --ci) {
165 unsigned r = ri;
166 unsigned c = ci;
167 T &dest = data[r * nReservedColumns + c];
168 if (c >= nColumns) {
169
170
172
173
174 dest = 0;
175 } else if (c >= pos + count) {
176
177 dest = data[r * oldNReservedColumns + c - count];
178 } else if (c >= pos) {
179
180 dest = 0;
181 } else {
182
183
185 if (nReservedColumns == oldNReservedColumns)
187 dest = data[r * oldNReservedColumns + c];
188 }
190 }
191 }
193 template
195 removeColumns(pos, 1);
196 }
197 template
199 if (count == 0)
201 assert(pos + count - 1 < nColumns);
202 for (unsigned r = 0; r < nRows; ++r) {
203 for (unsigned c = pos; c < nColumns - count; ++c)
204 at(r, c) = at(r, c + count);
205 for (unsigned c = nColumns - count; c < nColumns; ++c)
206 at(r, c) = 0;
207 }
208 nColumns -= count;
209 }
210
211 template
213 insertRows(pos, 1);
214 }
215 template
217 if (count == 0)
218 return;
219
220 assert(pos <= nRows);
221 resizeVertically(nRows + count);
222 for (int r = nRows - 1; r >= int(pos + count); --r)
223 copyRow(r - count, r);
224 for (int r = pos + count - 1; r >= int(pos); --r)
225 for (unsigned c = 0; c < nColumns; ++c)
226 at(r, c) = 0;
227 }
228
229 template
231 removeRows(pos, 1);
232 }
233 template
235 if (count == 0)
236 return;
237 assert(pos + count - 1 <= nRows);
238 for (unsigned r = pos; r + count < nRows; ++r)
239 copyRow(r + count, r);
240 resizeVertically(nRows - count);
241 }
242
243 template
245 if (sourceRow == targetRow)
246 return;
247 for (unsigned c = 0; c < nColumns; ++c)
248 at(targetRow, c) = at(sourceRow, c);
249 }
250
251 template
253 for (unsigned col = 0; col < nColumns; ++col)
254 at(row, col) = value;
255 }
256
257
258
259
260
261
262
263
264
265 template
267 if (num == 0)
268 return;
269
270 int offset = dstPos - srcPos;
271 if (offset == 0)
272 return;
273
274 assert(srcPos + num <= getNumColumns() &&
275 "move source range exceeds matrix columns");
276 assert(dstPos + num <= getNumColumns() &&
277 "move destination range exceeds matrix columns");
278
279 unsigned insertCount = offset > 0 ? offset : -offset;
280 unsigned finalAdjStart = offset > 0 ? srcPos : srcPos + num;
281 unsigned curAdjStart = offset > 0 ? srcPos + num : dstPos;
282
283
284
285 insertColumns(finalAdjStart, insertCount);
286
287 if (finalAdjStart < curAdjStart)
288 curAdjStart += insertCount;
289
290
291 for (unsigned i = 0; i < insertCount; ++i)
292 swapColumns(finalAdjStart + i, curAdjStart + i);
293
294
295 removeColumns(curAdjStart, insertCount);
296 }
297
298 template
300 const T &scale) {
301 addToRow(targetRow, getRow(sourceRow), scale);
302 }
303
304 template
306 if (scale == 0)
307 return;
308 for (unsigned col = 0; col < nColumns; ++col)
309 at(row, col) += scale * rowVec[col];
310 }
311
312 template
314 for (unsigned col = 0; col < nColumns; ++col)
315 at(row, col) *= scale;
316 }
317
318 template
320 const T &scale) {
321 if (scale == 0)
322 return;
323 for (unsigned row = 0, e = getNumRows(); row < e; ++row)
324 at(row, targetColumn) += scale * at(row, sourceColumn);
325 }
326
327 template
329 for (unsigned row = 0, e = getNumRows(); row < e; ++row)
330 at(row, column) = -at(row, column);
331 }
332
333 template
335 for (unsigned column = 0, e = getNumColumns(); column < e; ++column)
336 at(row, column) = -at(row, column);
337 }
338
339 template
341 for (unsigned row = 0; row < nRows; ++row)
342 negateRow(row);
343 }
344
345 template
347 assert(rowVec.size() == getNumRows() && "Invalid row vector dimension!");
348
350 for (unsigned col = 0, e = getNumColumns(); col < e; ++col)
351 for (unsigned i = 0, e = getNumRows(); i < e; ++i)
352 result[col] += rowVec[i] * at(i, col);
353 return result;
354 }
355
356 template
358 assert(getNumColumns() == colVec.size() &&
359 "Invalid column vector dimension!");
360
362 for (unsigned row = 0, e = getNumRows(); row < e; row++)
363 for (unsigned i = 0, e = getNumColumns(); i < e; i++)
364 result[row] += at(row, i) * colVec[i];
365 return result;
366 }
367
368
369
370
371
372
374 unsigned sourceCol, unsigned targetCol,
376 assert(m(row, sourceCol) != 0 && "Cannot divide by zero!");
377 assert(m(row, sourceCol) > 0 && "Source must be positive!");
378 DynamicAPInt ratio = -floorDiv(m(row, targetCol), m(row, sourceCol));
379 m.addToColumn(sourceCol, targetCol, ratio);
380 otherMatrix.addToColumn(sourceCol, targetCol, ratio);
381 }
382
383 template
385 unsigned fromColumn,
386 unsigned toColumn) const {
387 assert(fromRow <= toRow && "end of row range must be after beginning!");
388 assert(toRow < nRows && "end of row range out of bounds!");
389 assert(fromColumn <= toColumn &&
390 "end of column range must be after beginning!");
391 assert(toColumn < nColumns && "end of column range out of bounds!");
392 Matrix subMatrix(toRow - fromRow + 1, toColumn - fromColumn + 1);
393 for (unsigned i = fromRow; i <= toRow; ++i)
394 for (unsigned j = fromColumn; j <= toColumn; ++j)
395 subMatrix(i - fromRow, j - fromColumn) = at(i, j);
396 return subMatrix;
397 }
398
399 template
402 for (unsigned row = 0; row < nRows; ++row)
403 for (unsigned column = 0; column < nColumns; ++column)
404 updatePrintMetrics(at(row, column), ptm);
405 unsigned MIN_SPACING = 1;
406 for (unsigned row = 0; row < nRows; ++row) {
407 for (unsigned column = 0; column < nColumns; ++column) {
408 printWithPrintMetrics(os, at(row, column), MIN_SPACING, ptm);
409 }
410 os << "\n";
411 }
412 }
413
414
415
416 template
419 Matrix rowsForOne(0, nColumns), rowsForZero(0, nColumns);
420 for (unsigned i = 0; i < nRows; i++) {
421 if (indicator[i] == 1)
422 rowsForOne.appendExtraRow(getRow(i));
423 else
425 }
426 return {rowsForOne, rowsForZero};
427 }
428
429 template
431 print(llvm::errs());
432 }
433
434 template
436 if (data.size() != nRows * nReservedColumns)
437 return false;
438 if (nColumns > nReservedColumns)
439 return false;
440 #ifdef EXPENSIVE_CHECKS
441 for (unsigned r = 0; r < nRows; ++r)
442 for (unsigned c = nColumns; c < nReservedColumns; ++c)
443 if (data[r * nReservedColumns + c] != 0)
444 return false;
445 #endif
446 return true;
447 }
448
449 namespace mlir {
450 namespace presburger {
453 }
454 }
455
457 IntMatrix matrix(dimension, dimension);
458 for (unsigned i = 0; i < dimension; ++i)
459 matrix(i, i) = 1;
460 return matrix;
461 }
462
464
465
466
469
470 unsigned echelonCol = 0;
471
472
473
474
475 for (unsigned row = 0; row < h.getNumRows(); ++row) {
476
477 unsigned nonZeroCol = echelonCol;
478 for (unsigned e = h.getNumColumns(); nonZeroCol < e; ++nonZeroCol) {
479 if (h(row, nonZeroCol) == 0)
480 continue;
481 break;
482 }
483
484
485
487 continue;
488
489
490
491 if (nonZeroCol != echelonCol) {
494 }
495
496
497 if (h(row, echelonCol) < 0) {
500 }
501
502
503 for (unsigned i = echelonCol + 1, e = h.getNumColumns(); i < e; ++i) {
504
505
506
507
508 if (h(row, i) < 0) {
511 }
512
513 unsigned targetCol = i, sourceCol = echelonCol;
514
515
516
517
518
519
520
521
522
523
524
525 while (h(row, targetCol) != 0 && h(row, sourceCol) != 0) {
527 std::swap(targetCol, sourceCol);
528 }
529
530
531
532 if (h(row, echelonCol) == 0) {
535 }
536 }
537
538
539
540 for (unsigned i = 0; i < echelonCol; ++i)
542
543 ++echelonCol;
544 }
545
546 return {h, u};
547 }
548
551 }
552
555 }
556
559 "determinant can only be calculated for square matrices!");
560
562
564 DynamicAPInt detM = m.determinant(&fracInverse).getAsInteger();
565
566 if (detM == 0)
567 return DynamicAPInt(0);
568
569 if (!inverse)
570 return detM;
571
573 for (unsigned i = 0; i < nRows; i++)
575 inverse->at(i, j) = (fracInverse.at(i, j) * detM).getAsInteger();
576
577 return detM;
578 }
579
582 }
583
585 : FracMatrix(m.getNumRows(), m.getNumColumns()) {
586 for (unsigned i = 0, r = m.getNumRows(); i < r; i++)
587 for (unsigned j = 0, c = m.getNumColumns(); j < c; j++)
588 this->at(i, j) = m.at(i, j);
589 }
590
593 "determinant can only be calculated for square matrices!");
594
597 if (inverse)
599
601
602
603
604
605
606
607
608
609 for (unsigned i = 0; i < nRows; i++) {
610 if (m(i, i) == 0)
611
612
613
614 for (unsigned j = i + 1; j < nRows; j++) {
615 if (m(j, i) != 0) {
616 m.swapRows(j, i);
617 if (inverse)
619 break;
620 }
621 }
622
623 b = m.at(i, i);
624 if (b == 0)
625 return 0;
626
627
628
629 if (inverse) {
630 for (unsigned j = 0; j < i; j++) {
631 if (m.at(j, i) == 0)
632 continue;
633 a = m.at(j, i);
634
635
636
637 m.addToRow(i, j, -a / b);
639 }
640 }
641
642
643
644 for (unsigned j = i + 1; j < nRows; j++) {
645 if (m.at(j, i) == 0)
646 continue;
647 a = m.at(j, i);
648
649
650
651 m.addToRow(i, j, -a / b);
652 if (inverse)
654 }
655 }
656
657
658
659
660
661 if (inverse) {
662 for (unsigned i = 0; i < nRows; i++)
663 for (unsigned j = 0; j < nRows; j++)
664 tempInv.at(i, j) = tempInv.at(i, j) / m(i, i);
665
666 *inverse = std::move(tempInv);
667 }
668
670 for (unsigned i = 0; i < nRows; i++)
672
674 }
675
677
678
680
681
682
683
684
685 for (unsigned i = 1, e = getNumRows(); i < e; i++) {
686 for (unsigned j = 0; j < i; j++) {
688 assert(jNormSquared != 0 && "some row became zero! Inputs to this "
689 "function must be linearly independent.");
692 orth.addToRow(j, i, -projectionScale);
693 }
694 }
695 return orth;
696 }
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
725 DynamicAPInt nearest;
727
728
729
730
731
733
734
735 unsigned k = 1;
737 for (unsigned j = k - 1; j < k; j--) {
738
741 nearest = round(mu);
742
744 gsOrth = gramSchmidt();
745 }
748
750 (delta - mu * mu) *
752
753 k += 1;
754 } else {
755
756
758 gsOrth = gramSchmidt();
759 k = k > 1 ? k - 1 : 1;
760 }
761 }
762 }
763
767 IntMatrix normalized(numRows, numColumns);
768
769 DynamicAPInt lcmDenoms = DynamicAPInt(1);
770 for (unsigned i = 0; i < numRows; i++) {
771
772 for (unsigned j = 0; j < numColumns; j++)
773 lcmDenoms = lcm(lcmDenoms, at(i, j).den);
774
775 for (unsigned j = 0; j < numColumns; j++)
776 normalized(i, j) = (at(i, j) * lcmDenoms).getAsInteger();
777 }
778 return normalized;
779 }
static void modEntryColumnOperation(Matrix< DynamicAPInt > &m, unsigned row, unsigned sourceCol, unsigned targetCol, Matrix< DynamicAPInt > &otherMatrix)
Set M(row, targetCol) to its remainder on division by M(row, sourceCol) by subtracting from column ta...
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
FracMatrix gramSchmidt() const
IntMatrix normalizeRows() const
static FracMatrix identity(unsigned dimension)
Return the identity matrix of the specified dimension.
FracMatrix(unsigned rows, unsigned columns, unsigned reservedRows=0, unsigned reservedColumns=0)
Fraction determinant(FracMatrix *inverse=nullptr) const
static IntMatrix identity(unsigned dimension)
Return the identity matrix of the specified dimension.
std::pair< IntMatrix, IntMatrix > computeHermiteNormalForm() const
Given the current matrix M, returns the matrices H, U such that H is the column hermite normal form o...
DynamicAPInt determinant(IntMatrix *inverse=nullptr) const
IntMatrix(unsigned rows, unsigned columns, unsigned reservedRows=0, unsigned reservedColumns=0)
DynamicAPInt normalizeRow(unsigned row, unsigned nCols)
Divide the first nCols of the specified row by their GCD.
This is a class to represent a resizable matrix.
void moveColumns(unsigned srcPos, unsigned num, unsigned dstPos)
Move the columns in the source range [srcPos, srcPos + num) to the specified destination [dstPos,...
bool hasConsistentState() const
Return whether the Matrix is in a consistent state with all its invariants satisfied.
void insertRows(unsigned pos, unsigned count)
Insert rows having positions pos, pos + 1, ...
unsigned getNumRows() const
void swapColumns(unsigned column, unsigned otherColumn)
Swap the given columns.
unsigned nRows
The current number of rows, columns, and reserved columns.
void removeColumn(unsigned pos)
unsigned appendExtraRow()
Add an extra row at the bottom of the matrix and return its position.
unsigned nReservedColumns
void addToColumn(unsigned sourceColumn, unsigned targetColumn, const T &scale)
Add scale multiples of the source column to the target column.
Matrix< T > getSubMatrix(unsigned fromRow, unsigned toRow, unsigned fromColumn, unsigned toColumn) const
void print(raw_ostream &os) const
Print the matrix.
void copyRow(unsigned sourceRow, unsigned targetRow)
void scaleRow(unsigned row, const T &scale)
Multiply the specified row by a factor of scale.
void insertColumn(unsigned pos)
MutableArrayRef< T > getRow(unsigned row)
Get a [Mutable]ArrayRef corresponding to the specified row.
void removeColumns(unsigned pos, unsigned count)
Remove the columns having positions pos, pos + 1, ...
void insertColumns(unsigned pos, unsigned count)
Insert columns having positions pos, pos + 1, ...
void setRow(unsigned row, ArrayRef< T > elems)
Set the specified row to elems.
std::pair< Matrix< T >, Matrix< T > > splitByBitset(ArrayRef< int > indicator)
Split the rows of a matrix into two matrices according to which bits are 1 and which are 0 in a given...
void removeRow(unsigned pos)
bool operator==(const Matrix< T > &m) const
We cannot use the default implementation of operator== as it compares fields like reservedColumns etc...
SmallVector< T, 16 > data
Stores the data.
unsigned getNumColumns() const
void resizeVertically(unsigned newNRows)
unsigned getNumReservedRows() const
Return the maximum number of rows/columns that can be added without incurring a reallocation.
Matrix< T > transpose() const
SmallVector< T, 8 > preMultiplyWithRow(ArrayRef< T > rowVec) const
The given vector is interpreted as a row vector v.
static Matrix identity(unsigned dimension)
Return the identity matrix of the specified dimension.
void insertRow(unsigned pos)
SmallVector< T, 8 > postMultiplyWithColumn(ArrayRef< T > colVec) const
The given vector is interpreted as a column vector v.
void negateMatrix()
Negate the entire matrix.
void swapRows(unsigned row, unsigned otherRow)
Swap the given rows.
void resizeHorizontally(unsigned newNColumns)
void reserveRows(unsigned rows)
Reserve enough space to resize to the specified number of rows without reallocations.
void negateColumn(unsigned column)
Negate the specified column.
void resize(unsigned newNRows, unsigned newNColumns)
Resize the matrix to the specified dimensions.
void fillRow(unsigned row, const T &value)
void addToRow(unsigned sourceRow, unsigned targetRow, const T &scale)
Add scale multiples of the source row to the target row.
void negateRow(unsigned row)
Negate the specified row.
T & at(unsigned row, unsigned column)
Access the element at the specified row and column.
void removeRows(unsigned pos, unsigned count)
Remove the rows having positions pos, pos + 1, ...
DynamicAPInt round(const Fraction &f)
Fraction dotProduct(ArrayRef< Fraction > a, ArrayRef< Fraction > b)
Compute the dot product of two vectors.
DynamicAPInt normalizeRange(MutableArrayRef< DynamicAPInt > range)
Divide the range by its gcd and return the gcd.
Include the generated interface declarations.
A class to represent fractions.
Example usage: Print .12, 3.4, 56.7 preAlign = ".", minSpacing = 1, .12 .12 3.4 3....
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.