110a898b3SArjun P //===- MatrixTest.cpp - Tests for Matrix ----------------------------------===//
210a898b3SArjun P //
310a898b3SArjun P // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
410a898b3SArjun P // See https://llvm.org/LICENSE.txt for license information.
510a898b3SArjun P // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
610a898b3SArjun P //
710a898b3SArjun P //===----------------------------------------------------------------------===//
810a898b3SArjun P
910a898b3SArjun P #include "mlir/Analysis/Presburger/Matrix.h"
10b696e25aSGroverkss #include "./Utils.h"
11f08fe1f1SAbhinav271828 #include "mlir/Analysis/Presburger/Fraction.h"
1210a898b3SArjun P #include <gmock/gmock.h>
1310a898b3SArjun P #include <gtest/gtest.h>
1410a898b3SArjun P
150c1f6865SGroverkss using namespace mlir;
160c1f6865SGroverkss using namespace presburger;
1710a898b3SArjun P
TEST(MatrixTest,ReadWrite)1810a898b3SArjun P TEST(MatrixTest, ReadWrite) {
19c1b99746SAbhinav271828 IntMatrix mat(5, 5);
2010a898b3SArjun P for (unsigned row = 0; row < 5; ++row)
2110a898b3SArjun P for (unsigned col = 0; col < 5; ++col)
2210a898b3SArjun P mat(row, col) = 10 * row + col;
2310a898b3SArjun P for (unsigned row = 0; row < 5; ++row)
2410a898b3SArjun P for (unsigned col = 0; col < 5; ++col)
2510a898b3SArjun P EXPECT_EQ(mat(row, col), int(10 * row + col));
2610a898b3SArjun P }
2710a898b3SArjun P
TEST(MatrixTest,SwapColumns)2810a898b3SArjun P TEST(MatrixTest, SwapColumns) {
29c1b99746SAbhinav271828 IntMatrix mat(5, 5);
3010a898b3SArjun P for (unsigned row = 0; row < 5; ++row)
3110a898b3SArjun P for (unsigned col = 0; col < 5; ++col)
3210a898b3SArjun P mat(row, col) = col == 3 ? 1 : 0;
3310a898b3SArjun P mat.swapColumns(3, 1);
3410a898b3SArjun P for (unsigned row = 0; row < 5; ++row)
3510a898b3SArjun P for (unsigned col = 0; col < 5; ++col)
3610a898b3SArjun P EXPECT_EQ(mat(row, col), col == 1 ? 1 : 0);
3710a898b3SArjun P
3810a898b3SArjun P // swap around all the other columns, swap (1, 3) twice for no effect.
3910a898b3SArjun P mat.swapColumns(3, 1);
4010a898b3SArjun P mat.swapColumns(2, 4);
4110a898b3SArjun P mat.swapColumns(1, 3);
4210a898b3SArjun P mat.swapColumns(0, 4);
4310a898b3SArjun P mat.swapColumns(2, 2);
4410a898b3SArjun P
4510a898b3SArjun P for (unsigned row = 0; row < 5; ++row)
4610a898b3SArjun P for (unsigned col = 0; col < 5; ++col)
4710a898b3SArjun P EXPECT_EQ(mat(row, col), col == 1 ? 1 : 0);
4810a898b3SArjun P }
4910a898b3SArjun P
TEST(MatrixTest,SwapRows)5010a898b3SArjun P TEST(MatrixTest, SwapRows) {
51c1b99746SAbhinav271828 IntMatrix mat(5, 5);
5210a898b3SArjun P for (unsigned row = 0; row < 5; ++row)
5310a898b3SArjun P for (unsigned col = 0; col < 5; ++col)
5410a898b3SArjun P mat(row, col) = row == 2 ? 1 : 0;
5510a898b3SArjun P mat.swapRows(2, 0);
5610a898b3SArjun P for (unsigned row = 0; row < 5; ++row)
5710a898b3SArjun P for (unsigned col = 0; col < 5; ++col)
5810a898b3SArjun P EXPECT_EQ(mat(row, col), row == 0 ? 1 : 0);
5910a898b3SArjun P
6010a898b3SArjun P // swap around all the other rows, swap (2, 0) twice for no effect.
6110a898b3SArjun P mat.swapRows(3, 4);
6210a898b3SArjun P mat.swapRows(1, 4);
6310a898b3SArjun P mat.swapRows(2, 0);
6410a898b3SArjun P mat.swapRows(1, 1);
6510a898b3SArjun P mat.swapRows(0, 2);
6610a898b3SArjun P
6710a898b3SArjun P for (unsigned row = 0; row < 5; ++row)
6810a898b3SArjun P for (unsigned col = 0; col < 5; ++col)
6910a898b3SArjun P EXPECT_EQ(mat(row, col), row == 0 ? 1 : 0);
7010a898b3SArjun P }
7110a898b3SArjun P
TEST(MatrixTest,resizeVertically)7210a898b3SArjun P TEST(MatrixTest, resizeVertically) {
73c1b99746SAbhinav271828 IntMatrix mat(5, 5);
7410a898b3SArjun P EXPECT_EQ(mat.getNumRows(), 5u);
7510a898b3SArjun P EXPECT_EQ(mat.getNumColumns(), 5u);
7610a898b3SArjun P for (unsigned row = 0; row < 5; ++row)
7710a898b3SArjun P for (unsigned col = 0; col < 5; ++col)
7810a898b3SArjun P mat(row, col) = 10 * row + col;
7910a898b3SArjun P
8010a898b3SArjun P mat.resizeVertically(3);
81c605dfcfSArjun P ASSERT_TRUE(mat.hasConsistentState());
8210a898b3SArjun P EXPECT_EQ(mat.getNumRows(), 3u);
8310a898b3SArjun P EXPECT_EQ(mat.getNumColumns(), 5u);
8410a898b3SArjun P for (unsigned row = 0; row < 3; ++row)
8510a898b3SArjun P for (unsigned col = 0; col < 5; ++col)
8610a898b3SArjun P EXPECT_EQ(mat(row, col), int(10 * row + col));
8710a898b3SArjun P
8810a898b3SArjun P mat.resizeVertically(5);
89c605dfcfSArjun P ASSERT_TRUE(mat.hasConsistentState());
9010a898b3SArjun P EXPECT_EQ(mat.getNumRows(), 5u);
9110a898b3SArjun P EXPECT_EQ(mat.getNumColumns(), 5u);
9210a898b3SArjun P for (unsigned row = 0; row < 5; ++row)
9310a898b3SArjun P for (unsigned col = 0; col < 5; ++col)
9410a898b3SArjun P EXPECT_EQ(mat(row, col), row >= 3 ? 0 : int(10 * row + col));
9510a898b3SArjun P }
9610a898b3SArjun P
TEST(MatrixTest,insertColumns)97c605dfcfSArjun P TEST(MatrixTest, insertColumns) {
98c1b99746SAbhinav271828 IntMatrix mat(5, 5, 5, 10);
99c605dfcfSArjun P EXPECT_EQ(mat.getNumRows(), 5u);
100c605dfcfSArjun P EXPECT_EQ(mat.getNumColumns(), 5u);
101c605dfcfSArjun P for (unsigned row = 0; row < 5; ++row)
102c605dfcfSArjun P for (unsigned col = 0; col < 5; ++col)
103c605dfcfSArjun P mat(row, col) = 10 * row + col;
104c605dfcfSArjun P
105c605dfcfSArjun P mat.insertColumns(3, 100);
106c605dfcfSArjun P ASSERT_TRUE(mat.hasConsistentState());
107c605dfcfSArjun P EXPECT_EQ(mat.getNumRows(), 5u);
108c605dfcfSArjun P EXPECT_EQ(mat.getNumColumns(), 105u);
109c605dfcfSArjun P for (unsigned row = 0; row < 5; ++row) {
110c605dfcfSArjun P for (unsigned col = 0; col < 105; ++col) {
111c605dfcfSArjun P if (col < 3)
112c605dfcfSArjun P EXPECT_EQ(mat(row, col), int(10 * row + col));
113c605dfcfSArjun P else if (3 <= col && col <= 102)
114c605dfcfSArjun P EXPECT_EQ(mat(row, col), 0);
115c605dfcfSArjun P else
116c605dfcfSArjun P EXPECT_EQ(mat(row, col), int(10 * row + col - 100));
117c605dfcfSArjun P }
118c605dfcfSArjun P }
119c605dfcfSArjun P
120c605dfcfSArjun P mat.removeColumns(3, 100);
121c605dfcfSArjun P ASSERT_TRUE(mat.hasConsistentState());
122c605dfcfSArjun P mat.insertColumns(0, 0);
123c605dfcfSArjun P ASSERT_TRUE(mat.hasConsistentState());
124c605dfcfSArjun P mat.insertColumn(5);
125c605dfcfSArjun P ASSERT_TRUE(mat.hasConsistentState());
126c605dfcfSArjun P
127c605dfcfSArjun P EXPECT_EQ(mat.getNumRows(), 5u);
128c605dfcfSArjun P EXPECT_EQ(mat.getNumColumns(), 6u);
129c605dfcfSArjun P for (unsigned row = 0; row < 5; ++row)
130c605dfcfSArjun P for (unsigned col = 0; col < 6; ++col)
131c605dfcfSArjun P EXPECT_EQ(mat(row, col), col == 5 ? 0 : 10 * row + col);
132c605dfcfSArjun P }
133c605dfcfSArjun P
TEST(MatrixTest,insertRows)134c605dfcfSArjun P TEST(MatrixTest, insertRows) {
135c1b99746SAbhinav271828 IntMatrix mat(5, 5, 5, 10);
136c605dfcfSArjun P ASSERT_TRUE(mat.hasConsistentState());
137c605dfcfSArjun P EXPECT_EQ(mat.getNumRows(), 5u);
138c605dfcfSArjun P EXPECT_EQ(mat.getNumColumns(), 5u);
139c605dfcfSArjun P for (unsigned row = 0; row < 5; ++row)
140c605dfcfSArjun P for (unsigned col = 0; col < 5; ++col)
141c605dfcfSArjun P mat(row, col) = 10 * row + col;
142c605dfcfSArjun P
143c605dfcfSArjun P mat.insertRows(3, 100);
144c605dfcfSArjun P ASSERT_TRUE(mat.hasConsistentState());
145c605dfcfSArjun P EXPECT_EQ(mat.getNumRows(), 105u);
146c605dfcfSArjun P EXPECT_EQ(mat.getNumColumns(), 5u);
147c605dfcfSArjun P for (unsigned row = 0; row < 105; ++row) {
148c605dfcfSArjun P for (unsigned col = 0; col < 5; ++col) {
149c605dfcfSArjun P if (row < 3)
150c605dfcfSArjun P EXPECT_EQ(mat(row, col), int(10 * row + col));
151c605dfcfSArjun P else if (3 <= row && row <= 102)
152c605dfcfSArjun P EXPECT_EQ(mat(row, col), 0);
153c605dfcfSArjun P else
154c605dfcfSArjun P EXPECT_EQ(mat(row, col), int(10 * (row - 100) + col));
155c605dfcfSArjun P }
156c605dfcfSArjun P }
157c605dfcfSArjun P
158c605dfcfSArjun P mat.removeRows(3, 100);
159c605dfcfSArjun P ASSERT_TRUE(mat.hasConsistentState());
160c605dfcfSArjun P mat.insertRows(0, 0);
161c605dfcfSArjun P ASSERT_TRUE(mat.hasConsistentState());
162c605dfcfSArjun P mat.insertRow(5);
163c605dfcfSArjun P ASSERT_TRUE(mat.hasConsistentState());
164c605dfcfSArjun P
165c605dfcfSArjun P EXPECT_EQ(mat.getNumRows(), 6u);
166c605dfcfSArjun P EXPECT_EQ(mat.getNumColumns(), 5u);
167c605dfcfSArjun P for (unsigned row = 0; row < 6; ++row)
168c605dfcfSArjun P for (unsigned col = 0; col < 5; ++col)
169c605dfcfSArjun P EXPECT_EQ(mat(row, col), row == 5 ? 0 : 10 * row + col);
170c605dfcfSArjun P }
171c605dfcfSArjun P
TEST(MatrixTest,resize)172f263ea15SArjun P TEST(MatrixTest, resize) {
173c1b99746SAbhinav271828 IntMatrix mat(5, 5);
174f263ea15SArjun P EXPECT_EQ(mat.getNumRows(), 5u);
175f263ea15SArjun P EXPECT_EQ(mat.getNumColumns(), 5u);
176f263ea15SArjun P for (unsigned row = 0; row < 5; ++row)
177f263ea15SArjun P for (unsigned col = 0; col < 5; ++col)
178f263ea15SArjun P mat(row, col) = 10 * row + col;
179f263ea15SArjun P
180f263ea15SArjun P mat.resize(3, 3);
181f263ea15SArjun P ASSERT_TRUE(mat.hasConsistentState());
182f263ea15SArjun P EXPECT_EQ(mat.getNumRows(), 3u);
183f263ea15SArjun P EXPECT_EQ(mat.getNumColumns(), 3u);
184f263ea15SArjun P for (unsigned row = 0; row < 3; ++row)
185f263ea15SArjun P for (unsigned col = 0; col < 3; ++col)
186f263ea15SArjun P EXPECT_EQ(mat(row, col), int(10 * row + col));
187f263ea15SArjun P
188f263ea15SArjun P mat.resize(7, 7);
189f263ea15SArjun P ASSERT_TRUE(mat.hasConsistentState());
190f263ea15SArjun P EXPECT_EQ(mat.getNumRows(), 7u);
191f263ea15SArjun P EXPECT_EQ(mat.getNumColumns(), 7u);
192f263ea15SArjun P for (unsigned row = 0; row < 7; ++row)
193f263ea15SArjun P for (unsigned col = 0; col < 7; ++col)
194f263ea15SArjun P EXPECT_EQ(mat(row, col), row >= 3 || col >= 3 ? 0 : int(10 * row + col));
195f263ea15SArjun P }
196b696e25aSGroverkss
19766786a79SBharathi Ramana Joshi template <typename T>
checkMatEqual(const Matrix<T> m1,const Matrix<T> m2)19866786a79SBharathi Ramana Joshi static void checkMatEqual(const Matrix<T> m1, const Matrix<T> m2) {
19966786a79SBharathi Ramana Joshi EXPECT_EQ(m1.getNumRows(), m2.getNumRows());
20066786a79SBharathi Ramana Joshi EXPECT_EQ(m1.getNumColumns(), m2.getNumColumns());
20166786a79SBharathi Ramana Joshi
20266786a79SBharathi Ramana Joshi for (unsigned row = 0, rows = m1.getNumRows(); row < rows; ++row)
20366786a79SBharathi Ramana Joshi for (unsigned col = 0, cols = m1.getNumColumns(); col < cols; ++col)
20466786a79SBharathi Ramana Joshi EXPECT_EQ(m1(row, col), m2(row, col));
20566786a79SBharathi Ramana Joshi }
20666786a79SBharathi Ramana Joshi
checkHermiteNormalForm(const IntMatrix & mat,const IntMatrix & hermiteForm)207c1b99746SAbhinav271828 static void checkHermiteNormalForm(const IntMatrix &mat,
208c1b99746SAbhinav271828 const IntMatrix &hermiteForm) {
209b696e25aSGroverkss auto [h, u] = mat.computeHermiteNormalForm();
210b696e25aSGroverkss
21166786a79SBharathi Ramana Joshi checkMatEqual(h, hermiteForm);
212b696e25aSGroverkss }
213b696e25aSGroverkss
TEST(MatrixTest,computeHermiteNormalForm)214b696e25aSGroverkss TEST(MatrixTest, computeHermiteNormalForm) {
215b696e25aSGroverkss // TODO: Add a check to test the original statement of hermite normal form
216b696e25aSGroverkss // instead of using a precomputed result.
217b696e25aSGroverkss
218b696e25aSGroverkss {
219b696e25aSGroverkss // Hermite form of a unimodular matrix is the identity matrix.
220c1b99746SAbhinav271828 IntMatrix mat = makeIntMatrix(3, 3, {{2, 3, 6}, {3, 2, 3}, {17, 11, 16}});
221f08fe1f1SAbhinav271828 IntMatrix hermiteForm =
222f08fe1f1SAbhinav271828 makeIntMatrix(3, 3, {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}});
223b696e25aSGroverkss checkHermiteNormalForm(mat, hermiteForm);
224b696e25aSGroverkss }
225b696e25aSGroverkss
226b696e25aSGroverkss {
227b696e25aSGroverkss // Hermite form of a unimodular is the identity matrix.
228c1b99746SAbhinav271828 IntMatrix mat = makeIntMatrix(
229b696e25aSGroverkss 4, 4,
230b696e25aSGroverkss {{-6, -1, -19, -20}, {0, 1, 0, 0}, {-5, 0, -15, -16}, {6, 0, 18, 19}});
231c1b99746SAbhinav271828 IntMatrix hermiteForm = makeIntMatrix(
232b696e25aSGroverkss 4, 4, {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}});
233b696e25aSGroverkss checkHermiteNormalForm(mat, hermiteForm);
234b696e25aSGroverkss }
235b696e25aSGroverkss
236b696e25aSGroverkss {
237c1b99746SAbhinav271828 IntMatrix mat = makeIntMatrix(
238b696e25aSGroverkss 4, 4, {{3, 3, 1, 4}, {0, 1, 0, 0}, {0, 0, 19, 16}, {0, 0, 0, 3}});
239c1b99746SAbhinav271828 IntMatrix hermiteForm = makeIntMatrix(
240b696e25aSGroverkss 4, 4, {{1, 0, 0, 0}, {0, 1, 0, 0}, {1, 0, 3, 0}, {18, 0, 54, 57}});
241b696e25aSGroverkss checkHermiteNormalForm(mat, hermiteForm);
242b696e25aSGroverkss }
243b696e25aSGroverkss
244b696e25aSGroverkss {
245c1b99746SAbhinav271828 IntMatrix mat = makeIntMatrix(
246b696e25aSGroverkss 4, 4, {{3, 3, 1, 4}, {0, 1, 0, 0}, {0, 0, 19, 16}, {0, 0, 0, 3}});
247c1b99746SAbhinav271828 IntMatrix hermiteForm = makeIntMatrix(
248b696e25aSGroverkss 4, 4, {{1, 0, 0, 0}, {0, 1, 0, 0}, {1, 0, 3, 0}, {18, 0, 54, 57}});
249b696e25aSGroverkss checkHermiteNormalForm(mat, hermiteForm);
250b696e25aSGroverkss }
251b696e25aSGroverkss
252b696e25aSGroverkss {
253f08fe1f1SAbhinav271828 IntMatrix mat = makeIntMatrix(
254f08fe1f1SAbhinav271828 3, 5, {{0, 2, 0, 7, 1}, {-1, 0, 0, -3, 0}, {0, 4, 1, 0, 8}});
255f08fe1f1SAbhinav271828 IntMatrix hermiteForm = makeIntMatrix(
256f08fe1f1SAbhinav271828 3, 5, {{1, 0, 0, 0, 0}, {0, 1, 0, 0, 0}, {0, 0, 1, 0, 0}});
257b696e25aSGroverkss checkHermiteNormalForm(mat, hermiteForm);
258b696e25aSGroverkss }
259b696e25aSGroverkss }
260f08fe1f1SAbhinav271828
TEST(MatrixTest,inverse)261f08fe1f1SAbhinav271828 TEST(MatrixTest, inverse) {
262e213af78SAbhinav271828 IntMatrix mat1 = makeIntMatrix(2, 2, {{2, 1}, {7, 0}});
263e213af78SAbhinav271828 EXPECT_EQ(mat1.determinant(), -7);
264e213af78SAbhinav271828
265f08fe1f1SAbhinav271828 FracMatrix mat = makeFracMatrix(
266f08fe1f1SAbhinav271828 2, 2, {{Fraction(2), Fraction(1)}, {Fraction(7), Fraction(0)}});
267f08fe1f1SAbhinav271828 FracMatrix inverse = makeFracMatrix(
268f08fe1f1SAbhinav271828 2, 2, {{Fraction(0), Fraction(1, 7)}, {Fraction(1), Fraction(-2, 7)}});
269f08fe1f1SAbhinav271828
270f08fe1f1SAbhinav271828 FracMatrix inv(2, 2);
271f08fe1f1SAbhinav271828 mat.determinant(&inv);
272f08fe1f1SAbhinav271828
273f08fe1f1SAbhinav271828 EXPECT_EQ_FRAC_MATRIX(inv, inverse);
274f08fe1f1SAbhinav271828
275f08fe1f1SAbhinav271828 mat = makeFracMatrix(
276f08fe1f1SAbhinav271828 2, 2, {{Fraction(0), Fraction(1)}, {Fraction(0), Fraction(2)}});
277f08fe1f1SAbhinav271828 Fraction det = mat.determinant(nullptr);
278f08fe1f1SAbhinav271828
279f08fe1f1SAbhinav271828 EXPECT_EQ(det, Fraction(0));
280f08fe1f1SAbhinav271828
281f08fe1f1SAbhinav271828 mat = makeFracMatrix(3, 3,
282f08fe1f1SAbhinav271828 {{Fraction(1), Fraction(2), Fraction(3)},
283f08fe1f1SAbhinav271828 {Fraction(4), Fraction(8), Fraction(6)},
284f08fe1f1SAbhinav271828 {Fraction(7), Fraction(8), Fraction(6)}});
285f08fe1f1SAbhinav271828 inverse = makeFracMatrix(3, 3,
286f08fe1f1SAbhinav271828 {{Fraction(0), Fraction(-1, 3), Fraction(1, 3)},
287f08fe1f1SAbhinav271828 {Fraction(-1, 2), Fraction(5, 12), Fraction(-1, 6)},
288f08fe1f1SAbhinav271828 {Fraction(2, 3), Fraction(-1, 6), Fraction(0)}});
289f08fe1f1SAbhinav271828
290f08fe1f1SAbhinav271828 mat.determinant(&inv);
291f08fe1f1SAbhinav271828 EXPECT_EQ_FRAC_MATRIX(inv, inverse);
292f08fe1f1SAbhinav271828
293f08fe1f1SAbhinav271828 mat = makeFracMatrix(0, 0, {});
294f08fe1f1SAbhinav271828 mat.determinant(&inv);
295f08fe1f1SAbhinav271828 }
296f08fe1f1SAbhinav271828
TEST(MatrixTest,intInverse)297f08fe1f1SAbhinav271828 TEST(MatrixTest, intInverse) {
298f08fe1f1SAbhinav271828 IntMatrix mat = makeIntMatrix(2, 2, {{2, 1}, {7, 0}});
299f08fe1f1SAbhinav271828 IntMatrix inverse = makeIntMatrix(2, 2, {{0, -1}, {-7, 2}});
300f08fe1f1SAbhinav271828
301f08fe1f1SAbhinav271828 IntMatrix inv(2, 2);
302f08fe1f1SAbhinav271828 mat.determinant(&inv);
303f08fe1f1SAbhinav271828
304f08fe1f1SAbhinav271828 EXPECT_EQ_INT_MATRIX(inv, inverse);
305f08fe1f1SAbhinav271828
306f08fe1f1SAbhinav271828 mat = makeIntMatrix(
307f08fe1f1SAbhinav271828 4, 4, {{4, 14, 11, 3}, {13, 5, 14, 12}, {13, 9, 7, 14}, {2, 3, 12, 7}});
308f08fe1f1SAbhinav271828 inverse = makeIntMatrix(4, 4,
309f08fe1f1SAbhinav271828 {{155, 1636, -579, -1713},
310f08fe1f1SAbhinav271828 {725, -743, 537, -111},
311f08fe1f1SAbhinav271828 {210, 735, -855, 360},
312f08fe1f1SAbhinav271828 {-715, -1409, 1401, 1482}});
313f08fe1f1SAbhinav271828
314f08fe1f1SAbhinav271828 mat.determinant(&inv);
315f08fe1f1SAbhinav271828
316f08fe1f1SAbhinav271828 EXPECT_EQ_INT_MATRIX(inv, inverse);
317f08fe1f1SAbhinav271828
318f08fe1f1SAbhinav271828 mat = makeIntMatrix(2, 2, {{0, 0}, {1, 2}});
319f08fe1f1SAbhinav271828
320*1a0e67d7SRamkumar Ramachandra DynamicAPInt det = mat.determinant(&inv);
321f08fe1f1SAbhinav271828
322f08fe1f1SAbhinav271828 EXPECT_EQ(det, 0);
323f08fe1f1SAbhinav271828 }
32484ab06baSAbhinav271828
TEST(MatrixTest,gramSchmidt)32584ab06baSAbhinav271828 TEST(MatrixTest, gramSchmidt) {
32684ab06baSAbhinav271828 FracMatrix mat =
32784ab06baSAbhinav271828 makeFracMatrix(3, 5,
32884ab06baSAbhinav271828 {{Fraction(3, 1), Fraction(4, 1), Fraction(5, 1),
32984ab06baSAbhinav271828 Fraction(12, 1), Fraction(19, 1)},
33084ab06baSAbhinav271828 {Fraction(4, 1), Fraction(5, 1), Fraction(6, 1),
33184ab06baSAbhinav271828 Fraction(13, 1), Fraction(20, 1)},
33284ab06baSAbhinav271828 {Fraction(7, 1), Fraction(8, 1), Fraction(9, 1),
33384ab06baSAbhinav271828 Fraction(16, 1), Fraction(24, 1)}});
33484ab06baSAbhinav271828
33584ab06baSAbhinav271828 FracMatrix gramSchmidt = makeFracMatrix(
33684ab06baSAbhinav271828 3, 5,
33784ab06baSAbhinav271828 {{Fraction(3, 1), Fraction(4, 1), Fraction(5, 1), Fraction(12, 1),
33884ab06baSAbhinav271828 Fraction(19, 1)},
33984ab06baSAbhinav271828 {Fraction(142, 185), Fraction(383, 555), Fraction(68, 111),
34084ab06baSAbhinav271828 Fraction(13, 185), Fraction(-262, 555)},
34184ab06baSAbhinav271828 {Fraction(53, 463), Fraction(27, 463), Fraction(1, 463),
34284ab06baSAbhinav271828 Fraction(-181, 463), Fraction(100, 463)}});
34384ab06baSAbhinav271828
34484ab06baSAbhinav271828 FracMatrix gs = mat.gramSchmidt();
34584ab06baSAbhinav271828
34684ab06baSAbhinav271828 EXPECT_EQ_FRAC_MATRIX(gs, gramSchmidt);
34784ab06baSAbhinav271828 for (unsigned i = 0; i < 3u; i++)
34884ab06baSAbhinav271828 for (unsigned j = i + 1; j < 3u; j++)
34984ab06baSAbhinav271828 EXPECT_EQ(dotProduct(gs.getRow(i), gs.getRow(j)), 0);
35084ab06baSAbhinav271828
35184ab06baSAbhinav271828 mat = makeFracMatrix(3, 3,
35284ab06baSAbhinav271828 {{Fraction(20, 1), Fraction(17, 1), Fraction(10, 1)},
35384ab06baSAbhinav271828 {Fraction(20, 1), Fraction(18, 1), Fraction(6, 1)},
35484ab06baSAbhinav271828 {Fraction(15, 1), Fraction(14, 1), Fraction(10, 1)}});
35584ab06baSAbhinav271828
35684ab06baSAbhinav271828 gramSchmidt = makeFracMatrix(
35784ab06baSAbhinav271828 3, 3,
35884ab06baSAbhinav271828 {{Fraction(20, 1), Fraction(17, 1), Fraction(10, 1)},
35984ab06baSAbhinav271828 {Fraction(460, 789), Fraction(1180, 789), Fraction(-2926, 789)},
36084ab06baSAbhinav271828 {Fraction(-2925, 3221), Fraction(3000, 3221), Fraction(750, 3221)}});
36184ab06baSAbhinav271828
36284ab06baSAbhinav271828 gs = mat.gramSchmidt();
36384ab06baSAbhinav271828
36484ab06baSAbhinav271828 EXPECT_EQ_FRAC_MATRIX(gs, gramSchmidt);
36584ab06baSAbhinav271828 for (unsigned i = 0; i < 3u; i++)
36684ab06baSAbhinav271828 for (unsigned j = i + 1; j < 3u; j++)
36784ab06baSAbhinav271828 EXPECT_EQ(dotProduct(gs.getRow(i), gs.getRow(j)), 0);
36884ab06baSAbhinav271828
36984ab06baSAbhinav271828 mat = makeFracMatrix(
37084ab06baSAbhinav271828 4, 4,
37184ab06baSAbhinav271828 {{Fraction(1, 26), Fraction(13, 12), Fraction(34, 13), Fraction(7, 10)},
37284ab06baSAbhinav271828 {Fraction(40, 23), Fraction(34, 1), Fraction(11, 19), Fraction(15, 1)},
37384ab06baSAbhinav271828 {Fraction(21, 22), Fraction(10, 9), Fraction(4, 11), Fraction(14, 11)},
37484ab06baSAbhinav271828 {Fraction(35, 22), Fraction(1, 15), Fraction(5, 8), Fraction(30, 1)}});
37584ab06baSAbhinav271828
37684ab06baSAbhinav271828 gs = mat.gramSchmidt();
37784ab06baSAbhinav271828
37884ab06baSAbhinav271828 // The integers involved are too big to construct the actual matrix.
37984ab06baSAbhinav271828 // but we can check that the result is linearly independent.
38084ab06baSAbhinav271828 ASSERT_FALSE(mat.determinant(nullptr) == 0);
38184ab06baSAbhinav271828
38284ab06baSAbhinav271828 for (unsigned i = 0; i < 4u; i++)
38384ab06baSAbhinav271828 for (unsigned j = i + 1; j < 4u; j++)
38484ab06baSAbhinav271828 EXPECT_EQ(dotProduct(gs.getRow(i), gs.getRow(j)), 0);
38584ab06baSAbhinav271828
38684ab06baSAbhinav271828 mat = FracMatrix::identity(/*dim=*/10);
38784ab06baSAbhinav271828
38884ab06baSAbhinav271828 gs = mat.gramSchmidt();
38984ab06baSAbhinav271828
39084ab06baSAbhinav271828 EXPECT_EQ_FRAC_MATRIX(gs, FracMatrix::identity(10));
39184ab06baSAbhinav271828 }
392cfd51fbaSAbhinav271828
checkReducedBasis(FracMatrix mat,Fraction delta)393cfd51fbaSAbhinav271828 void checkReducedBasis(FracMatrix mat, Fraction delta) {
394cfd51fbaSAbhinav271828 FracMatrix gsOrth = mat.gramSchmidt();
395cfd51fbaSAbhinav271828
396cfd51fbaSAbhinav271828 // Size-reduced check.
397cfd51fbaSAbhinav271828 for (unsigned i = 0, e = mat.getNumRows(); i < e; i++) {
398cfd51fbaSAbhinav271828 for (unsigned j = 0; j < i; j++) {
399cfd51fbaSAbhinav271828 Fraction mu = dotProduct(mat.getRow(i), gsOrth.getRow(j)) /
400cfd51fbaSAbhinav271828 dotProduct(gsOrth.getRow(j), gsOrth.getRow(j));
401cfd51fbaSAbhinav271828 EXPECT_TRUE(abs(mu) <= Fraction(1, 2));
402cfd51fbaSAbhinav271828 }
403cfd51fbaSAbhinav271828 }
404cfd51fbaSAbhinav271828
405cfd51fbaSAbhinav271828 // Lovasz condition check.
406cfd51fbaSAbhinav271828 for (unsigned i = 1, e = mat.getNumRows(); i < e; i++) {
407cfd51fbaSAbhinav271828 Fraction mu = dotProduct(mat.getRow(i), gsOrth.getRow(i - 1)) /
408cfd51fbaSAbhinav271828 dotProduct(gsOrth.getRow(i - 1), gsOrth.getRow(i - 1));
409cfd51fbaSAbhinav271828 EXPECT_TRUE(dotProduct(mat.getRow(i), mat.getRow(i)) >
410cfd51fbaSAbhinav271828 (delta - mu * mu) *
411cfd51fbaSAbhinav271828 dotProduct(gsOrth.getRow(i - 1), gsOrth.getRow(i - 1)));
412cfd51fbaSAbhinav271828 }
413cfd51fbaSAbhinav271828 }
414cfd51fbaSAbhinav271828
TEST(MatrixTest,LLL)415cfd51fbaSAbhinav271828 TEST(MatrixTest, LLL) {
416cfd51fbaSAbhinav271828 FracMatrix mat =
417cfd51fbaSAbhinav271828 makeFracMatrix(3, 3,
418cfd51fbaSAbhinav271828 {{Fraction(1, 1), Fraction(1, 1), Fraction(1, 1)},
419cfd51fbaSAbhinav271828 {Fraction(-1, 1), Fraction(0, 1), Fraction(2, 1)},
420cfd51fbaSAbhinav271828 {Fraction(3, 1), Fraction(5, 1), Fraction(6, 1)}});
421cfd51fbaSAbhinav271828 mat.LLL(Fraction(3, 4));
422cfd51fbaSAbhinav271828
423cfd51fbaSAbhinav271828 checkReducedBasis(mat, Fraction(3, 4));
424cfd51fbaSAbhinav271828
425cfd51fbaSAbhinav271828 mat = makeFracMatrix(
426cfd51fbaSAbhinav271828 2, 2,
427cfd51fbaSAbhinav271828 {{Fraction(12, 1), Fraction(2, 1)}, {Fraction(13, 1), Fraction(4, 1)}});
428cfd51fbaSAbhinav271828 mat.LLL(Fraction(3, 4));
429cfd51fbaSAbhinav271828
430cfd51fbaSAbhinav271828 checkReducedBasis(mat, Fraction(3, 4));
431cfd51fbaSAbhinav271828
432cfd51fbaSAbhinav271828 mat = makeFracMatrix(3, 3,
433cfd51fbaSAbhinav271828 {{Fraction(1, 1), Fraction(0, 1), Fraction(2, 1)},
434cfd51fbaSAbhinav271828 {Fraction(0, 1), Fraction(1, 3), -Fraction(5, 3)},
435cfd51fbaSAbhinav271828 {Fraction(0, 1), Fraction(0, 1), Fraction(1, 1)}});
436cfd51fbaSAbhinav271828 mat.LLL(Fraction(3, 4));
437cfd51fbaSAbhinav271828
438cfd51fbaSAbhinav271828 checkReducedBasis(mat, Fraction(3, 4));
439cfd51fbaSAbhinav271828 }
44066786a79SBharathi Ramana Joshi
TEST(MatrixTest,moveColumns)44166786a79SBharathi Ramana Joshi TEST(MatrixTest, moveColumns) {
44266786a79SBharathi Ramana Joshi IntMatrix mat =
44366786a79SBharathi Ramana Joshi makeIntMatrix(3, 4, {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 4, 2}});
44466786a79SBharathi Ramana Joshi
44566786a79SBharathi Ramana Joshi {
44666786a79SBharathi Ramana Joshi IntMatrix movedMat =
44766786a79SBharathi Ramana Joshi makeIntMatrix(3, 4, {{0, 3, 1, 2}, {4, 7, 5, 6}, {8, 2, 9, 4}});
44866786a79SBharathi Ramana Joshi
44966786a79SBharathi Ramana Joshi movedMat.moveColumns(2, 2, 1);
45066786a79SBharathi Ramana Joshi checkMatEqual(mat, movedMat);
45166786a79SBharathi Ramana Joshi }
45266786a79SBharathi Ramana Joshi
45366786a79SBharathi Ramana Joshi {
45466786a79SBharathi Ramana Joshi IntMatrix movedMat =
45566786a79SBharathi Ramana Joshi makeIntMatrix(3, 4, {{0, 3, 1, 2}, {4, 7, 5, 6}, {8, 2, 9, 4}});
45666786a79SBharathi Ramana Joshi
45766786a79SBharathi Ramana Joshi movedMat.moveColumns(1, 1, 3);
45866786a79SBharathi Ramana Joshi checkMatEqual(mat, movedMat);
45966786a79SBharathi Ramana Joshi }
46066786a79SBharathi Ramana Joshi
46166786a79SBharathi Ramana Joshi {
46266786a79SBharathi Ramana Joshi IntMatrix movedMat =
46366786a79SBharathi Ramana Joshi makeIntMatrix(3, 4, {{1, 2, 0, 3}, {5, 6, 4, 7}, {9, 4, 8, 2}});
46466786a79SBharathi Ramana Joshi
46566786a79SBharathi Ramana Joshi movedMat.moveColumns(0, 2, 1);
46666786a79SBharathi Ramana Joshi checkMatEqual(mat, movedMat);
46766786a79SBharathi Ramana Joshi }
46866786a79SBharathi Ramana Joshi
46966786a79SBharathi Ramana Joshi {
47066786a79SBharathi Ramana Joshi IntMatrix movedMat =
47166786a79SBharathi Ramana Joshi makeIntMatrix(3, 4, {{1, 0, 2, 3}, {5, 4, 6, 7}, {9, 8, 4, 2}});
47266786a79SBharathi Ramana Joshi
47366786a79SBharathi Ramana Joshi movedMat.moveColumns(0, 1, 1);
47466786a79SBharathi Ramana Joshi checkMatEqual(mat, movedMat);
47566786a79SBharathi Ramana Joshi }
47666786a79SBharathi Ramana Joshi }
477