[Mlir-commits] [mlir] [MLIR][Presburger] Implement Matrix::moveColumns (PR #68362)

Bharathi Ramana Joshi llvmlistbot at llvm.org
Thu Jan 4 23:40:42 PST 2024


https://github.com/iambrj updated https://github.com/llvm/llvm-project/pull/68362

>From c1c73408c0ce6b72d09d3e5217284eee95d21f69 Mon Sep 17 00:00:00 2001
From: iambrj <joshibharathiramana at gmail.com>
Date: Fri, 5 Jan 2024 13:06:05 +0530
Subject: [PATCH] [MLIR][Presburger] Implement Matrix::moveColumns

---
 .../include/mlir/Analysis/Presburger/Matrix.h | 18 +++++++
 mlir/lib/Analysis/Presburger/Matrix.cpp       | 41 ++++++++++++++
 .../Analysis/Presburger/MatrixTest.cpp        | 53 +++++++++++++++++--
 3 files changed, 108 insertions(+), 4 deletions(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/Matrix.h b/mlir/include/mlir/Analysis/Presburger/Matrix.h
index 347e2e0489786f..94f6fede95e871 100644
--- a/mlir/include/mlir/Analysis/Presburger/Matrix.h
+++ b/mlir/include/mlir/Analysis/Presburger/Matrix.h
@@ -189,6 +189,24 @@ class Matrix {
   /// invariants satisfied.
   bool hasConsistentState() const;
 
+  /// Move the columns in the source range [srcPos, srcPos + num) to the
+  /// specified destination [dstPos, dstPos + num), while moving the columns
+  /// adjacent to the source range to the left/right of the shifted columns.
+  ///
+  /// When moving the source columns right (i.e. dstPos > srcPos), columns that
+  /// were at positions [0, srcPos) and [dstPos + num, nCols) will stay where
+  /// they are; columns that were at positions [srcPos, srcPos + num) will be
+  /// moved to [dstPos, dstPos + num); and columns that were at positions
+  /// [srcPos + num, dstPos + num) will be moved to [srcPos, dstPos).
+  /// Equivalently, the columns [srcPos + num, dstPos + num) are interchanged
+  /// with [srcPos, srcPos + num).
+  /// For example, if m = |0 1 2 3 4 5| then:
+  /// m.moveColumns(1, 3, 2) will result in m = |0 4 1 2 3 5|; or
+  /// m.moveColumns(1, 2, 4) will result in m = |0 3 4 5 1 2|.
+  ///
+  /// The left shift operation (i.e. dstPos < srcPos) works in a similar way.
+  void moveColumns(unsigned srcPos, unsigned num, unsigned dstPos);
+
 protected:
   /// The current number of rows, columns, and reserved columns. The underlying
   /// data vector is viewed as an nRows x nReservedColumns matrix, of which the
diff --git a/mlir/lib/Analysis/Presburger/Matrix.cpp b/mlir/lib/Analysis/Presburger/Matrix.cpp
index 1f1188c115a8b5..648b33890a98dd 100644
--- a/mlir/lib/Analysis/Presburger/Matrix.cpp
+++ b/mlir/lib/Analysis/Presburger/Matrix.cpp
@@ -230,6 +230,47 @@ void Matrix<T>::fillRow(unsigned row, const T &value) {
     at(row, col) = value;
 }
 
+// moveColumns is implemented by moving the columns adjacent to the source range
+// to their final position. When moving right (i.e. dstPos > srcPos), the range
+// of the adjacent columns is [srcPos + num, dstPos + num). When moving left
+// (i.e. dstPos < srcPos) the range of the adjacent columns is [dstPos, srcPos).
+// First, zeroed out columns are inserted in the final positions of the adjacent
+// columns. Then, the adjacent columns are moved to their final positions by
+// swapping them with the zeroed columns. Finally, the now zeroed adjacent
+// columns are deleted.
+template <typename T>
+void Matrix<T>::moveColumns(unsigned srcPos, unsigned num, unsigned dstPos) {
+  if (num == 0)
+    return;
+
+  int offset = dstPos - srcPos;
+  if (offset == 0)
+    return;
+
+  assert(srcPos + num <= getNumColumns() &&
+         "move source range exceeds matrix columns");
+  assert(dstPos + num <= getNumColumns() &&
+         "move destination range exceeds matrix columns");
+
+  unsigned insertCount = offset > 0 ? offset : -offset;
+  unsigned finalAdjStart = offset > 0 ? srcPos : srcPos + num;
+  unsigned curAdjStart = offset > 0 ? srcPos + num : dstPos;
+  // TODO: This can be done using std::rotate.
+  // Insert new zero columns in the positions where the adjacent columns are to
+  // be moved.
+  insertColumns(finalAdjStart, insertCount);
+  // Update curAdjStart if insertion of new columns invalidates it.
+  if (finalAdjStart < curAdjStart)
+    curAdjStart += insertCount;
+
+  // Swap the adjacent columns with inserted zero columns.
+  for (unsigned i = 0; i < insertCount; ++i)
+    swapColumns(finalAdjStart + i, curAdjStart + i);
+
+  // Delete the now redundant zero columns.
+  removeColumns(curAdjStart, insertCount);
+}
+
 template <typename T>
 void Matrix<T>::addToRow(unsigned sourceRow, unsigned targetRow,
                          const T &scale) {
diff --git a/mlir/unittests/Analysis/Presburger/MatrixTest.cpp b/mlir/unittests/Analysis/Presburger/MatrixTest.cpp
index 103619518c15a2..fa1f32970b1463 100644
--- a/mlir/unittests/Analysis/Presburger/MatrixTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/MatrixTest.cpp
@@ -194,13 +194,21 @@ TEST(MatrixTest, resize) {
       EXPECT_EQ(mat(row, col), row >= 3 || col >= 3 ? 0 : int(10 * row + col));
 }
 
+template <typename T>
+static void checkMatEqual(const Matrix<T> m1, const Matrix<T> m2) {
+  EXPECT_EQ(m1.getNumRows(), m2.getNumRows());
+  EXPECT_EQ(m1.getNumColumns(), m2.getNumColumns());
+
+  for (unsigned row = 0, rows = m1.getNumRows(); row < rows; ++row)
+    for (unsigned col = 0, cols = m1.getNumColumns(); col < cols; ++col)
+      EXPECT_EQ(m1(row, col), m2(row, col));
+}
+
 static void checkHermiteNormalForm(const IntMatrix &mat,
                                    const IntMatrix &hermiteForm) {
   auto [h, u] = mat.computeHermiteNormalForm();
 
-  for (unsigned row = 0; row < mat.getNumRows(); row++)
-    for (unsigned col = 0; col < mat.getNumColumns(); col++)
-      EXPECT_EQ(h(row, col), hermiteForm(row, col));
+  checkMatEqual(h, hermiteForm);
 }
 
 TEST(MatrixTest, computeHermiteNormalForm) {
@@ -428,4 +436,41 @@ TEST(MatrixTest, LLL) {
   mat.LLL(Fraction(3, 4));
 
   checkReducedBasis(mat, Fraction(3, 4));
-}
\ No newline at end of file
+}
+
+TEST(MatrixTest, moveColumns) {
+  IntMatrix mat =
+      makeIntMatrix(3, 4, {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 4, 2}});
+
+  {
+    IntMatrix movedMat =
+        makeIntMatrix(3, 4, {{0, 3, 1, 2}, {4, 7, 5, 6}, {8, 2, 9, 4}});
+
+    movedMat.moveColumns(2, 2, 1);
+    checkMatEqual(mat, movedMat);
+  }
+
+  {
+    IntMatrix movedMat =
+        makeIntMatrix(3, 4, {{0, 3, 1, 2}, {4, 7, 5, 6}, {8, 2, 9, 4}});
+
+    movedMat.moveColumns(1, 1, 3);
+    checkMatEqual(mat, movedMat);
+  }
+
+  {
+    IntMatrix movedMat =
+        makeIntMatrix(3, 4, {{1, 2, 0, 3}, {5, 6, 4, 7}, {9, 4, 8, 2}});
+
+    movedMat.moveColumns(0, 2, 1);
+    checkMatEqual(mat, movedMat);
+  }
+
+  {
+    IntMatrix movedMat =
+        makeIntMatrix(3, 4, {{1, 0, 2, 3}, {5, 4, 6, 7}, {9, 8, 4, 2}});
+
+    movedMat.moveColumns(0, 1, 1);
+    checkMatEqual(mat, movedMat);
+  }
+}



More information about the Mlir-commits mailing list