[clang-tools-extra] [MLIR][Presburger] Implement matrix inverse (PR #67382)

Arjun P via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 13 03:36:35 PDT 2023


================
@@ -390,4 +463,83 @@ MPInt IntMatrix::normalizeRow(unsigned row, unsigned cols) {
 
 MPInt IntMatrix::normalizeRow(unsigned row) {
   return normalizeRow(row, getNumColumns());
+}
+
+std::optional<IntMatrix> IntMatrix::integerInverse() {
+  Fraction det = Fraction(determinant(), 1);
+  FracMatrix newMat(getNumRows(), getNumColumns());
+  for (unsigned i = 0; i < getNumRows(); i++)
+    for (unsigned j = 0; j < getNumColumns(); j++)
+      newMat(i, j) = Fraction(at(i, j), 1);
+
+  std::optional<FracMatrix> fracInverse = newMat.inverse();
+
+  if (!fracInverse)
+    return {};
+
+  IntMatrix intInverse(getNumRows(), getNumColumns());
+  for (unsigned i = 0; i < getNumRows(); i++)
+    for (unsigned j = 0; j < getNumColumns(); j++)
+      intInverse(i, j) = ((*fracInverse)(i, j) * det).getAsInteger();
+
+  return intInverse;
+}
+
+FracMatrix FracMatrix::identity(unsigned dimension) {
+  return Matrix::identity(dimension);
+}
+
+std::optional<FracMatrix> FracMatrix::inverse() {
+  // We use Gaussian elimination on the rows of [M | I]
+  // to find the integer inverse. We proceed left-to-right,
+  // top-to-bottom. M is assumed to be a dim x dim matrix.
+
+  unsigned dim = getNumRows();
+
+  // Construct the augmented matrix [M | I]
+  FracMatrix augmented(dim, dim + dim);
+  for (unsigned i = 0; i < dim; i++) {
+    augmented.fillRow(i, 0);
+    for (unsigned j = 0; j < dim; j++)
+      augmented(i, j) = at(i, j);
+    augmented(i, dim + i).num = 1;
+    augmented(i, dim + i).den = 1;
+  }
----------------
Superty wrote:

I think it's cleaner to just maintain a copy of `this` and the inverse as separate matrices. You can just assign to 1 btw. and filling 0 should be by default, check the constructor doc.

https://github.com/llvm/llvm-project/pull/67382


More information about the cfe-commits mailing list