1//===- MatrixTest.cpp - Tests for Matrix ----------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "mlir/Analysis/Presburger/Matrix.h"
10#include "./Utils.h"
11#include "mlir/Analysis/Presburger/Fraction.h"
12#include <gmock/gmock.h>
13#include <gtest/gtest.h>
14
15using namespace mlir;
16using namespace presburger;
17
18TEST(MatrixTest, ReadWrite) {
19 IntMatrix mat(5, 5);
20 for (unsigned row = 0; row < 5; ++row)
21 for (unsigned col = 0; col < 5; ++col)
22 mat(row, col) = 10 * row + col;
23 for (unsigned row = 0; row < 5; ++row)
24 for (unsigned col = 0; col < 5; ++col)
25 EXPECT_EQ(mat(row, col), int(10 * row + col));
26}
27
28TEST(MatrixTest, SwapColumns) {
29 IntMatrix mat(5, 5);
30 for (unsigned row = 0; row < 5; ++row)
31 for (unsigned col = 0; col < 5; ++col)
32 mat(row, col) = col == 3 ? 1 : 0;
33 mat.swapColumns(column: 3, otherColumn: 1);
34 for (unsigned row = 0; row < 5; ++row)
35 for (unsigned col = 0; col < 5; ++col)
36 EXPECT_EQ(mat(row, col), col == 1 ? 1 : 0);
37
38 // swap around all the other columns, swap (1, 3) twice for no effect.
39 mat.swapColumns(column: 3, otherColumn: 1);
40 mat.swapColumns(column: 2, otherColumn: 4);
41 mat.swapColumns(column: 1, otherColumn: 3);
42 mat.swapColumns(column: 0, otherColumn: 4);
43 mat.swapColumns(column: 2, otherColumn: 2);
44
45 for (unsigned row = 0; row < 5; ++row)
46 for (unsigned col = 0; col < 5; ++col)
47 EXPECT_EQ(mat(row, col), col == 1 ? 1 : 0);
48}
49
50TEST(MatrixTest, SwapRows) {
51 IntMatrix mat(5, 5);
52 for (unsigned row = 0; row < 5; ++row)
53 for (unsigned col = 0; col < 5; ++col)
54 mat(row, col) = row == 2 ? 1 : 0;
55 mat.swapRows(row: 2, otherRow: 0);
56 for (unsigned row = 0; row < 5; ++row)
57 for (unsigned col = 0; col < 5; ++col)
58 EXPECT_EQ(mat(row, col), row == 0 ? 1 : 0);
59
60 // swap around all the other rows, swap (2, 0) twice for no effect.
61 mat.swapRows(row: 3, otherRow: 4);
62 mat.swapRows(row: 1, otherRow: 4);
63 mat.swapRows(row: 2, otherRow: 0);
64 mat.swapRows(row: 1, otherRow: 1);
65 mat.swapRows(row: 0, otherRow: 2);
66
67 for (unsigned row = 0; row < 5; ++row)
68 for (unsigned col = 0; col < 5; ++col)
69 EXPECT_EQ(mat(row, col), row == 0 ? 1 : 0);
70}
71
72TEST(MatrixTest, resizeVertically) {
73 IntMatrix mat(5, 5);
74 EXPECT_EQ(mat.getNumRows(), 5u);
75 EXPECT_EQ(mat.getNumColumns(), 5u);
76 for (unsigned row = 0; row < 5; ++row)
77 for (unsigned col = 0; col < 5; ++col)
78 mat(row, col) = 10 * row + col;
79
80 mat.resizeVertically(newNRows: 3);
81 ASSERT_TRUE(mat.hasConsistentState());
82 EXPECT_EQ(mat.getNumRows(), 3u);
83 EXPECT_EQ(mat.getNumColumns(), 5u);
84 for (unsigned row = 0; row < 3; ++row)
85 for (unsigned col = 0; col < 5; ++col)
86 EXPECT_EQ(mat(row, col), int(10 * row + col));
87
88 mat.resizeVertically(newNRows: 5);
89 ASSERT_TRUE(mat.hasConsistentState());
90 EXPECT_EQ(mat.getNumRows(), 5u);
91 EXPECT_EQ(mat.getNumColumns(), 5u);
92 for (unsigned row = 0; row < 5; ++row)
93 for (unsigned col = 0; col < 5; ++col)
94 EXPECT_EQ(mat(row, col), row >= 3 ? 0 : int(10 * row + col));
95}
96
97TEST(MatrixTest, insertColumns) {
98 IntMatrix mat(5, 5, 5, 10);
99 EXPECT_EQ(mat.getNumRows(), 5u);
100 EXPECT_EQ(mat.getNumColumns(), 5u);
101 for (unsigned row = 0; row < 5; ++row)
102 for (unsigned col = 0; col < 5; ++col)
103 mat(row, col) = 10 * row + col;
104
105 mat.insertColumns(pos: 3, count: 100);
106 ASSERT_TRUE(mat.hasConsistentState());
107 EXPECT_EQ(mat.getNumRows(), 5u);
108 EXPECT_EQ(mat.getNumColumns(), 105u);
109 for (unsigned row = 0; row < 5; ++row) {
110 for (unsigned col = 0; col < 105; ++col) {
111 if (col < 3)
112 EXPECT_EQ(mat(row, col), int(10 * row + col));
113 else if (3 <= col && col <= 102)
114 EXPECT_EQ(mat(row, col), 0);
115 else
116 EXPECT_EQ(mat(row, col), int(10 * row + col - 100));
117 }
118 }
119
120 mat.removeColumns(pos: 3, count: 100);
121 ASSERT_TRUE(mat.hasConsistentState());
122 mat.insertColumns(pos: 0, count: 0);
123 ASSERT_TRUE(mat.hasConsistentState());
124 mat.insertColumn(pos: 5);
125 ASSERT_TRUE(mat.hasConsistentState());
126
127 EXPECT_EQ(mat.getNumRows(), 5u);
128 EXPECT_EQ(mat.getNumColumns(), 6u);
129 for (unsigned row = 0; row < 5; ++row)
130 for (unsigned col = 0; col < 6; ++col)
131 EXPECT_EQ(mat(row, col), col == 5 ? 0 : 10 * row + col);
132}
133
134TEST(MatrixTest, insertRows) {
135 IntMatrix mat(5, 5, 5, 10);
136 ASSERT_TRUE(mat.hasConsistentState());
137 EXPECT_EQ(mat.getNumRows(), 5u);
138 EXPECT_EQ(mat.getNumColumns(), 5u);
139 for (unsigned row = 0; row < 5; ++row)
140 for (unsigned col = 0; col < 5; ++col)
141 mat(row, col) = 10 * row + col;
142
143 mat.insertRows(pos: 3, count: 100);
144 ASSERT_TRUE(mat.hasConsistentState());
145 EXPECT_EQ(mat.getNumRows(), 105u);
146 EXPECT_EQ(mat.getNumColumns(), 5u);
147 for (unsigned row = 0; row < 105; ++row) {
148 for (unsigned col = 0; col < 5; ++col) {
149 if (row < 3)
150 EXPECT_EQ(mat(row, col), int(10 * row + col));
151 else if (3 <= row && row <= 102)
152 EXPECT_EQ(mat(row, col), 0);
153 else
154 EXPECT_EQ(mat(row, col), int(10 * (row - 100) + col));
155 }
156 }
157
158 mat.removeRows(pos: 3, count: 100);
159 ASSERT_TRUE(mat.hasConsistentState());
160 mat.insertRows(pos: 0, count: 0);
161 ASSERT_TRUE(mat.hasConsistentState());
162 mat.insertRow(pos: 5);
163 ASSERT_TRUE(mat.hasConsistentState());
164
165 EXPECT_EQ(mat.getNumRows(), 6u);
166 EXPECT_EQ(mat.getNumColumns(), 5u);
167 for (unsigned row = 0; row < 6; ++row)
168 for (unsigned col = 0; col < 5; ++col)
169 EXPECT_EQ(mat(row, col), row == 5 ? 0 : 10 * row + col);
170}
171
172TEST(MatrixTest, resize) {
173 IntMatrix mat(5, 5);
174 EXPECT_EQ(mat.getNumRows(), 5u);
175 EXPECT_EQ(mat.getNumColumns(), 5u);
176 for (unsigned row = 0; row < 5; ++row)
177 for (unsigned col = 0; col < 5; ++col)
178 mat(row, col) = 10 * row + col;
179
180 mat.resize(newNRows: 3, newNColumns: 3);
181 ASSERT_TRUE(mat.hasConsistentState());
182 EXPECT_EQ(mat.getNumRows(), 3u);
183 EXPECT_EQ(mat.getNumColumns(), 3u);
184 for (unsigned row = 0; row < 3; ++row)
185 for (unsigned col = 0; col < 3; ++col)
186 EXPECT_EQ(mat(row, col), int(10 * row + col));
187
188 mat.resize(newNRows: 7, newNColumns: 7);
189 ASSERT_TRUE(mat.hasConsistentState());
190 EXPECT_EQ(mat.getNumRows(), 7u);
191 EXPECT_EQ(mat.getNumColumns(), 7u);
192 for (unsigned row = 0; row < 7; ++row)
193 for (unsigned col = 0; col < 7; ++col)
194 EXPECT_EQ(mat(row, col), row >= 3 || col >= 3 ? 0 : int(10 * row + col));
195}
196
197template <typename T>
198static void checkMatEqual(const Matrix<T> m1, const Matrix<T> m2) {
199 EXPECT_EQ(m1.getNumRows(), m2.getNumRows());
200 EXPECT_EQ(m1.getNumColumns(), m2.getNumColumns());
201
202 for (unsigned row = 0, rows = m1.getNumRows(); row < rows; ++row)
203 for (unsigned col = 0, cols = m1.getNumColumns(); col < cols; ++col)
204 EXPECT_EQ(m1(row, col), m2(row, col));
205}
206
207static void checkHermiteNormalForm(const IntMatrix &mat,
208 const IntMatrix &hermiteForm) {
209 auto [h, u] = mat.computeHermiteNormalForm();
210
211 checkMatEqual(m1: h, m2: hermiteForm);
212}
213
214TEST(MatrixTest, computeHermiteNormalForm) {
215 // TODO: Add a check to test the original statement of hermite normal form
216 // instead of using a precomputed result.
217
218 {
219 // Hermite form of a unimodular matrix is the identity matrix.
220 IntMatrix mat = makeIntMatrix(numRow: 3, numColumns: 3, matrix: {{2, 3, 6}, {3, 2, 3}, {17, 11, 16}});
221 IntMatrix hermiteForm =
222 makeIntMatrix(numRow: 3, numColumns: 3, matrix: {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}});
223 checkHermiteNormalForm(mat, hermiteForm);
224 }
225
226 {
227 // Hermite form of a unimodular is the identity matrix.
228 IntMatrix mat = makeIntMatrix(
229 numRow: 4, numColumns: 4,
230 matrix: {{-6, -1, -19, -20}, {0, 1, 0, 0}, {-5, 0, -15, -16}, {6, 0, 18, 19}});
231 IntMatrix hermiteForm = makeIntMatrix(
232 numRow: 4, numColumns: 4, matrix: {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}});
233 checkHermiteNormalForm(mat, hermiteForm);
234 }
235
236 {
237 IntMatrix mat = makeIntMatrix(
238 numRow: 4, numColumns: 4, matrix: {{3, 3, 1, 4}, {0, 1, 0, 0}, {0, 0, 19, 16}, {0, 0, 0, 3}});
239 IntMatrix hermiteForm = makeIntMatrix(
240 numRow: 4, numColumns: 4, matrix: {{1, 0, 0, 0}, {0, 1, 0, 0}, {1, 0, 3, 0}, {18, 0, 54, 57}});
241 checkHermiteNormalForm(mat, hermiteForm);
242 }
243
244 {
245 IntMatrix mat = makeIntMatrix(
246 numRow: 4, numColumns: 4, matrix: {{3, 3, 1, 4}, {0, 1, 0, 0}, {0, 0, 19, 16}, {0, 0, 0, 3}});
247 IntMatrix hermiteForm = makeIntMatrix(
248 numRow: 4, numColumns: 4, matrix: {{1, 0, 0, 0}, {0, 1, 0, 0}, {1, 0, 3, 0}, {18, 0, 54, 57}});
249 checkHermiteNormalForm(mat, hermiteForm);
250 }
251
252 {
253 IntMatrix mat = makeIntMatrix(
254 numRow: 3, numColumns: 5, matrix: {{0, 2, 0, 7, 1}, {-1, 0, 0, -3, 0}, {0, 4, 1, 0, 8}});
255 IntMatrix hermiteForm = makeIntMatrix(
256 numRow: 3, numColumns: 5, matrix: {{1, 0, 0, 0, 0}, {0, 1, 0, 0, 0}, {0, 0, 1, 0, 0}});
257 checkHermiteNormalForm(mat, hermiteForm);
258 }
259}
260
261TEST(MatrixTest, inverse) {
262 IntMatrix mat1 = makeIntMatrix(numRow: 2, numColumns: 2, matrix: {{2, 1}, {7, 0}});
263 EXPECT_EQ(mat1.determinant(), -7);
264
265 FracMatrix mat = makeFracMatrix(
266 numRow: 2, numColumns: 2, matrix: {{Fraction(2), Fraction(1)}, {Fraction(7), Fraction(0)}});
267 FracMatrix inverse = makeFracMatrix(
268 numRow: 2, numColumns: 2, matrix: {{Fraction(0), Fraction(1, 7)}, {Fraction(1), Fraction(-2, 7)}});
269
270 FracMatrix inv(2, 2);
271 mat.determinant(inverse: &inv);
272
273 EXPECT_EQ_FRAC_MATRIX(a: inv, b: inverse);
274
275 mat = makeFracMatrix(
276 numRow: 2, numColumns: 2, matrix: {{Fraction(0), Fraction(1)}, {Fraction(0), Fraction(2)}});
277 Fraction det = mat.determinant(inverse: nullptr);
278
279 EXPECT_EQ(det, Fraction(0));
280
281 mat = makeFracMatrix(numRow: 3, numColumns: 3,
282 matrix: {{Fraction(1), Fraction(2), Fraction(3)},
283 {Fraction(4), Fraction(8), Fraction(6)},
284 {Fraction(7), Fraction(8), Fraction(6)}});
285 inverse = makeFracMatrix(numRow: 3, numColumns: 3,
286 matrix: {{Fraction(0), Fraction(-1, 3), Fraction(1, 3)},
287 {Fraction(-1, 2), Fraction(5, 12), Fraction(-1, 6)},
288 {Fraction(2, 3), Fraction(-1, 6), Fraction(0)}});
289
290 mat.determinant(inverse: &inv);
291 EXPECT_EQ_FRAC_MATRIX(a: inv, b: inverse);
292
293 mat = makeFracMatrix(numRow: 0, numColumns: 0, matrix: {});
294 mat.determinant(inverse: &inv);
295}
296
297TEST(MatrixTest, intInverse) {
298 IntMatrix mat = makeIntMatrix(numRow: 2, numColumns: 2, matrix: {{2, 1}, {7, 0}});
299 IntMatrix inverse = makeIntMatrix(numRow: 2, numColumns: 2, matrix: {{0, -1}, {-7, 2}});
300
301 IntMatrix inv(2, 2);
302 mat.determinant(inverse: &inv);
303
304 EXPECT_EQ_INT_MATRIX(a: inv, b: inverse);
305
306 mat = makeIntMatrix(
307 numRow: 4, numColumns: 4, matrix: {{4, 14, 11, 3}, {13, 5, 14, 12}, {13, 9, 7, 14}, {2, 3, 12, 7}});
308 inverse = makeIntMatrix(numRow: 4, numColumns: 4,
309 matrix: {{155, 1636, -579, -1713},
310 {725, -743, 537, -111},
311 {210, 735, -855, 360},
312 {-715, -1409, 1401, 1482}});
313
314 mat.determinant(inverse: &inv);
315
316 EXPECT_EQ_INT_MATRIX(a: inv, b: inverse);
317
318 mat = makeIntMatrix(numRow: 2, numColumns: 2, matrix: {{0, 0}, {1, 2}});
319
320 MPInt det = mat.determinant(inverse: &inv);
321
322 EXPECT_EQ(det, 0);
323}
324
325TEST(MatrixTest, gramSchmidt) {
326 FracMatrix mat =
327 makeFracMatrix(numRow: 3, numColumns: 5,
328 matrix: {{Fraction(3, 1), Fraction(4, 1), Fraction(5, 1),
329 Fraction(12, 1), Fraction(19, 1)},
330 {Fraction(4, 1), Fraction(5, 1), Fraction(6, 1),
331 Fraction(13, 1), Fraction(20, 1)},
332 {Fraction(7, 1), Fraction(8, 1), Fraction(9, 1),
333 Fraction(16, 1), Fraction(24, 1)}});
334
335 FracMatrix gramSchmidt = makeFracMatrix(
336 numRow: 3, numColumns: 5,
337 matrix: {{Fraction(3, 1), Fraction(4, 1), Fraction(5, 1), Fraction(12, 1),
338 Fraction(19, 1)},
339 {Fraction(142, 185), Fraction(383, 555), Fraction(68, 111),
340 Fraction(13, 185), Fraction(-262, 555)},
341 {Fraction(53, 463), Fraction(27, 463), Fraction(1, 463),
342 Fraction(-181, 463), Fraction(100, 463)}});
343
344 FracMatrix gs = mat.gramSchmidt();
345
346 EXPECT_EQ_FRAC_MATRIX(a: gs, b: gramSchmidt);
347 for (unsigned i = 0; i < 3u; i++)
348 for (unsigned j = i + 1; j < 3u; j++)
349 EXPECT_EQ(dotProduct(gs.getRow(i), gs.getRow(j)), 0);
350
351 mat = makeFracMatrix(numRow: 3, numColumns: 3,
352 matrix: {{Fraction(20, 1), Fraction(17, 1), Fraction(10, 1)},
353 {Fraction(20, 1), Fraction(18, 1), Fraction(6, 1)},
354 {Fraction(15, 1), Fraction(14, 1), Fraction(10, 1)}});
355
356 gramSchmidt = makeFracMatrix(
357 numRow: 3, numColumns: 3,
358 matrix: {{Fraction(20, 1), Fraction(17, 1), Fraction(10, 1)},
359 {Fraction(460, 789), Fraction(1180, 789), Fraction(-2926, 789)},
360 {Fraction(-2925, 3221), Fraction(3000, 3221), Fraction(750, 3221)}});
361
362 gs = mat.gramSchmidt();
363
364 EXPECT_EQ_FRAC_MATRIX(a: gs, b: gramSchmidt);
365 for (unsigned i = 0; i < 3u; i++)
366 for (unsigned j = i + 1; j < 3u; j++)
367 EXPECT_EQ(dotProduct(gs.getRow(i), gs.getRow(j)), 0);
368
369 mat = makeFracMatrix(
370 numRow: 4, numColumns: 4,
371 matrix: {{Fraction(1, 26), Fraction(13, 12), Fraction(34, 13), Fraction(7, 10)},
372 {Fraction(40, 23), Fraction(34, 1), Fraction(11, 19), Fraction(15, 1)},
373 {Fraction(21, 22), Fraction(10, 9), Fraction(4, 11), Fraction(14, 11)},
374 {Fraction(35, 22), Fraction(1, 15), Fraction(5, 8), Fraction(30, 1)}});
375
376 gs = mat.gramSchmidt();
377
378 // The integers involved are too big to construct the actual matrix.
379 // but we can check that the result is linearly independent.
380 ASSERT_FALSE(mat.determinant(nullptr) == 0);
381
382 for (unsigned i = 0; i < 4u; i++)
383 for (unsigned j = i + 1; j < 4u; j++)
384 EXPECT_EQ(dotProduct(gs.getRow(i), gs.getRow(j)), 0);
385
386 mat = FracMatrix::identity(/*dim=*/dimension: 10);
387
388 gs = mat.gramSchmidt();
389
390 EXPECT_EQ_FRAC_MATRIX(a: gs, b: FracMatrix::identity(dimension: 10));
391}
392
393void checkReducedBasis(FracMatrix mat, Fraction delta) {
394 FracMatrix gsOrth = mat.gramSchmidt();
395
396 // Size-reduced check.
397 for (unsigned i = 0, e = mat.getNumRows(); i < e; i++) {
398 for (unsigned j = 0; j < i; j++) {
399 Fraction mu = dotProduct(a: mat.getRow(row: i), b: gsOrth.getRow(row: j)) /
400 dotProduct(a: gsOrth.getRow(row: j), b: gsOrth.getRow(row: j));
401 EXPECT_TRUE(abs(mu) <= Fraction(1, 2));
402 }
403 }
404
405 // Lovasz condition check.
406 for (unsigned i = 1, e = mat.getNumRows(); i < e; i++) {
407 Fraction mu = dotProduct(a: mat.getRow(row: i), b: gsOrth.getRow(row: i - 1)) /
408 dotProduct(a: gsOrth.getRow(row: i - 1), b: gsOrth.getRow(row: i - 1));
409 EXPECT_TRUE(dotProduct(mat.getRow(i), mat.getRow(i)) >
410 (delta - mu * mu) *
411 dotProduct(gsOrth.getRow(i - 1), gsOrth.getRow(i - 1)));
412 }
413}
414
415TEST(MatrixTest, LLL) {
416 FracMatrix mat =
417 makeFracMatrix(numRow: 3, numColumns: 3,
418 matrix: {{Fraction(1, 1), Fraction(1, 1), Fraction(1, 1)},
419 {Fraction(-1, 1), Fraction(0, 1), Fraction(2, 1)},
420 {Fraction(3, 1), Fraction(5, 1), Fraction(6, 1)}});
421 mat.LLL(delta: Fraction(3, 4));
422
423 checkReducedBasis(mat, delta: Fraction(3, 4));
424
425 mat = makeFracMatrix(
426 numRow: 2, numColumns: 2,
427 matrix: {{Fraction(12, 1), Fraction(2, 1)}, {Fraction(13, 1), Fraction(4, 1)}});
428 mat.LLL(delta: Fraction(3, 4));
429
430 checkReducedBasis(mat, delta: Fraction(3, 4));
431
432 mat = makeFracMatrix(numRow: 3, numColumns: 3,
433 matrix: {{Fraction(1, 1), Fraction(0, 1), Fraction(2, 1)},
434 {Fraction(0, 1), Fraction(1, 3), -Fraction(5, 3)},
435 {Fraction(0, 1), Fraction(0, 1), Fraction(1, 1)}});
436 mat.LLL(delta: Fraction(3, 4));
437
438 checkReducedBasis(mat, delta: Fraction(3, 4));
439}
440
441TEST(MatrixTest, moveColumns) {
442 IntMatrix mat =
443 makeIntMatrix(numRow: 3, numColumns: 4, matrix: {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 4, 2}});
444
445 {
446 IntMatrix movedMat =
447 makeIntMatrix(numRow: 3, numColumns: 4, matrix: {{0, 3, 1, 2}, {4, 7, 5, 6}, {8, 2, 9, 4}});
448
449 movedMat.moveColumns(srcPos: 2, num: 2, dstPos: 1);
450 checkMatEqual(m1: mat, m2: movedMat);
451 }
452
453 {
454 IntMatrix movedMat =
455 makeIntMatrix(numRow: 3, numColumns: 4, matrix: {{0, 3, 1, 2}, {4, 7, 5, 6}, {8, 2, 9, 4}});
456
457 movedMat.moveColumns(srcPos: 1, num: 1, dstPos: 3);
458 checkMatEqual(m1: mat, m2: movedMat);
459 }
460
461 {
462 IntMatrix movedMat =
463 makeIntMatrix(numRow: 3, numColumns: 4, matrix: {{1, 2, 0, 3}, {5, 6, 4, 7}, {9, 4, 8, 2}});
464
465 movedMat.moveColumns(srcPos: 0, num: 2, dstPos: 1);
466 checkMatEqual(m1: mat, m2: movedMat);
467 }
468
469 {
470 IntMatrix movedMat =
471 makeIntMatrix(numRow: 3, numColumns: 4, matrix: {{1, 0, 2, 3}, {5, 4, 6, 7}, {9, 8, 4, 2}});
472
473 movedMat.moveColumns(srcPos: 0, num: 1, dstPos: 1);
474 checkMatEqual(m1: mat, m2: movedMat);
475 }
476}
477

source code of mlir/unittests/Analysis/Presburger/MatrixTest.cpp