xref: /llvm-project/mlir/unittests/Analysis/Presburger/MatrixTest.cpp (revision 1a0e67d73023e7ad9e7e79f66afb43a6f2561d04)
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