7
7
// ===----------------------------------------------------------------------===//
8
8
//
9
9
// This is a simple 2D matrix class that supports reading, writing, resizing,
10
- // swapping rows, and swapping columns.
10
+ // swapping rows, and swapping columns. It can hold integers (MPInt) or rational
11
+ // numbers (Fraction).
11
12
//
12
13
// ===----------------------------------------------------------------------===//
13
14
14
15
#ifndef MLIR_ANALYSIS_PRESBURGER_MATRIX_H
15
16
#define MLIR_ANALYSIS_PRESBURGER_MATRIX_H
16
17
17
- #include " mlir/Analysis/Presburger/MPInt.h"
18
18
#include " mlir/Support/LLVM.h"
19
+ #include " mlir/Analysis/Presburger/Fraction.h"
20
+ #include " mlir/Analysis/Presburger/Matrix.h"
19
21
#include " llvm/ADT/ArrayRef.h"
20
22
#include " llvm/Support/raw_ostream.h"
21
23
@@ -32,7 +34,12 @@ namespace presburger {
32
34
// / (i, j) is stored at data[i*nReservedColumns + j]. The reserved but unused
33
35
// / columns always have all zero values. The reserved rows are just reserved
34
36
// / space in the underlying SmallVector's capacity.
37
+ // / This class only works for the types MPInt and Fraction, since the method
38
+ // / implementations are in the Matrix.cpp file. Only these two types have
39
+ // / been explicitly instantiated there.
40
+ template <typename T>
35
41
class Matrix {
42
+ static_assert (std::is_same_v<T,MPInt> || std::is_same_v<T,Fraction>, " T must be MPInt or Fraction." );
36
43
public:
37
44
Matrix () = delete ;
38
45
@@ -49,21 +56,21 @@ class Matrix {
49
56
static Matrix identity (unsigned dimension);
50
57
51
58
// / Access the element at the specified row and column.
52
- MPInt &at (unsigned row, unsigned column) {
59
+ T &at (unsigned row, unsigned column) {
53
60
assert (row < nRows && " Row outside of range" );
54
61
assert (column < nColumns && " Column outside of range" );
55
62
return data[row * nReservedColumns + column];
56
63
}
57
64
58
- MPInt at (unsigned row, unsigned column) const {
65
+ T at (unsigned row, unsigned column) const {
59
66
assert (row < nRows && " Row outside of range" );
60
67
assert (column < nColumns && " Column outside of range" );
61
68
return data[row * nReservedColumns + column];
62
69
}
63
70
64
- MPInt &operator ()(unsigned row, unsigned column) { return at (row, column); }
71
+ T &operator ()(unsigned row, unsigned column) { return at (row, column); }
65
72
66
- MPInt operator ()(unsigned row, unsigned column) const {
73
+ T operator ()(unsigned row, unsigned column) const {
67
74
return at (row, column);
68
75
}
69
76
@@ -87,11 +94,11 @@ class Matrix {
87
94
void reserveRows (unsigned rows);
88
95
89
96
// / Get a [Mutable]ArrayRef corresponding to the specified row.
90
- MutableArrayRef<MPInt > getRow (unsigned row);
91
- ArrayRef<MPInt > getRow (unsigned row) const ;
97
+ MutableArrayRef<T > getRow (unsigned row);
98
+ ArrayRef<T > getRow (unsigned row) const ;
92
99
93
100
// / Set the specified row to `elems`.
94
- void setRow (unsigned row, ArrayRef<MPInt > elems);
101
+ void setRow (unsigned row, ArrayRef<T > elems);
95
102
96
103
// / Insert columns having positions pos, pos + 1, ... pos + count - 1.
97
104
// / Columns that were at positions 0 to pos - 1 will stay where they are;
@@ -125,23 +132,23 @@ class Matrix {
125
132
126
133
void copyRow (unsigned sourceRow, unsigned targetRow);
127
134
128
- void fillRow (unsigned row, const MPInt &value);
129
- void fillRow (unsigned row, int64_t value) { fillRow (row, MPInt (value)); }
135
+ void fillRow (unsigned row, const T &value);
136
+ void fillRow (unsigned row, int64_t value) { fillRow (row, T (value)); }
130
137
131
138
// / Add `scale` multiples of the source row to the target row.
132
- void addToRow (unsigned sourceRow, unsigned targetRow, const MPInt &scale);
139
+ void addToRow (unsigned sourceRow, unsigned targetRow, const T &scale);
133
140
void addToRow (unsigned sourceRow, unsigned targetRow, int64_t scale) {
134
- addToRow (sourceRow, targetRow, MPInt (scale));
141
+ addToRow (sourceRow, targetRow, T (scale));
135
142
}
136
143
// / Add `scale` multiples of the rowVec row to the specified row.
137
- void addToRow (unsigned row, ArrayRef<MPInt > rowVec, const MPInt &scale);
144
+ void addToRow (unsigned row, ArrayRef<T > rowVec, const T &scale);
138
145
139
146
// / Add `scale` multiples of the source column to the target column.
140
147
void addToColumn (unsigned sourceColumn, unsigned targetColumn,
141
- const MPInt &scale);
148
+ const T &scale);
142
149
void addToColumn (unsigned sourceColumn, unsigned targetColumn,
143
150
int64_t scale) {
144
- addToColumn (sourceColumn, targetColumn, MPInt (scale));
151
+ addToColumn (sourceColumn, targetColumn, T (scale));
145
152
}
146
153
147
154
// / Negate the specified column.
@@ -150,32 +157,13 @@ class Matrix {
150
157
// / Negate the specified row.
151
158
void negateRow (unsigned row);
152
159
153
- // / Divide the first `nCols` of the specified row by their GCD.
154
- // / Returns the GCD of the first `nCols` of the specified row.
155
- MPInt normalizeRow (unsigned row, unsigned nCols);
156
- // / Divide the columns of the specified row by their GCD.
157
- // / Returns the GCD of the columns of the specified row.
158
- MPInt normalizeRow (unsigned row);
159
-
160
160
// / The given vector is interpreted as a row vector v. Post-multiply v with
161
161
// / this matrix, say M, and return vM.
162
- SmallVector<MPInt , 8 > preMultiplyWithRow (ArrayRef<MPInt > rowVec) const ;
162
+ SmallVector<T , 8 > preMultiplyWithRow (ArrayRef<T > rowVec) const ;
163
163
164
164
// / The given vector is interpreted as a column vector v. Pre-multiply v with
165
165
// / this matrix, say M, and return Mv.
166
- SmallVector<MPInt, 8 > postMultiplyWithColumn (ArrayRef<MPInt> colVec) const ;
167
-
168
- // / Given the current matrix M, returns the matrices H, U such that H is the
169
- // / column hermite normal form of M, i.e. H = M * U, where U is unimodular and
170
- // / the matrix H has the following restrictions:
171
- // / - H is lower triangular.
172
- // / - The leading coefficient (the first non-zero entry from the top, called
173
- // / the pivot) of a non-zero column is always strictly below of the leading
174
- // / coefficient of the column before it; moreover, it is positive.
175
- // / - The elements to the right of the pivots are zero and the elements to
176
- // / the left of the pivots are nonnegative and strictly smaller than the
177
- // / pivot.
178
- std::pair<Matrix, Matrix> computeHermiteNormalForm () const ;
166
+ SmallVector<T, 8 > postMultiplyWithColumn (ArrayRef<T> colVec) const ;
179
167
180
168
// / Resize the matrix to the specified dimensions. If a dimension is smaller,
181
169
// / the values are truncated; if it is bigger, the new values are initialized
@@ -192,7 +180,7 @@ class Matrix {
192
180
unsigned appendExtraRow ();
193
181
// / Same as above, but copy the given elements into the row. The length of
194
182
// / `elems` must be equal to the number of columns.
195
- unsigned appendExtraRow (ArrayRef<MPInt > elems);
183
+ unsigned appendExtraRow (ArrayRef<T > elems);
196
184
197
185
// / Print the matrix.
198
186
void print (raw_ostream &os) const ;
@@ -211,10 +199,52 @@ class Matrix {
211
199
212
200
// / Stores the data. data.size() is equal to nRows * nReservedColumns.
213
201
// / data.capacity() / nReservedColumns is the number of reserved rows.
214
- SmallVector<MPInt, 16 > data;
202
+ SmallVector<T, 16 > data;
203
+ };
204
+
205
+ // An inherited class for integer matrices, with no new data attributes.
206
+ // This is only used for the matrix-related methods which apply only
207
+ // to integers (hermite normal form computation and row normalisation).
208
+ class IntMatrix : public Matrix <MPInt>
209
+ {
210
+ public:
211
+ IntMatrix (unsigned rows, unsigned columns, unsigned reservedRows = 0 ,
212
+ unsigned reservedColumns = 0 ) :
213
+ Matrix<MPInt>(rows, columns, reservedRows, reservedColumns) {};
214
+
215
+ IntMatrix (Matrix<MPInt> m) :
216
+ Matrix<MPInt>(m.getNumRows(), m.getNumColumns(), m.getNumReservedRows(), m.getNumReservedColumns())
217
+ {
218
+ for (unsigned i = 0 ; i < m.getNumRows (); i++)
219
+ for (unsigned j = 0 ; j < m.getNumColumns (); j++)
220
+ at (i, j) = m (i, j);
221
+ };
222
+
223
+ // / Return the identity matrix of the specified dimension.
224
+ static IntMatrix identity (unsigned dimension);
225
+
226
+ // / Given the current matrix M, returns the matrices H, U such that H is the
227
+ // / column hermite normal form of M, i.e. H = M * U, where U is unimodular and
228
+ // / the matrix H has the following restrictions:
229
+ // / - H is lower triangular.
230
+ // / - The leading coefficient (the first non-zero entry from the top, called
231
+ // / the pivot) of a non-zero column is always strictly below of the leading
232
+ // / coefficient of the column before it; moreover, it is positive.
233
+ // / - The elements to the right of the pivots are zero and the elements to
234
+ // / the left of the pivots are nonnegative and strictly smaller than the
235
+ // / pivot.
236
+ std::pair<IntMatrix, IntMatrix> computeHermiteNormalForm () const ;
237
+
238
+ // / Divide the first `nCols` of the specified row by their GCD.
239
+ // / Returns the GCD of the first `nCols` of the specified row.
240
+ MPInt normalizeRow (unsigned row, unsigned nCols);
241
+ // / Divide the columns of the specified row by their GCD.
242
+ // / Returns the GCD of the columns of the specified row.
243
+ MPInt normalizeRow (unsigned row);
244
+
215
245
};
216
246
217
247
} // namespace presburger
218
248
} // namespace mlir
219
249
220
- #endif // MLIR_ANALYSIS_PRESBURGER_MATRIX_H
250
+ #endif // MLIR_ANALYSIS_PRESBURGER_MATRIX_H
0 commit comments