12#include "llvm/Support/MathExtras.h"
13#include "llvm/Support/raw_ostream.h"
23 unsigned reservedColumns)
39 for (
unsigned i = 0; i <
nRows; i++)
48 Matrix matrix(dimension, dimension);
49 for (
unsigned i = 0; i < dimension; ++i)
72 assert(elems.size() ==
nColumns &&
"elems must match row length!");
74 for (
unsigned col = 0; col <
nColumns; ++col)
75 at(row, col) = elems[col];
82 for (
unsigned row = 0; row <
nRows; ++row)
83 for (
unsigned col = 0; col <
nColumns; ++col)
84 transp(col, row) =
at(row, col);
112 "Given row out of bounds");
115 for (
unsigned col = 0; col <
nColumns; col++)
116 std::swap(
at(row, col),
at(otherRow, col));
122 "Given column out of bounds");
123 if (column == otherColumn)
125 for (
unsigned row = 0; row <
nRows; row++)
126 std::swap(
at(row, column),
at(row, otherColumn));
142 "elems size must match row length!");
144 at(row, i) = elems[i];
163 for (
int ri =
nRows - 1; ri >= 0; --ri) {
175 }
else if (c >= pos + count) {
177 dest = data[r * oldNReservedColumns + c - count];
178 }
else if (c >= pos) {
187 dest =
data[r * oldNReservedColumns + c];
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);
220 assert(pos <=
nRows);
222 for (
int r =
nRows - 1; r >= int(pos + count); --r)
224 for (
int r = pos + count - 1; r >= int(pos); --r)
225 for (
unsigned c = 0; c <
nColumns; ++c)
237 assert(pos + count - 1 <=
nRows);
238 for (
unsigned r = pos; r + count <
nRows; ++r)
245 if (sourceRow == targetRow)
247 for (
unsigned c = 0; c <
nColumns; ++c)
248 at(targetRow, c) =
at(sourceRow, c);
253 for (
unsigned col = 0; col <
nColumns; ++col)
254 at(row, col) = value;
264 if (dstPos == srcPos)
268 "move source range exceeds matrix columns");
270 "move destination range exceeds matrix columns");
276 if (dstPos > srcPos) {
277 for (
unsigned i = 0; i < numRows; ++i) {
278 std::rotate(&
at(i, srcPos), &
at(i, srcPos) + num, &
at(i, dstPos) + num);
282 for (
unsigned i = 0; i < numRows; ++i) {
283 std::rotate(&
at(i, dstPos), &
at(i, srcPos), &
at(i, srcPos) + num);
295 for (
unsigned i = 0; i < n; i++) {
296 for (
unsigned j = 0;
j < m;
j++) {
297 for (
unsigned k = 0; k < p; k++) {
315 for (
unsigned col = 0; col <
nColumns; ++col)
316 at(row, col) += scale * rowVec[col];
321 for (
unsigned col = 0; col <
nColumns; ++col)
322 at(row, col) *= scale;
330 for (
unsigned row = 0, e =
getNumRows(); row < e; ++row)
331 at(row, targetColumn) += scale *
at(row, sourceColumn);
336 for (
unsigned row = 0, e =
getNumRows(); row < e; ++row)
337 at(row, column) = -
at(row, column);
342 for (
unsigned column = 0, e =
getNumColumns(); column < e; ++column)
343 at(row, column) = -
at(row, column);
348 for (
unsigned row = 0; row <
nRows; ++row)
354 assert(rowVec.size() ==
getNumRows() &&
"Invalid row vector dimension!");
358 for (
unsigned i = 0, e =
getNumRows(); i < e; ++i)
359 result[col] += rowVec[i] *
at(i, col);
366 "Invalid column vector dimension!");
369 for (
unsigned row = 0, e =
getNumRows(); row < e; row++)
371 result[row] +=
at(row, i) * colVec[i];
381 unsigned sourceCol,
unsigned targetCol,
383 assert(m(row, sourceCol) != 0 &&
"Cannot divide by zero!");
384 assert(m(row, sourceCol) > 0 &&
"Source must be positive!");
385 DynamicAPInt ratio = -floorDiv(m(row, targetCol), m(row, sourceCol));
387 otherMatrix.
addToColumn(sourceCol, targetCol, ratio);
393 unsigned toColumn)
const {
394 assert(fromRow <= toRow &&
"end of row range must be after beginning!");
395 assert(toRow <=
nRows &&
"end of row range out of bounds!");
396 assert(fromColumn <= toColumn &&
397 "end of column range must be after beginning!");
398 assert(toColumn <=
nColumns &&
"end of column range out of bounds!");
399 Matrix<T> subMatrix(toRow - fromRow, toColumn - fromColumn);
400 for (
unsigned i = fromRow; i < toRow; ++i)
401 for (
unsigned j = fromColumn;
j < toColumn; ++
j)
402 subMatrix(i - fromRow,
j - fromColumn) =
at(i,
j);
409 for (
unsigned row = 0; row <
nRows; ++row)
410 for (
unsigned column = 0; column <
nColumns; ++column)
412 unsigned minSpacing = 1;
413 for (
unsigned row = 0; row <
nRows; ++row) {
414 for (
unsigned column = 0; column <
nColumns; ++column) {
427 for (
unsigned i = 0; i <
nRows; i++) {
428 if (indicator[i] == 1)
429 rowsForOne.appendExtraRow(
getRow(i));
433 return {rowsForOne, rowsForZero};
447#ifdef EXPENSIVE_CHECKS
448 for (
unsigned r = 0; r <
nRows; ++r)
465 for (
unsigned i = 0; i < dimension; ++i)
472 for (
unsigned i = 0; i <
nRows; i++)
474 mat(i,
j) =
at(i,
j);
486 unsigned echelonCol = 0;
491 for (
unsigned row = 0; row < h.
getNumRows(); ++row) {
493 unsigned nonZeroCol = echelonCol;
494 for (
unsigned e = h.
getNumColumns(); nonZeroCol < e; ++nonZeroCol) {
495 if (h(row, nonZeroCol) == 0)
507 if (nonZeroCol != echelonCol) {
513 if (h(row, echelonCol) < 0) {
519 for (
unsigned i = echelonCol + 1, e = h.
getNumColumns(); i < e; ++i) {
529 unsigned targetCol = i, sourceCol = echelonCol;
541 while (h(row, targetCol) != 0 && h(row, sourceCol) != 0) {
543 std::swap(targetCol, sourceCol);
548 if (h(row, echelonCol) == 0) {
556 for (
unsigned i = 0; i < echelonCol; ++i)
568static std::optional<std::pair<unsigned, unsigned>>
572 unsigned minRow = from, minCol = from;
574 std::optional<DynamicAPInt> minVal;
575 for (
unsigned r = from; r < numRows; r++) {
576 for (
unsigned c = from; c < numCols; c++) {
577 DynamicAPInt val = llvm::abs(mat(r, c));
578 if (val == 0 || (minVal && val >= *minVal))
590 return std::make_pair(minRow, minCol);
598 const DynamicAPInt &divisor) {
601 for (
unsigned row = from; row < numRows; ++row) {
602 for (
unsigned col = from; col < numCols; ++col) {
603 if (mat(row, col) % divisor != 0)
610std::tuple<IntMatrix, IntMatrix, IntMatrix>
621 for (
unsigned i = 0, e = std::min(numRows, numCols); i < e; i++) {
643 auto [pvtRow, pvtCol] = *pivotPos;
646 if (d(pvtRow, pvtCol) == 0)
666 for (
unsigned r = i + 1; r < numRows; ++r) {
667 while (d(r, i) != 0) {
668 DynamicAPInt quotient = d(r, i) / d(i, i);
680 for (
unsigned c = i + 1; c < numCols; ++c) {
681 while (d(i, c) != 0) {
682 DynamicAPInt quotient = d(i, c) / d(i, i);
718 "determinant can only be calculated for square matrices!");
726 return DynamicAPInt(0);
732 for (
unsigned i = 0; i <
nRows; i++)
734 inverse->
at(i,
j) = (fracInverse.
at(i,
j) * detM).getAsInteger();
745 for (
unsigned i = 0; i <
nRows; i++)
747 mat(i,
j) =
at(i,
j).getAsInteger();
754 for (
unsigned i = 0, r = m.
getNumRows(); i < r; i++)
756 this->at(i,
j) = m.
at(i,
j);
761 "determinant can only be calculated for square matrices!");
777 for (
unsigned i = 0; i <
nRows; i++) {
782 for (
unsigned j = i + 1;
j <
nRows;
j++) {
798 for (
unsigned j = 0;
j < i;
j++) {
812 for (
unsigned j = i + 1;
j <
nRows;
j++) {
830 for (
unsigned i = 0; i <
nRows; i++)
831 for (
unsigned j = 0;
j <
nRows;
j++)
832 tempInv.
at(i,
j) = tempInv.
at(i,
j) / m(i, i);
834 *inverse = std::move(tempInv);
838 for (
unsigned i = 0; i <
nRows; i++)
853 for (
unsigned i = 1, e =
getNumRows(); i < e; i++) {
854 for (
unsigned j = 0;
j < i;
j++) {
856 assert(jNormSquared != 0 &&
"some row became zero! Inputs to this "
857 "function must be linearly independent.");
893 DynamicAPInt nearest;
905 for (
unsigned j = k - 1;
j < k;
j--) {
927 k = k > 1 ? k - 1 : 1;
935 IntMatrix normalized(numRows, numColumns);
937 DynamicAPInt lcmDenoms = DynamicAPInt(1);
938 for (
unsigned i = 0; i < numRows; i++) {
940 for (
unsigned j = 0;
j < numColumns;
j++)
941 lcmDenoms = lcm(lcmDenoms,
at(i,
j).den);
943 for (
unsigned j = 0;
j < numColumns;
j++)
944 normalized(i,
j) = (
at(i,
j) * lcmDenoms).getAsInteger();
static std::optional< std::pair< unsigned, unsigned > > findNonZeroMinInSubmatrix(const IntMatrix &mat, unsigned from)
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 std::optional< unsigned > findNonMultipleRow(const IntMatrix &mat, unsigned from, const DynamicAPInt &divisor)
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
void LLL(const Fraction &delta)
IntMatrix asIntMatrix() 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
FracMatrix asFracMatrix() 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.
std::tuple< IntMatrix, IntMatrix, IntMatrix > computeSmithNormalForm() const
Given the current matrix M, returns the matrices U, D, V such that UMV = D, where D is called the Smi...
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)
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)
void insertColumns(unsigned pos, unsigned count)
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
T & at(unsigned row, unsigned column)
Access the element at the specified row and column.
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.
Matrix< T > postMultiply(const Matrix< T > &other) const
Returns the matrix right-multiplied with other.
void removeRows(unsigned pos, unsigned count)
Remove the rows having positions pos, pos + 1, ... pos + count - 1.
DynamicAPInt round(const Fraction &f)
Fraction dotProduct(ArrayRef< Fraction > a, ArrayRef< Fraction > b)
Compute the dot product of two vectors.
void printWithPrintMetrics(raw_ostream &os, T val, unsigned minSpacing, const PrintTableMetrics &m)
Print val in the table with metrics specified in 'm'.
void updatePrintMetrics(T val, PrintTableMetrics &m)
Iterate over each val in the table and update 'm' where .maxPreIndent and .maxPostIndent are initiali...
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.
DynamicAPInt getAsInteger() const
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.