[Mlir-commits] [mlir] [MLIR][Presburger] Add support for Smith normal form (PR #185328)

Arjun Pitchanathan llvmlistbot at llvm.org
Sun Mar 15 16:55:35 PDT 2026


================
@@ -535,6 +553,129 @@ std::pair<IntMatrix, IntMatrix> IntMatrix::computeHermiteNormalForm() const {
   return {h, u};
 }
 
+std::tuple<IntMatrix, IntMatrix, IntMatrix>
+IntMatrix::computeSmithNormalForm() const {
+  IntMatrix d = *this;
+  // We put D into diagonal form by applying row and columns operations to it.
+  // The matrix U records row operations applied in the process, and V records
+  // column operations.
+  IntMatrix u = IntMatrix::identity(d.getNumRows());
+  IntMatrix v = IntMatrix::identity(d.getNumColumns());
+
+  unsigned numRows = d.getNumRows();
+  unsigned numCols = d.getNumColumns();
+  for (unsigned i = 0, e = std::min(numRows, numCols); i < e; i++) {
+    // We first put D into diagonal form, and then ensure the divisibility
+    // condition. The latter step is better illustrated with an example:
+    //
+    // [6 0 ] ---(1)--> [6 10] ---(2)--> [2 0 ]
+    // [0 10]           [0 10]           [0 10]
+    //
+    // (1) adds the element violating the divisibility constraint to the same
+    // column in row i;
+    // (2) does an elimination of the column.
+    //
+    // There can be many elements that violate the constraint, hence the loop.
+    bool changed;
+    do {
+      changed = false;
+
+      // Find the entry in the submatrix d(i:, i:) with the smallest non-zero
+      // absolute value.
+      // The element is the pivot, and we record its current row and column.
+      unsigned pvtRow = i, pvtCol = i;
+      DynamicAPInt minVal(0);
+      for (unsigned r = i; r < numRows; r++) {
+        for (unsigned c = i; c < numCols; c++) {
+          DynamicAPInt val = llvm::abs(d(r, c));
+          if (val == 0 || (minVal != 0 && val >= minVal))
+            continue;
+
+          minVal = val;
+          pvtRow = r;
+          pvtCol = c;
----------------
superty wrote:

you can make a minInSubmatrix() free function here that takes a matrix. that would clean up this function 

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


More information about the Mlir-commits mailing list