View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.linear;
23  
24  import org.hipparchus.UnitTestUtils;
25  import org.hipparchus.exception.LocalizedCoreFormats;
26  import org.hipparchus.exception.MathIllegalArgumentException;
27  import org.hipparchus.exception.NullArgumentException;
28  import org.hipparchus.fraction.Fraction;
29  import org.hipparchus.fraction.FractionField;
30  import org.hipparchus.random.RandomGenerator;
31  import org.hipparchus.random.Well1024a;
32  import org.hipparchus.util.Binary64;
33  import org.hipparchus.util.Binary64Field;
34  import org.junit.jupiter.api.Test;
35  
36  import java.util.Arrays;
37  import java.util.Random;
38  
39  import static org.junit.jupiter.api.Assertions.assertEquals;
40  import static org.junit.jupiter.api.Assertions.assertFalse;
41  import static org.junit.jupiter.api.Assertions.assertNotEquals;
42  import static org.junit.jupiter.api.Assertions.assertNotSame;
43  import static org.junit.jupiter.api.Assertions.assertTrue;
44  import static org.junit.jupiter.api.Assertions.fail;
45  
46  /**
47   * Test cases for the {@link BlockFieldMatrix} class.
48   *
49   */
50  
51  final class BlockFieldMatrixTest {
52  
53      // 3 x 3 identity matrix
54      protected Fraction[][] id = {
55              {new Fraction(1),new Fraction(0),new Fraction(0)},
56              {new Fraction(0),new Fraction(1),new Fraction(0)},
57              {new Fraction(0),new Fraction(0),new Fraction(1)}
58      };
59  
60      // Test data for group operations
61      protected Fraction[][] testData = {
62              {new Fraction(1),new Fraction(2),new Fraction(3)},
63              {new Fraction(2),new Fraction(5),new Fraction(3)},
64              {new Fraction(1),new Fraction(0),new Fraction(8)}
65      };
66      protected Fraction[][] testDataLU = {
67              {new Fraction(2), new Fraction(5), new Fraction(3)},
68              {new Fraction(1, 2), new Fraction(-5, 2), new Fraction(13, 2)},
69              {new Fraction(1, 2), new Fraction(1, 5), new Fraction(1, 5)}
70      };
71      protected Fraction[][] testDataPlus2 = {
72              {new Fraction(3),new Fraction(4),new Fraction(5)},
73              {new Fraction(4),new Fraction(7),new Fraction(5)},
74              {new Fraction(3),new Fraction(2),new Fraction(10)}
75      };
76      protected Fraction[][] testDataMinus = {
77              {new Fraction(-1),new Fraction(-2),new Fraction(-3)},
78              {new Fraction(-2),new Fraction(-5),new Fraction(-3)},
79              {new Fraction(-1),new Fraction(0),new Fraction(-8)}
80      };
81      protected Fraction[] testDataRow1 = {new Fraction(1),new Fraction(2),new Fraction(3)};
82      protected Fraction[] testDataCol3 = {new Fraction(3),new Fraction(3),new Fraction(8)};
83      protected Fraction[][] testDataInv = {
84              {new Fraction(-40),new Fraction(16),new Fraction(9)},
85              {new Fraction(13),new Fraction(-5),new Fraction(-3)},
86              {new Fraction(5),new Fraction(-2),new Fraction(-1)}
87      };
88      protected Fraction[] preMultTest = {new Fraction(8), new Fraction(12), new Fraction(33)};
89      protected Fraction[][] testData2 = {
90              {new Fraction(1),new Fraction(2),new Fraction(3)},
91              {new Fraction(2),new Fraction(5),new Fraction(3)}
92      };
93      protected Fraction[][] testData2T = {
94              {new Fraction(1),new Fraction(2)},
95              {new Fraction(2),new Fraction(5)},
96              {new Fraction(3),new Fraction(3)}
97      };
98      protected Fraction[][] testDataPlusInv = {
99              {new Fraction(-39),new Fraction(18),new Fraction(12)},
100             {new Fraction(15),new Fraction(0),new Fraction(0)},
101             {new Fraction(6),new Fraction(-2),new Fraction(7)}
102     };
103 
104     // lu decomposition tests
105     protected Fraction[][] luData = {
106             {new Fraction(2),new Fraction(3),new Fraction(3)},
107             {new Fraction(0),new Fraction(5),new Fraction(7)},
108             {new Fraction(6),new Fraction(9),new Fraction(8)}
109     };
110     protected Fraction[][] luDataLUDecomposition = {
111             {new Fraction(6),new Fraction(9),new Fraction(8)},
112             {new Fraction(0),new Fraction(5),new Fraction(7)},
113             {new Fraction(1, 3),new Fraction(0),new Fraction(1, 3)}
114     };
115 
116     // singular matrices
117     protected Fraction[][] singular = { {new Fraction(2),new Fraction(3)}, {new Fraction(2),new Fraction(3)} };
118     protected Fraction[][] bigSingular = {
119             {new Fraction(1),new Fraction(2),new Fraction(3),new Fraction(4)},
120             {new Fraction(2),new Fraction(5),new Fraction(3),new Fraction(4)},
121             {new Fraction(7),new Fraction(3),new Fraction(256),new Fraction(1930)},
122             {new Fraction(3),new Fraction(7),new Fraction(6),new Fraction(8)}
123     }; // 4th row = 1st + 2nd
124     protected Fraction[][] detData = {
125             {new Fraction(1),new Fraction(2),new Fraction(3)},
126             {new Fraction(4),new Fraction(5),new Fraction(6)},
127             {new Fraction(7),new Fraction(8),new Fraction(10)}
128     };
129     protected Fraction[][] detData2 = { {new Fraction(1), new Fraction(3)}, {new Fraction(2), new Fraction(4)}};
130 
131     // vectors
132     protected Fraction[] testVector = {new Fraction(1),new Fraction(2),new Fraction(3)};
133     protected Fraction[] testVector2 = {new Fraction(1),new Fraction(2),new Fraction(3),new Fraction(4)};
134 
135     // submatrix accessor tests
136     protected Fraction[][] subTestData = {
137             {new Fraction(1), new Fraction(2), new Fraction(3), new Fraction(4)},
138             {new Fraction(3, 2), new Fraction(5, 2), new Fraction(7, 2), new Fraction(9, 2)},
139             {new Fraction(2), new Fraction(4), new Fraction(6), new Fraction(8)},
140             {new Fraction(4), new Fraction(5), new Fraction(6), new Fraction(7)}
141     };
142     // array selections
143     protected Fraction[][] subRows02Cols13 = { {new Fraction(2), new Fraction(4)}, {new Fraction(4), new Fraction(8)}};
144     protected Fraction[][] subRows03Cols12 = { {new Fraction(2), new Fraction(3)}, {new Fraction(5), new Fraction(6)}};
145     protected Fraction[][] subRows03Cols123 = {
146             {new Fraction(2), new Fraction(3), new Fraction(4)},
147             {new Fraction(5), new Fraction(6), new Fraction(7)}
148     };
149     // effective permutations
150     protected Fraction[][] subRows20Cols123 = {
151             {new Fraction(4), new Fraction(6), new Fraction(8)},
152             {new Fraction(2), new Fraction(3), new Fraction(4)}
153     };
154     protected Fraction[][] subRows31Cols31 = {{new Fraction(7), new Fraction(5)}, {new Fraction(9, 2), new Fraction(5, 2)}};
155     // contiguous ranges
156     protected Fraction[][] subRows01Cols23 = {{new Fraction(3),new Fraction(4)} , {new Fraction(7, 2), new Fraction(9, 2)}};
157     protected Fraction[][] subRows23Cols00 = {{new Fraction(2)} , {new Fraction(4)}};
158     protected Fraction[][] subRows00Cols33 = {{new Fraction(4)}};
159     // row matrices
160     protected Fraction[][] subRow0 = {{new Fraction(1),new Fraction(2),new Fraction(3),new Fraction(4)}};
161     protected Fraction[][] subRow3 = {{new Fraction(4),new Fraction(5),new Fraction(6),new Fraction(7)}};
162     // column matrices
163     protected Fraction[][] subColumn1 = {{new Fraction(2)}, {new Fraction(5, 2)}, {new Fraction(4)}, {new Fraction(5)}};
164     protected Fraction[][] subColumn3 = {{new Fraction(4)}, {new Fraction(9, 2)}, {new Fraction(8)}, {new Fraction(7)}};
165 
166     // tolerances
167     protected double entryTolerance = 10E-16;
168     protected double normTolerance = 10E-14;
169 
170     /** test dimensions */
171     @Test
172     void testDimensions() {
173         BlockFieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(testData);
174         BlockFieldMatrix<Fraction> m2 = new BlockFieldMatrix<Fraction>(testData2);
175         assertEquals(3,m.getRowDimension(),"testData row dimension");
176         assertEquals(3,m.getColumnDimension(),"testData column dimension");
177         assertTrue(m.isSquare(),"testData is square");
178         assertEquals(2, m2.getRowDimension(), "testData2 row dimension");
179         assertEquals(3, m2.getColumnDimension(), "testData2 column dimension");
180         assertFalse(m2.isSquare(), "testData2 is not square");
181     }
182 
183     /** test copy functions */
184     @Test
185     void testCopyFunctions() {
186         Random r = new Random(66636328996002l);
187         BlockFieldMatrix<Fraction> m1 = createRandomMatrix(r, 47, 83);
188         BlockFieldMatrix<Fraction> m2 = new BlockFieldMatrix<Fraction>(m1.getData());
189         assertEquals(m1, m2);
190         BlockFieldMatrix<Fraction> m3 = new BlockFieldMatrix<Fraction>(testData);
191         BlockFieldMatrix<Fraction> m4 = new BlockFieldMatrix<Fraction>(m3.getData());
192         assertEquals(m3, m4);
193     }
194 
195     /** test add */
196     @Test
197     void testAdd() {
198         BlockFieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(testData);
199         BlockFieldMatrix<Fraction> mInv = new BlockFieldMatrix<Fraction>(testDataInv);
200         FieldMatrix<Fraction> mPlusMInv = m.add(mInv);
201         Fraction[][] sumEntries = mPlusMInv.getData();
202         for (int row = 0; row < m.getRowDimension(); row++) {
203             for (int col = 0; col < m.getColumnDimension(); col++) {
204                 assertEquals(testDataPlusInv[row][col],sumEntries[row][col]);
205             }
206         }
207     }
208 
209     /** test add failure */
210     @Test
211     void testAddFail() {
212         BlockFieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(testData);
213         BlockFieldMatrix<Fraction> m2 = new BlockFieldMatrix<Fraction>(testData2);
214         try {
215             m.add(m2);
216             fail("MathIllegalArgumentException expected");
217         } catch (MathIllegalArgumentException ex) {
218             // ignored
219         }
220     }
221 
222     /** test m-n = m + -n */
223     @Test
224     void testPlusMinus() {
225         BlockFieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(testData);
226         BlockFieldMatrix<Fraction> m2 = new BlockFieldMatrix<Fraction>(testDataInv);
227         UnitTestUtils.customAssertEquals(m.subtract(m2), m2.scalarMultiply(new Fraction(-1)).add(m));
228         try {
229             m.subtract(new BlockFieldMatrix<Fraction>(testData2));
230             fail("Expecting illegalArgumentException");
231         } catch (MathIllegalArgumentException ex) {
232             // ignored
233         }
234     }
235 
236     /** test multiply */
237     @Test
238     void testMultiply() {
239         BlockFieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(testData);
240         BlockFieldMatrix<Fraction> mInv = new BlockFieldMatrix<Fraction>(testDataInv);
241         BlockFieldMatrix<Fraction> identity = new BlockFieldMatrix<Fraction>(id);
242         BlockFieldMatrix<Fraction> m2 = new BlockFieldMatrix<Fraction>(testData2);
243         UnitTestUtils.customAssertEquals(m.multiply(mInv), identity);
244         UnitTestUtils.customAssertEquals(mInv.multiply(m), identity);
245         UnitTestUtils.customAssertEquals(m.multiply(identity), m);
246         UnitTestUtils.customAssertEquals(identity.multiply(mInv), mInv);
247         UnitTestUtils.customAssertEquals(m2.multiply(identity), m2);
248         try {
249             m.multiply(new BlockFieldMatrix<Fraction>(bigSingular));
250             fail("Expecting illegalArgumentException");
251         } catch (MathIllegalArgumentException ex) {
252             // expected
253         }
254     }
255 
256     @Test
257     void testSeveralBlocks() {
258         FieldMatrix<Fraction> m =
259             new BlockFieldMatrix<Fraction>(FractionField.getInstance(), 37, 41);
260         for (int i = 0; i < m.getRowDimension(); ++i) {
261             for (int j = 0; j < m.getColumnDimension(); ++j) {
262                 m.setEntry(i, j, new Fraction(i * 11 + j, 11));
263             }
264         }
265 
266         FieldMatrix<Fraction> mT = m.transpose();
267         assertEquals(m.getRowDimension(), mT.getColumnDimension());
268         assertEquals(m.getColumnDimension(), mT.getRowDimension());
269         for (int i = 0; i < mT.getRowDimension(); ++i) {
270             for (int j = 0; j < mT.getColumnDimension(); ++j) {
271                 assertEquals(m.getEntry(j, i), mT.getEntry(i, j));
272             }
273         }
274 
275         FieldMatrix<Fraction> mPm = m.add(m);
276         for (int i = 0; i < mPm.getRowDimension(); ++i) {
277             for (int j = 0; j < mPm.getColumnDimension(); ++j) {
278                 assertEquals(m.getEntry(i, j).multiply(new Fraction(2)), mPm.getEntry(i, j));
279             }
280         }
281 
282         FieldMatrix<Fraction> mPmMm = mPm.subtract(m);
283         for (int i = 0; i < mPmMm.getRowDimension(); ++i) {
284             for (int j = 0; j < mPmMm.getColumnDimension(); ++j) {
285                 assertEquals(m.getEntry(i, j), mPmMm.getEntry(i, j));
286             }
287         }
288 
289         FieldMatrix<Fraction> mTm = mT.multiply(m);
290         for (int i = 0; i < mTm.getRowDimension(); ++i) {
291             for (int j = 0; j < mTm.getColumnDimension(); ++j) {
292                 Fraction sum = Fraction.ZERO;
293                 for (int k = 0; k < mT.getColumnDimension(); ++k) {
294                     sum = sum.add(new Fraction(k * 11 + i, 11).multiply(new Fraction(k * 11 + j, 11)));
295                 }
296                 assertEquals(sum, mTm.getEntry(i, j));
297             }
298         }
299 
300         FieldMatrix<Fraction> mmT = m.multiply(mT);
301         for (int i = 0; i < mmT.getRowDimension(); ++i) {
302             for (int j = 0; j < mmT.getColumnDimension(); ++j) {
303                 Fraction sum = Fraction.ZERO;
304                 for (int k = 0; k < m.getColumnDimension(); ++k) {
305                     sum = sum.add(new Fraction(i * 11 + k, 11).multiply(new Fraction(j * 11 + k, 11)));
306                 }
307                 assertEquals(sum, mmT.getEntry(i, j));
308             }
309         }
310 
311         FieldMatrix<Fraction> sub1 = m.getSubMatrix(2, 9, 5, 20);
312         for (int i = 0; i < sub1.getRowDimension(); ++i) {
313             for (int j = 0; j < sub1.getColumnDimension(); ++j) {
314                 assertEquals(new Fraction((i + 2) * 11 + (j + 5), 11), sub1.getEntry(i, j));
315             }
316         }
317 
318         FieldMatrix<Fraction> sub2 = m.getSubMatrix(10, 12, 3, 40);
319         for (int i = 0; i < sub2.getRowDimension(); ++i) {
320             for (int j = 0; j < sub2.getColumnDimension(); ++j) {
321                 assertEquals(new Fraction((i + 10) * 11 + (j + 3), 11), sub2.getEntry(i, j));
322             }
323         }
324 
325         FieldMatrix<Fraction> sub3 = m.getSubMatrix(30, 34, 0, 5);
326         for (int i = 0; i < sub3.getRowDimension(); ++i) {
327             for (int j = 0; j < sub3.getColumnDimension(); ++j) {
328                 assertEquals(new Fraction((i + 30) * 11 + (j + 0), 11), sub3.getEntry(i, j));
329             }
330         }
331 
332         FieldMatrix<Fraction> sub4 = m.getSubMatrix(30, 32, 32, 35);
333         for (int i = 0; i < sub4.getRowDimension(); ++i) {
334             for (int j = 0; j < sub4.getColumnDimension(); ++j) {
335                 assertEquals(new Fraction((i + 30) * 11 + (j + 32), 11), sub4.getEntry(i, j));
336             }
337         }
338 
339     }
340 
341     //Additional Test for BlockFieldMatrix<Fraction>Test.testMultiply
342 
343     private Fraction[][] d3 = new Fraction[][] {
344             {new Fraction(1),new Fraction(2),new Fraction(3),new Fraction(4)},
345             {new Fraction(5),new Fraction(6),new Fraction(7),new Fraction(8)}
346     };
347     private Fraction[][] d4 = new Fraction[][] {
348             {new Fraction(1)},
349             {new Fraction(2)},
350             {new Fraction(3)},
351             {new Fraction(4)}
352     };
353     private Fraction[][] d5 = new Fraction[][] {{new Fraction(30)},{new Fraction(70)}};
354 
355     @Test
356     void testMultiply2() {
357        FieldMatrix<Fraction> m3 = new BlockFieldMatrix<Fraction>(d3);
358        FieldMatrix<Fraction> m4 = new BlockFieldMatrix<Fraction>(d4);
359        FieldMatrix<Fraction> m5 = new BlockFieldMatrix<Fraction>(d5);
360        UnitTestUtils.customAssertEquals(m3.multiply(m4), m5);
361     }
362 
363     @Test
364     void testMultiplyTransposedBlockRealMatrix() {
365         RandomGenerator randomGenerator = new Well1024a(0xfaa1594a49a1359el);
366         final FieldMatrixChangingVisitor<Binary64> randomSetter = new DefaultFieldMatrixChangingVisitor<Binary64>(Binary64Field.getInstance().getZero()) {
367             public Binary64 visit(final int row, final int column, final Binary64 value) {
368                 return new Binary64(randomGenerator.nextDouble());
369             }
370         };
371         final FieldMatrixPreservingVisitor<Binary64> zeroChecker = new DefaultFieldMatrixPreservingVisitor<Binary64>(Binary64Field.getInstance().getZero()) {
372             public void visit(final int row, final int column, final Binary64 value) {
373                 assertEquals(0.0, value.doubleValue(), 1.0e-15);
374             }
375         };
376         for (int rows = 1; rows <= 64; rows += 7) {
377             for (int cols = 1; cols <= 64; cols += 7) {
378                 final BlockFieldMatrix<Binary64> a = new BlockFieldMatrix<>(Binary64Field.getInstance(), rows, cols);
379                 a.walkInOptimizedOrder(randomSetter);
380                 for (int interm = 1; interm <= 64; interm += 7) {
381                     final BlockFieldMatrix<Binary64> b = new BlockFieldMatrix<>(Binary64Field.getInstance(), interm, cols);
382                     b.walkInOptimizedOrder(randomSetter);
383                     a.multiplyTransposed(b).subtract(a.multiply(b.transpose())).walkInOptimizedOrder(zeroChecker);
384                 }
385             }
386         }
387     }
388 
389     @Test
390     void testMultiplyTransposedArray2DRowRealMatrix() {
391         RandomGenerator randomGenerator = new Well1024a(0xac2d0185fc69670bl);
392         final FieldMatrixChangingVisitor<Binary64> randomSetter = new DefaultFieldMatrixChangingVisitor<Binary64>(Binary64Field.getInstance().getZero()) {
393             public Binary64 visit(final int row, final int column, final Binary64 value) {
394                 return new Binary64(randomGenerator.nextDouble());
395             }
396         };
397         final FieldMatrixPreservingVisitor<Binary64> zeroChecker = new DefaultFieldMatrixPreservingVisitor<Binary64>(Binary64Field.getInstance().getZero()) {
398             public void visit(final int row, final int column, final Binary64 value) {
399                 assertEquals(0.0, value.doubleValue(), 1.0e-15);
400             }
401         };
402         for (int rows = 1; rows <= 64; rows += 7) {
403             for (int cols = 1; cols <= 64; cols += 7) {
404                 final BlockFieldMatrix<Binary64> a = new BlockFieldMatrix<>(Binary64Field.getInstance(), rows, cols);
405                 a.walkInOptimizedOrder(randomSetter);
406                 for (int interm = 1; interm <= 64; interm += 7) {
407                     final Array2DRowFieldMatrix<Binary64> b = new Array2DRowFieldMatrix<>(Binary64Field.getInstance(), interm, cols);
408                     b.walkInOptimizedOrder(randomSetter);
409                     a.multiplyTransposed(b).subtract(a.multiply(b.transpose())).walkInOptimizedOrder(zeroChecker);
410                 }
411             }
412         }
413     }
414 
415     @Test
416     void testMultiplyTransposedWrongDimensions() {
417         try {
418             new BlockFieldMatrix<Binary64>(Binary64Field.getInstance(), 2, 3).
419             multiplyTransposed(new BlockFieldMatrix<Binary64>(Binary64Field.getInstance(), 3, 2));
420             fail("an exception should have been thrown");
421         } catch (MathIllegalArgumentException miae) {
422             assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, miae.getSpecifier());
423             assertEquals(3, ((Integer) miae.getParts()[0]).intValue());
424             assertEquals(2, ((Integer) miae.getParts()[1]).intValue());
425         }
426     }
427 
428     @Test
429     void testTransposeMultiplyBlockRealMatrix() {
430         RandomGenerator randomGenerator = new Well1024a(0xfaa1594a49a1359el);
431         final FieldMatrixChangingVisitor<Binary64> randomSetter = new DefaultFieldMatrixChangingVisitor<Binary64>(Binary64Field.getInstance().getZero()) {
432             public Binary64 visit(final int row, final int column, final Binary64 value) {
433                 return new Binary64(randomGenerator.nextDouble());
434             }
435         };
436         final FieldMatrixPreservingVisitor<Binary64> zeroChecker = new DefaultFieldMatrixPreservingVisitor<Binary64>(Binary64Field.getInstance().getZero()) {
437             public void visit(final int row, final int column, final Binary64 value) {
438                 assertEquals(0.0, value.doubleValue(), 2.0e-14);
439             }
440         };
441         for (int rows = 1; rows <= 64; rows += 7) {
442             for (int cols = 1; cols <= 64; cols += 7) {
443                 final BlockFieldMatrix<Binary64> a = new BlockFieldMatrix<>(Binary64Field.getInstance(), rows, cols);
444                 a.walkInOptimizedOrder(randomSetter);
445                 for (int interm = 1; interm <= 64; interm += 7) {
446                     final BlockFieldMatrix<Binary64> b = new BlockFieldMatrix<>(Binary64Field.getInstance(), rows, interm);
447                     b.walkInOptimizedOrder(randomSetter);
448                     a.transposeMultiply(b).subtract(a.transpose().multiply(b)).walkInOptimizedOrder(zeroChecker);
449                 }
450             }
451         }
452     }
453 
454     @Test
455     void testTransposeMultiplyArray2DRowRealMatrix() {
456         RandomGenerator randomGenerator = new Well1024a(0xac2d0185fc69670bl);
457         final FieldMatrixChangingVisitor<Binary64> randomSetter = new DefaultFieldMatrixChangingVisitor<Binary64>(Binary64Field.getInstance().getZero()) {
458             public Binary64 visit(final int row, final int column, final Binary64 value) {
459                 return new Binary64(randomGenerator.nextDouble());
460             }
461         };
462         final FieldMatrixPreservingVisitor<Binary64> zeroChecker = new DefaultFieldMatrixPreservingVisitor<Binary64>(Binary64Field.getInstance().getZero()) {
463             public void visit(final int row, final int column, final Binary64 value) {
464                 assertEquals(0.0, value.doubleValue(), 1.0e-15);
465             }
466         };
467         for (int rows = 1; rows <= 64; rows += 7) {
468             for (int cols = 1; cols <= 64; cols += 7) {
469                 final BlockFieldMatrix<Binary64> a = new BlockFieldMatrix<>(Binary64Field.getInstance(), rows, cols);
470                 a.walkInOptimizedOrder(randomSetter);
471                 for (int interm = 1; interm <= 64; interm += 7) {
472                     final Array2DRowFieldMatrix<Binary64> b = new Array2DRowFieldMatrix<>(Binary64Field.getInstance(), rows, interm);
473                     b.walkInOptimizedOrder(randomSetter);
474                     a.transposeMultiply(b).subtract(a.transpose().multiply(b)).walkInOptimizedOrder(zeroChecker);
475                 }
476             }
477         }
478     }
479 
480     @Test
481     void testTransposeMultiplyWrongDimensions() {
482         try {
483             new BlockFieldMatrix<Binary64>(Binary64Field.getInstance(), 2, 3).
484             transposeMultiply(new BlockFieldMatrix<Binary64>(Binary64Field.getInstance(), 3, 2));
485             fail("an exception should have been thrown");
486         } catch (MathIllegalArgumentException miae) {
487             assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, miae.getSpecifier());
488             assertEquals(2, ((Integer) miae.getParts()[0]).intValue());
489             assertEquals(3, ((Integer) miae.getParts()[1]).intValue());
490         }
491     }
492 
493     /** test trace */
494     @Test
495     void testTrace() {
496         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(id);
497         assertEquals(new Fraction(3),m.getTrace());
498         m = new BlockFieldMatrix<Fraction>(testData2);
499         try {
500             m.getTrace();
501             fail("Expecting MathIllegalArgumentException");
502         } catch (MathIllegalArgumentException ex) {
503             // ignored
504         }
505     }
506 
507     /** test scalarAdd */
508     @Test
509     void testScalarAdd() {
510         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(testData);
511         UnitTestUtils.customAssertEquals(new BlockFieldMatrix<Fraction>(testDataPlus2),
512                                          m.scalarAdd(new Fraction(2)));
513     }
514 
515     /** test operate */
516     @Test
517     void testOperate() {
518         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(id);
519         UnitTestUtils.customAssertEquals(testVector, m.operate(testVector));
520         UnitTestUtils.customAssertEquals(testVector, m.operate(new ArrayFieldVector<Fraction>(testVector)).toArray());
521         m = new BlockFieldMatrix<Fraction>(bigSingular);
522         try {
523             m.operate(testVector);
524             fail("Expecting illegalArgumentException");
525         } catch (MathIllegalArgumentException ex) {
526             // ignored
527         }
528     }
529 
530     @Test
531     void testOperateLarge() {
532         int p = (11 * BlockFieldMatrix.BLOCK_SIZE) / 10;
533         int q = (11 * BlockFieldMatrix.BLOCK_SIZE) / 10;
534         int r =  BlockFieldMatrix.BLOCK_SIZE / 2;
535         Random random = new Random(111007463902334l);
536         FieldMatrix<Fraction> m1 = createRandomMatrix(random, p, q);
537         FieldMatrix<Fraction> m2 = createRandomMatrix(random, q, r);
538         FieldMatrix<Fraction> m1m2 = m1.multiply(m2);
539         for (int i = 0; i < r; ++i) {
540             UnitTestUtils.customAssertEquals(m1m2.getColumn(i), m1.operate(m2.getColumn(i)));
541         }
542     }
543 
544     @Test
545     void testOperatePremultiplyLarge() {
546         int p = (11 * BlockFieldMatrix.BLOCK_SIZE) / 10;
547         int q = (11 * BlockFieldMatrix.BLOCK_SIZE) / 10;
548         int r =  BlockFieldMatrix.BLOCK_SIZE / 2;
549         Random random = new Random(111007463902334l);
550         FieldMatrix<Fraction> m1 = createRandomMatrix(random, p, q);
551         FieldMatrix<Fraction> m2 = createRandomMatrix(random, q, r);
552         FieldMatrix<Fraction> m1m2 = m1.multiply(m2);
553         for (int i = 0; i < p; ++i) {
554             UnitTestUtils.customAssertEquals(m1m2.getRow(i), m2.preMultiply(m1.getRow(i)));
555         }
556     }
557 
558     /** test issue MATH-209 */
559     @Test
560     void testMath209() {
561         FieldMatrix<Fraction> a = new BlockFieldMatrix<Fraction>(new Fraction[][] {
562                 { new Fraction(1), new Fraction(2) },
563                 { new Fraction(3), new Fraction(4) },
564                 { new Fraction(5), new Fraction(6) }
565         });
566         Fraction[] b = a.operate(new Fraction[] { new Fraction(1), new Fraction(1) });
567         assertEquals(a.getRowDimension(), b.length);
568         assertEquals( new Fraction(3), b[0]);
569         assertEquals( new Fraction(7), b[1]);
570         assertEquals(new Fraction(11), b[2]);
571     }
572 
573     /** test transpose */
574     @Test
575     void testTranspose() {
576         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(testData);
577         FieldMatrix<Fraction> mIT = new FieldLUDecomposition<Fraction>(m).getSolver().getInverse().transpose();
578         FieldMatrix<Fraction> mTI = new FieldLUDecomposition<Fraction>(m.transpose()).getSolver().getInverse();
579         UnitTestUtils.customAssertEquals(mIT, mTI);
580         m = new BlockFieldMatrix<Fraction>(testData2);
581         FieldMatrix<Fraction> mt = new BlockFieldMatrix<Fraction>(testData2T);
582         UnitTestUtils.customAssertEquals(mt, m.transpose());
583     }
584 
585     /** test preMultiply by vector */
586     @Test
587     void testPremultiplyVector() {
588         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(testData);
589         UnitTestUtils.customAssertEquals(m.preMultiply(testVector), preMultTest);
590         UnitTestUtils.customAssertEquals(m.preMultiply(new ArrayFieldVector<Fraction>(testVector).toArray()),
591                                          preMultTest);
592         m = new BlockFieldMatrix<Fraction>(bigSingular);
593         try {
594             m.preMultiply(testVector);
595             fail("expecting MathIllegalArgumentException");
596         } catch (MathIllegalArgumentException ex) {
597             // ignored
598         }
599     }
600 
601     @Test
602     void testPremultiply() {
603         FieldMatrix<Fraction> m3 = new BlockFieldMatrix<Fraction>(d3);
604         FieldMatrix<Fraction> m4 = new BlockFieldMatrix<Fraction>(d4);
605         FieldMatrix<Fraction> m5 = new BlockFieldMatrix<Fraction>(d5);
606         UnitTestUtils.customAssertEquals(m4.preMultiply(m3), m5);
607 
608         BlockFieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(testData);
609         BlockFieldMatrix<Fraction> mInv = new BlockFieldMatrix<Fraction>(testDataInv);
610         BlockFieldMatrix<Fraction> identity = new BlockFieldMatrix<Fraction>(id);
611         UnitTestUtils.customAssertEquals(m.preMultiply(mInv), identity);
612         UnitTestUtils.customAssertEquals(mInv.preMultiply(m), identity);
613         UnitTestUtils.customAssertEquals(m.preMultiply(identity), m);
614         UnitTestUtils.customAssertEquals(identity.preMultiply(mInv), mInv);
615         try {
616             m.preMultiply(new BlockFieldMatrix<Fraction>(bigSingular));
617             fail("Expecting illegalArgumentException");
618         } catch (MathIllegalArgumentException ex) {
619             // ignored
620         }
621     }
622 
623     @Test
624     void testGetVectors() {
625         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(testData);
626         UnitTestUtils.customAssertEquals(m.getRow(0), testDataRow1);
627         UnitTestUtils.customAssertEquals(m.getColumn(2), testDataCol3);
628         try {
629             m.getRow(10);
630             fail("expecting MathIllegalArgumentException");
631         } catch (MathIllegalArgumentException ex) {
632             // ignored
633         }
634         try {
635             m.getColumn(-1);
636             fail("expecting MathIllegalArgumentException");
637         } catch (MathIllegalArgumentException ex) {
638             // ignored
639         }
640     }
641 
642     @Test
643     void testGetEntry() {
644         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(testData);
645         assertEquals(m.getEntry(0,1),new Fraction(2));
646         try {
647             m.getEntry(10, 4);
648             fail ("Expecting MathIllegalArgumentException");
649         } catch (MathIllegalArgumentException ex) {
650             // expected
651         }
652     }
653 
654     /** test examples in user guide */
655     @Test
656     void testExamples() {
657         // Create a real matrix with two rows and three columns
658         Fraction[][] matrixData = {
659                 {new Fraction(1),new Fraction(2),new Fraction(3)},
660                 {new Fraction(2),new Fraction(5),new Fraction(3)}
661         };
662         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(matrixData);
663         // One more with three rows, two columns
664         Fraction[][] matrixData2 = {
665                 {new Fraction(1),new Fraction(2)},
666                 {new Fraction(2),new Fraction(5)},
667                 {new Fraction(1), new Fraction(7)}
668         };
669         FieldMatrix<Fraction> n = new BlockFieldMatrix<Fraction>(matrixData2);
670         // Now multiply m by n
671         FieldMatrix<Fraction> p = m.multiply(n);
672         assertEquals(2, p.getRowDimension());
673         assertEquals(2, p.getColumnDimension());
674         // Invert p
675         FieldMatrix<Fraction> pInverse = new FieldLUDecomposition<Fraction>(p).getSolver().getInverse();
676         assertEquals(2, pInverse.getRowDimension());
677         assertEquals(2, pInverse.getColumnDimension());
678 
679         // Solve example
680         Fraction[][] coefficientsData = {
681                 {new Fraction(2), new Fraction(3), new Fraction(-2)},
682                 {new Fraction(-1), new Fraction(7), new Fraction(6)},
683                 {new Fraction(4), new Fraction(-3), new Fraction(-5)}
684         };
685         FieldMatrix<Fraction> coefficients = new BlockFieldMatrix<Fraction>(coefficientsData);
686         Fraction[] constants = {
687             new Fraction(1), new Fraction(-2), new Fraction(1)
688         };
689         Fraction[] solution;
690         solution = new FieldLUDecomposition<Fraction>(coefficients)
691             .getSolver()
692             .solve(new ArrayFieldVector<Fraction>(constants, false)).toArray();
693         assertEquals(new Fraction(2).multiply(solution[0]).
694                      add(new Fraction(3).multiply(solution[1])).
695                      subtract(new Fraction(2).multiply(solution[2])),
696                      constants[0]);
697         assertEquals(new Fraction(-1).multiply(solution[0]).
698                      add(new Fraction(7).multiply(solution[1])).
699                      add(new Fraction(6).multiply(solution[2])),
700                      constants[1]);
701         assertEquals(new Fraction(4).multiply(solution[0]).
702                      subtract(new Fraction(3).multiply(solution[1])).
703                      subtract(new Fraction(5).multiply(solution[2])),
704                      constants[2]);
705 
706     }
707 
708     // test submatrix accessors
709     @Test
710     void testGetSubMatrix() {
711         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(subTestData);
712         checkGetSubMatrix(m, subRows23Cols00,  2 , 3 , 0, 0);
713         checkGetSubMatrix(m, subRows00Cols33,  0 , 0 , 3, 3);
714         checkGetSubMatrix(m, subRows01Cols23,  0 , 1 , 2, 3);
715         checkGetSubMatrix(m, subRows02Cols13,  new int[] { 0, 2 }, new int[] { 1, 3 });
716         checkGetSubMatrix(m, subRows03Cols12,  new int[] { 0, 3 }, new int[] { 1, 2 });
717         checkGetSubMatrix(m, subRows03Cols123, new int[] { 0, 3 }, new int[] { 1, 2, 3 });
718         checkGetSubMatrix(m, subRows20Cols123, new int[] { 2, 0 }, new int[] { 1, 2, 3 });
719         checkGetSubMatrix(m, subRows31Cols31,  new int[] { 3, 1 }, new int[] { 3, 1 });
720         checkGetSubMatrix(m, subRows31Cols31,  new int[] { 3, 1 }, new int[] { 3, 1 });
721         checkGetSubMatrix(m, null,  1, 0, 2, 4);
722         checkGetSubMatrix(m, null, -1, 1, 2, 2);
723         checkGetSubMatrix(m, null,  1, 0, 2, 2);
724         checkGetSubMatrix(m, null,  1, 0, 2, 4);
725         checkGetSubMatrix(m, null, new int[] {},    new int[] { 0 });
726         checkGetSubMatrix(m, null, new int[] { 0 }, new int[] { 4 });
727     }
728 
729     private void checkGetSubMatrix(FieldMatrix<Fraction> m, Fraction[][] reference,
730                                    int startRow, int endRow, int startColumn, int endColumn) {
731         try {
732             FieldMatrix<Fraction> sub = m.getSubMatrix(startRow, endRow, startColumn, endColumn);
733             if (reference != null) {
734                 assertEquals(new BlockFieldMatrix<Fraction>(reference), sub);
735             } else {
736                 fail("Expecting MathIllegalArgumentException or MathIllegalArgumentException"
737                      + " or MathIllegalArgumentException or MathIllegalArgumentException");
738             }
739         } catch (MathIllegalArgumentException e) {
740             if (reference != null) {
741                 throw e;
742             }
743         }
744     }
745 
746     private void checkGetSubMatrix(FieldMatrix<Fraction> m, Fraction[][] reference,
747                                    int[] selectedRows, int[] selectedColumns) {
748         try {
749             FieldMatrix<Fraction> sub = m.getSubMatrix(selectedRows, selectedColumns);
750             if (reference != null) {
751                 assertEquals(new BlockFieldMatrix<Fraction>(reference), sub);
752             } else {
753                 fail("Expecting MathIllegalArgumentException");
754             }
755         } catch (MathIllegalArgumentException e) {
756             if (reference != null) {
757                 throw e;
758             }
759         }
760     }
761 
762     @Test
763     void testGetSetMatrixLarge() {
764         int n = 3 * BlockFieldMatrix.BLOCK_SIZE;
765         FieldMatrix<Fraction> m =
766             new BlockFieldMatrix<Fraction>(FractionField.getInstance(), n, n);
767         FieldMatrix<Fraction> sub =
768             new BlockFieldMatrix<Fraction>(FractionField.getInstance(), n - 4, n - 4).scalarAdd(new Fraction(1));
769 
770         m.setSubMatrix(sub.getData(), 2, 2);
771         for (int i = 0; i < n; ++i) {
772             for (int j = 0; j < n; ++j) {
773                 if ((i < 2) || (i > n - 3) || (j < 2) || (j > n - 3)) {
774                     assertEquals(new Fraction(0), m.getEntry(i, j));
775                 } else {
776                     assertEquals(new Fraction(1), m.getEntry(i, j));
777                 }
778             }
779         }
780         assertEquals(sub, m.getSubMatrix(2, n - 3, 2, n - 3));
781     }
782 
783     @Test
784     void testCopySubMatrix() {
785         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(subTestData);
786         checkCopy(m, subRows23Cols00,  2 , 3 , 0, 0);
787         checkCopy(m, subRows00Cols33,  0 , 0 , 3, 3);
788         checkCopy(m, subRows01Cols23,  0 , 1 , 2, 3);
789         checkCopy(m, subRows02Cols13,  new int[] { 0, 2 }, new int[] { 1, 3 });
790         checkCopy(m, subRows03Cols12,  new int[] { 0, 3 }, new int[] { 1, 2 });
791         checkCopy(m, subRows03Cols123, new int[] { 0, 3 }, new int[] { 1, 2, 3 });
792         checkCopy(m, subRows20Cols123, new int[] { 2, 0 }, new int[] { 1, 2, 3 });
793         checkCopy(m, subRows31Cols31,  new int[] { 3, 1 }, new int[] { 3, 1 });
794         checkCopy(m, subRows31Cols31,  new int[] { 3, 1 }, new int[] { 3, 1 });
795 
796         checkCopy(m, null,  1, 0, 2, 4);
797         checkCopy(m, null, -1, 1, 2, 2);
798         checkCopy(m, null,  1, 0, 2, 2);
799         checkCopy(m, null,  1, 0, 2, 4);
800         checkCopy(m, null, new int[] {}, new int[] { 0 });
801         checkCopy(m, null, new int[] { 0 }, new int[] { 4 });
802     }
803 
804     private void checkCopy(FieldMatrix<Fraction> m, Fraction[][] reference,
805                            int startRow, int endRow, int startColumn, int endColumn) {
806         try {
807             Fraction[][] sub = (reference == null) ?
808                              new Fraction[1][1] :
809                              new Fraction[reference.length][reference[0].length];
810             m.copySubMatrix(startRow, endRow, startColumn, endColumn, sub);
811             if (reference != null) {
812                 assertEquals(new BlockFieldMatrix<Fraction>(reference), new BlockFieldMatrix<Fraction>(sub));
813             } else {
814                 fail("Expecting MathIllegalArgumentException or MathIllegalArgumentException or MathIllegalArgumentException");
815             }
816         } catch (MathIllegalArgumentException e) {
817             if (reference != null) {
818                 throw e;
819             }
820         }
821     }
822 
823     private void checkCopy(FieldMatrix<Fraction> m, Fraction[][] reference,
824                            int[] selectedRows, int[] selectedColumns) {
825         try {
826             Fraction[][] sub = (reference == null) ?
827                     new Fraction[1][1] :
828                     new Fraction[reference.length][reference[0].length];
829             m.copySubMatrix(selectedRows, selectedColumns, sub);
830             if (reference != null) {
831                 assertEquals(new BlockFieldMatrix<Fraction>(reference), new BlockFieldMatrix<Fraction>(sub));
832             } else {
833                 fail("Expecting MathIllegalArgumentException or MathIllegalArgumentException or MathIllegalArgumentException");
834             }
835         } catch (MathIllegalArgumentException e) {
836             if (reference != null) {
837                 throw e;
838             }
839         }
840     }
841 
842     @Test
843     void testGetRowMatrix() {
844         FieldMatrix<Fraction> m     = new BlockFieldMatrix<Fraction>(subTestData);
845         FieldMatrix<Fraction> mRow0 = new BlockFieldMatrix<Fraction>(subRow0);
846         FieldMatrix<Fraction> mRow3 = new BlockFieldMatrix<Fraction>(subRow3);
847         assertEquals(mRow0, m.getRowMatrix(0), "Row0");
848         assertEquals(mRow3, m.getRowMatrix(3), "Row3");
849         try {
850             m.getRowMatrix(-1);
851             fail("Expecting MathIllegalArgumentException");
852         } catch (MathIllegalArgumentException ex) {
853             // expected
854         }
855         try {
856             m.getRowMatrix(4);
857             fail("Expecting MathIllegalArgumentException");
858         } catch (MathIllegalArgumentException ex) {
859             // expected
860         }
861     }
862 
863     @Test
864     void testSetRowMatrix() {
865         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(subTestData);
866         FieldMatrix<Fraction> mRow3 = new BlockFieldMatrix<Fraction>(subRow3);
867         assertNotSame(mRow3, m.getRowMatrix(0));
868         m.setRowMatrix(0, mRow3);
869         assertEquals(mRow3, m.getRowMatrix(0));
870         try {
871             m.setRowMatrix(-1, mRow3);
872             fail("Expecting MathIllegalArgumentException");
873         } catch (MathIllegalArgumentException ex) {
874             // expected
875         }
876         try {
877             m.setRowMatrix(0, m);
878             fail("Expecting MathIllegalArgumentException");
879         } catch (MathIllegalArgumentException ex) {
880             // expected
881         }
882     }
883 
884     @Test
885     void testGetSetRowMatrixLarge() {
886         int n = 3 * BlockFieldMatrix.BLOCK_SIZE;
887         FieldMatrix<Fraction> m =
888             new BlockFieldMatrix<Fraction>(FractionField.getInstance(), n, n);
889         FieldMatrix<Fraction> sub =
890             new BlockFieldMatrix<Fraction>(FractionField.getInstance(), 1, n).scalarAdd(new Fraction(1));
891 
892         m.setRowMatrix(2, sub);
893         for (int i = 0; i < n; ++i) {
894             for (int j = 0; j < n; ++j) {
895                 if (i != 2) {
896                     assertEquals(new Fraction(0), m.getEntry(i, j));
897                 } else {
898                     assertEquals(new Fraction(1), m.getEntry(i, j));
899                 }
900             }
901         }
902         assertEquals(sub, m.getRowMatrix(2));
903 
904     }
905 
906     @Test
907     void testGetColumnMatrix() {
908         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(subTestData);
909         FieldMatrix<Fraction> mColumn1 = new BlockFieldMatrix<Fraction>(subColumn1);
910         FieldMatrix<Fraction> mColumn3 = new BlockFieldMatrix<Fraction>(subColumn3);
911         assertEquals(mColumn1, m.getColumnMatrix(1));
912         assertEquals(mColumn3, m.getColumnMatrix(3));
913         try {
914             m.getColumnMatrix(-1);
915             fail("Expecting MathIllegalArgumentException");
916         } catch (MathIllegalArgumentException ex) {
917             // expected
918         }
919         try {
920             m.getColumnMatrix(4);
921             fail("Expecting MathIllegalArgumentException");
922         } catch (MathIllegalArgumentException ex) {
923             // expected
924         }
925     }
926 
927     @Test
928     void testSetColumnMatrix() {
929         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(subTestData);
930         FieldMatrix<Fraction> mColumn3 = new BlockFieldMatrix<Fraction>(subColumn3);
931         assertNotSame(mColumn3, m.getColumnMatrix(1));
932         m.setColumnMatrix(1, mColumn3);
933         assertEquals(mColumn3, m.getColumnMatrix(1));
934         try {
935             m.setColumnMatrix(-1, mColumn3);
936             fail("Expecting MathIllegalArgumentException");
937         } catch (MathIllegalArgumentException ex) {
938             // expected
939         }
940         try {
941             m.setColumnMatrix(0, m);
942             fail("Expecting MathIllegalArgumentException");
943         } catch (MathIllegalArgumentException ex) {
944             // expected
945         }
946     }
947 
948     @Test
949     void testGetSetColumnMatrixLarge() {
950         int n = 3 * BlockFieldMatrix.BLOCK_SIZE;
951         FieldMatrix<Fraction> m =
952             new BlockFieldMatrix<Fraction>(FractionField.getInstance(), n, n);
953         FieldMatrix<Fraction> sub =
954             new BlockFieldMatrix<Fraction>(FractionField.getInstance(), n, 1).scalarAdd(new Fraction(1));
955 
956         m.setColumnMatrix(2, sub);
957         for (int i = 0; i < n; ++i) {
958             for (int j = 0; j < n; ++j) {
959                 if (j != 2) {
960                     assertEquals(new Fraction(0), m.getEntry(i, j));
961                 } else {
962                     assertEquals(new Fraction(1), m.getEntry(i, j));
963                 }
964             }
965         }
966         assertEquals(sub, m.getColumnMatrix(2));
967 
968     }
969 
970     @Test
971     void testGetRowVector() {
972         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(subTestData);
973         FieldVector<Fraction> mRow0 = new ArrayFieldVector<Fraction>(subRow0[0]);
974         FieldVector<Fraction> mRow3 = new ArrayFieldVector<Fraction>(subRow3[0]);
975         assertEquals(mRow0, m.getRowVector(0));
976         assertEquals(mRow3, m.getRowVector(3));
977         try {
978             m.getRowVector(-1);
979             fail("Expecting MathIllegalArgumentException");
980         } catch (MathIllegalArgumentException ex) {
981             // expected
982         }
983         try {
984             m.getRowVector(4);
985             fail("Expecting MathIllegalArgumentException");
986         } catch (MathIllegalArgumentException ex) {
987             // expected
988         }
989     }
990 
991     @Test
992     void testSetRowVector() {
993         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(subTestData);
994         FieldVector<Fraction> mRow3 = new ArrayFieldVector<Fraction>(subRow3[0]);
995         assertNotSame(mRow3, m.getRowMatrix(0));
996         m.setRowVector(0, mRow3);
997         assertEquals(mRow3, m.getRowVector(0));
998         try {
999             m.setRowVector(-1, mRow3);
1000             fail("Expecting MathIllegalArgumentException");
1001         } catch (MathIllegalArgumentException ex) {
1002             // expected
1003         }
1004         try {
1005             m.setRowVector(0, new ArrayFieldVector<Fraction>(FractionField.getInstance(), 5));
1006             fail("Expecting MathIllegalArgumentException");
1007         } catch (MathIllegalArgumentException ex) {
1008             // expected
1009         }
1010     }
1011 
1012     @Test
1013     void testGetSetRowVectorLarge() {
1014         int n = 3 * BlockFieldMatrix.BLOCK_SIZE;
1015         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(FractionField.getInstance(), n, n);
1016         FieldVector<Fraction> sub = new ArrayFieldVector<Fraction>(n, new Fraction(1));
1017 
1018         m.setRowVector(2, sub);
1019         for (int i = 0; i < n; ++i) {
1020             for (int j = 0; j < n; ++j) {
1021                 if (i != 2) {
1022                     assertEquals(new Fraction(0), m.getEntry(i, j));
1023                 } else {
1024                     assertEquals(new Fraction(1), m.getEntry(i, j));
1025                 }
1026             }
1027         }
1028         assertEquals(sub, m.getRowVector(2));
1029 
1030     }
1031 
1032     @Test
1033     void testGetColumnVector() {
1034         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(subTestData);
1035         FieldVector<Fraction> mColumn1 = columnToVector(subColumn1);
1036         FieldVector<Fraction> mColumn3 = columnToVector(subColumn3);
1037         assertEquals(mColumn1, m.getColumnVector(1));
1038         assertEquals(mColumn3, m.getColumnVector(3));
1039         try {
1040             m.getColumnVector(-1);
1041             fail("Expecting MathIllegalArgumentException");
1042         } catch (MathIllegalArgumentException ex) {
1043             // expected
1044         }
1045         try {
1046             m.getColumnVector(4);
1047             fail("Expecting MathIllegalArgumentException");
1048         } catch (MathIllegalArgumentException ex) {
1049             // expected
1050         }
1051     }
1052 
1053     @Test
1054     void testSetColumnVector() {
1055         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(subTestData);
1056         FieldVector<Fraction> mColumn3 = columnToVector(subColumn3);
1057         assertNotSame(mColumn3, m.getColumnVector(1));
1058         m.setColumnVector(1, mColumn3);
1059         assertEquals(mColumn3, m.getColumnVector(1));
1060         try {
1061             m.setColumnVector(-1, mColumn3);
1062             fail("Expecting MathIllegalArgumentException");
1063         } catch (MathIllegalArgumentException ex) {
1064             // expected
1065         }
1066         try {
1067             m.setColumnVector(0, new ArrayFieldVector<Fraction>(FractionField.getInstance(), 5));
1068             fail("Expecting MathIllegalArgumentException");
1069         } catch (MathIllegalArgumentException ex) {
1070             // expected
1071         }
1072     }
1073 
1074     @Test
1075     void testGetSetColumnVectorLarge() {
1076         int n = 3 * BlockFieldMatrix.BLOCK_SIZE;
1077         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(FractionField.getInstance(), n, n);
1078         FieldVector<Fraction> sub = new ArrayFieldVector<Fraction>(n, new Fraction(1));
1079 
1080         m.setColumnVector(2, sub);
1081         for (int i = 0; i < n; ++i) {
1082             for (int j = 0; j < n; ++j) {
1083                 if (j != 2) {
1084                     assertEquals(new Fraction(0), m.getEntry(i, j));
1085                 } else {
1086                     assertEquals(new Fraction(1), m.getEntry(i, j));
1087                 }
1088             }
1089         }
1090         assertEquals(sub, m.getColumnVector(2));
1091 
1092     }
1093 
1094     private FieldVector<Fraction> columnToVector(Fraction[][] column) {
1095         Fraction[] data = new Fraction[column.length];
1096         for (int i = 0; i < data.length; ++i) {
1097             data[i] = column[i][0];
1098         }
1099         return new ArrayFieldVector<Fraction>(data, false);
1100     }
1101 
1102     @Test
1103     void testGetRow() {
1104         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(subTestData);
1105         checkArrays(subRow0[0], m.getRow(0));
1106         checkArrays(subRow3[0], m.getRow(3));
1107         try {
1108             m.getRow(-1);
1109             fail("Expecting MathIllegalArgumentException");
1110         } catch (MathIllegalArgumentException ex) {
1111             // expected
1112         }
1113         try {
1114             m.getRow(4);
1115             fail("Expecting MathIllegalArgumentException");
1116         } catch (MathIllegalArgumentException ex) {
1117             // expected
1118         }
1119     }
1120 
1121     @Test
1122     void testSetRow() {
1123         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(subTestData);
1124         assertTrue(subRow3[0][0] != m.getRow(0)[0]);
1125         m.setRow(0, subRow3[0]);
1126         checkArrays(subRow3[0], m.getRow(0));
1127         try {
1128             m.setRow(-1, subRow3[0]);
1129             fail("Expecting MathIllegalArgumentException");
1130         } catch (MathIllegalArgumentException ex) {
1131             // expected
1132         }
1133         try {
1134             m.setRow(0, new Fraction[5]);
1135             fail("Expecting MathIllegalArgumentException");
1136         } catch (MathIllegalArgumentException ex) {
1137             // expected
1138         }
1139     }
1140 
1141     @Test
1142     void testGetSetRowLarge() {
1143         int n = 3 * BlockFieldMatrix.BLOCK_SIZE;
1144         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(FractionField.getInstance(), n, n);
1145         Fraction[] sub = new Fraction[n];
1146         Arrays.fill(sub, new Fraction(1));
1147 
1148         m.setRow(2, sub);
1149         for (int i = 0; i < n; ++i) {
1150             for (int j = 0; j < n; ++j) {
1151                 if (i != 2) {
1152                     assertEquals(new Fraction(0), m.getEntry(i, j));
1153                 } else {
1154                     assertEquals(new Fraction(1), m.getEntry(i, j));
1155                 }
1156             }
1157         }
1158         checkArrays(sub, m.getRow(2));
1159 
1160     }
1161 
1162     @Test
1163     void testGetColumn() {
1164         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(subTestData);
1165         Fraction[] mColumn1 = columnToArray(subColumn1);
1166         Fraction[] mColumn3 = columnToArray(subColumn3);
1167         checkArrays(mColumn1, m.getColumn(1));
1168         checkArrays(mColumn3, m.getColumn(3));
1169         try {
1170             m.getColumn(-1);
1171             fail("Expecting MathIllegalArgumentException");
1172         } catch (MathIllegalArgumentException ex) {
1173             // expected
1174         }
1175         try {
1176             m.getColumn(4);
1177             fail("Expecting MathIllegalArgumentException");
1178         } catch (MathIllegalArgumentException ex) {
1179             // expected
1180         }
1181     }
1182 
1183     @Test
1184     void testSetColumn() {
1185         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(subTestData);
1186         Fraction[] mColumn3 = columnToArray(subColumn3);
1187         assertTrue(mColumn3[0] != m.getColumn(1)[0]);
1188         m.setColumn(1, mColumn3);
1189         checkArrays(mColumn3, m.getColumn(1));
1190         try {
1191             m.setColumn(-1, mColumn3);
1192             fail("Expecting MathIllegalArgumentException");
1193         } catch (MathIllegalArgumentException ex) {
1194             // expected
1195         }
1196         try {
1197             m.setColumn(0, new Fraction[5]);
1198             fail("Expecting MathIllegalArgumentException");
1199         } catch (MathIllegalArgumentException ex) {
1200             // expected
1201         }
1202     }
1203 
1204     @Test
1205     void testGetSetColumnLarge() {
1206         int n = 3 * BlockFieldMatrix.BLOCK_SIZE;
1207         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(FractionField.getInstance(), n, n);
1208         Fraction[] sub = new Fraction[n];
1209         Arrays.fill(sub, new Fraction(1));
1210 
1211         m.setColumn(2, sub);
1212         for (int i = 0; i < n; ++i) {
1213             for (int j = 0; j < n; ++j) {
1214                 if (j != 2) {
1215                     assertEquals(new Fraction(0), m.getEntry(i, j));
1216                 } else {
1217                     assertEquals(new Fraction(1), m.getEntry(i, j));
1218                 }
1219             }
1220         }
1221         checkArrays(sub, m.getColumn(2));
1222 
1223     }
1224 
1225     private Fraction[] columnToArray(Fraction[][] column) {
1226         Fraction[] data = new Fraction[column.length];
1227         for (int i = 0; i < data.length; ++i) {
1228             data[i] = column[i][0];
1229         }
1230         return data;
1231     }
1232 
1233     private void checkArrays(Fraction[] expected, Fraction[] actual) {
1234         assertEquals(expected.length, actual.length);
1235         for (int i = 0; i < expected.length; ++i) {
1236             assertEquals(expected[i], actual[i]);
1237         }
1238     }
1239 
1240     @Test
1241     void testEqualsAndHashCode() {
1242         BlockFieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(testData);
1243         BlockFieldMatrix<Fraction> m1 = (BlockFieldMatrix<Fraction>) m.copy();
1244         BlockFieldMatrix<Fraction> mt = (BlockFieldMatrix<Fraction>) m.transpose();
1245         assertTrue(m.hashCode() != mt.hashCode());
1246         assertEquals(m.hashCode(), m1.hashCode());
1247         assertEquals(m, m);
1248         assertEquals(m, m1);
1249         assertNotEquals(null, m);
1250         assertNotEquals(m, mt);
1251         assertNotEquals(m, new BlockFieldMatrix<Fraction>(bigSingular));
1252     }
1253 
1254     @Test
1255     void testToString() {
1256         BlockFieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(testData);
1257         assertEquals("BlockFieldMatrix{{1,2,3},{2,5,3},{1,0,8}}", m.toString());
1258     }
1259 
1260     @Test
1261     void testSetSubMatrix() {
1262         BlockFieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(testData);
1263         m.setSubMatrix(detData2,1,1);
1264         FieldMatrix<Fraction> expected = new BlockFieldMatrix<Fraction>
1265             (new Fraction[][] {{new Fraction(1),new Fraction(2),new Fraction(3)},{new Fraction(2),new Fraction(1),new Fraction(3)},{new Fraction(1),new Fraction(2),new Fraction(4)}});
1266         assertEquals(expected, m);
1267 
1268         m.setSubMatrix(detData2,0,0);
1269         expected = new BlockFieldMatrix<Fraction>
1270             (new Fraction[][] {{new Fraction(1),new Fraction(3),new Fraction(3)},{new Fraction(2),new Fraction(4),new Fraction(3)},{new Fraction(1),new Fraction(2),new Fraction(4)}});
1271         assertEquals(expected, m);
1272 
1273         m.setSubMatrix(testDataPlus2,0,0);
1274         expected = new BlockFieldMatrix<Fraction>
1275             (new Fraction[][] {{new Fraction(3),new Fraction(4),new Fraction(5)},{new Fraction(4),new Fraction(7),new Fraction(5)},{new Fraction(3),new Fraction(2),new Fraction(10)}});
1276         assertEquals(expected, m);
1277 
1278         // javadoc example
1279         BlockFieldMatrix<Fraction> matrix =
1280             new BlockFieldMatrix<Fraction>(new Fraction[][] {
1281                     {new Fraction(1), new Fraction(2), new Fraction(3), new Fraction(4)},
1282                     {new Fraction(5), new Fraction(6), new Fraction(7), new Fraction(8)},
1283                     {new Fraction(9), new Fraction(0), new Fraction(1) , new Fraction(2)}
1284             });
1285         matrix.setSubMatrix(new Fraction[][] {
1286                 {new Fraction(3), new Fraction(4)},
1287                 {new Fraction(5), new Fraction(6)}
1288         }, 1, 1);
1289         expected =
1290             new BlockFieldMatrix<Fraction>(new Fraction[][] {
1291                     {new Fraction(1), new Fraction(2), new Fraction(3),new Fraction(4)},
1292                     {new Fraction(5), new Fraction(3), new Fraction(4), new Fraction(8)},
1293                     {new Fraction(9), new Fraction(5) ,new Fraction(6), new Fraction(2)}
1294             });
1295         assertEquals(expected, matrix);
1296 
1297         // dimension overflow
1298         try {
1299             m.setSubMatrix(testData,1,1);
1300             fail("expecting MathIllegalArgumentException");
1301         } catch (MathIllegalArgumentException e) {
1302             // expected
1303         }
1304         // dimension underflow
1305         try {
1306             m.setSubMatrix(testData,-1,1);
1307             fail("expecting MathIllegalArgumentException");
1308         } catch (MathIllegalArgumentException e) {
1309             // expected
1310         }
1311         try {
1312             m.setSubMatrix(testData,1,-1);
1313             fail("expecting MathIllegalArgumentException");
1314         } catch (MathIllegalArgumentException e) {
1315             // expected
1316         }
1317 
1318         // null
1319         try {
1320             m.setSubMatrix(null,1,1);
1321             fail("expecting NullArgumentException");
1322         } catch (NullArgumentException e) {
1323             // expected
1324         }
1325 
1326         // ragged
1327         try {
1328             m.setSubMatrix(new Fraction[][] {{new Fraction(1)}, {new Fraction(2), new Fraction(3)}}, 0, 0);
1329             fail("expecting MathIllegalArgumentException");
1330         } catch (MathIllegalArgumentException e) {
1331             // expected
1332         }
1333 
1334         // empty
1335         try {
1336             m.setSubMatrix(new Fraction[][] {{}}, 0, 0);
1337             fail("expecting MathIllegalArgumentException");
1338         } catch (MathIllegalArgumentException e) {
1339             // expected
1340         }
1341     }
1342 
1343     @Test
1344     void testWalk() {
1345         int rows    = 150;
1346         int columns = 75;
1347 
1348         FieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(FractionField.getInstance(), rows, columns);
1349         m.walkInRowOrder(new SetVisitor());
1350         GetVisitor getVisitor = new GetVisitor();
1351         m.walkInOptimizedOrder(getVisitor);
1352         assertEquals(rows * columns, getVisitor.getCount());
1353 
1354         m = new BlockFieldMatrix<Fraction>(FractionField.getInstance(), rows, columns);
1355         m.walkInRowOrder(new SetVisitor(), 1, rows - 2, 1, columns - 2);
1356         getVisitor = new GetVisitor();
1357         m.walkInOptimizedOrder(getVisitor, 1, rows - 2, 1, columns - 2);
1358         assertEquals((rows - 2) * (columns - 2), getVisitor.getCount());
1359         for (int i = 0; i < rows; ++i) {
1360             assertEquals(new Fraction(0), m.getEntry(i, 0));
1361             assertEquals(new Fraction(0), m.getEntry(i, columns - 1));
1362         }
1363         for (int j = 0; j < columns; ++j) {
1364             assertEquals(new Fraction(0), m.getEntry(0, j));
1365             assertEquals(new Fraction(0), m.getEntry(rows - 1, j));
1366         }
1367 
1368         m = new BlockFieldMatrix<Fraction>(FractionField.getInstance(), rows, columns);
1369         m.walkInColumnOrder(new SetVisitor());
1370         getVisitor = new GetVisitor();
1371         m.walkInOptimizedOrder(getVisitor);
1372         assertEquals(rows * columns, getVisitor.getCount());
1373 
1374         m = new BlockFieldMatrix<Fraction>(FractionField.getInstance(), rows, columns);
1375         m.walkInColumnOrder(new SetVisitor(), 1, rows - 2, 1, columns - 2);
1376         getVisitor = new GetVisitor();
1377         m.walkInOptimizedOrder(getVisitor, 1, rows - 2, 1, columns - 2);
1378         assertEquals((rows - 2) * (columns - 2), getVisitor.getCount());
1379         for (int i = 0; i < rows; ++i) {
1380             assertEquals(new Fraction(0), m.getEntry(i, 0));
1381             assertEquals(new Fraction(0), m.getEntry(i, columns - 1));
1382         }
1383         for (int j = 0; j < columns; ++j) {
1384             assertEquals(new Fraction(0), m.getEntry(0, j));
1385             assertEquals(new Fraction(0), m.getEntry(rows - 1, j));
1386         }
1387 
1388         m = new BlockFieldMatrix<Fraction>(FractionField.getInstance(), rows, columns);
1389         m.walkInOptimizedOrder(new SetVisitor());
1390         getVisitor = new GetVisitor();
1391         m.walkInRowOrder(getVisitor);
1392         assertEquals(rows * columns, getVisitor.getCount());
1393 
1394         m = new BlockFieldMatrix<Fraction>(FractionField.getInstance(), rows, columns);
1395         m.walkInOptimizedOrder(new SetVisitor(), 1, rows - 2, 1, columns - 2);
1396         getVisitor = new GetVisitor();
1397         m.walkInRowOrder(getVisitor, 1, rows - 2, 1, columns - 2);
1398         assertEquals((rows - 2) * (columns - 2), getVisitor.getCount());
1399         for (int i = 0; i < rows; ++i) {
1400             assertEquals(new Fraction(0), m.getEntry(i, 0));
1401             assertEquals(new Fraction(0), m.getEntry(i, columns - 1));
1402         }
1403         for (int j = 0; j < columns; ++j) {
1404             assertEquals(new Fraction(0), m.getEntry(0, j));
1405             assertEquals(new Fraction(0), m.getEntry(rows - 1, j));
1406         }
1407 
1408         m = new BlockFieldMatrix<Fraction>(FractionField.getInstance(), rows, columns);
1409         m.walkInOptimizedOrder(new SetVisitor());
1410         getVisitor = new GetVisitor();
1411         m.walkInColumnOrder(getVisitor);
1412         assertEquals(rows * columns, getVisitor.getCount());
1413 
1414         m = new BlockFieldMatrix<Fraction>(FractionField.getInstance(), rows, columns);
1415         m.walkInOptimizedOrder(new SetVisitor(), 1, rows - 2, 1, columns - 2);
1416         getVisitor = new GetVisitor();
1417         m.walkInColumnOrder(getVisitor, 1, rows - 2, 1, columns - 2);
1418         assertEquals((rows - 2) * (columns - 2), getVisitor.getCount());
1419         for (int i = 0; i < rows; ++i) {
1420             assertEquals(new Fraction(0), m.getEntry(i, 0));
1421             assertEquals(new Fraction(0), m.getEntry(i, columns - 1));
1422         }
1423         for (int j = 0; j < columns; ++j) {
1424             assertEquals(new Fraction(0), m.getEntry(0, j));
1425             assertEquals(new Fraction(0), m.getEntry(rows - 1, j));
1426         }
1427 
1428     }
1429 
1430     @Test
1431     void testSerial()  {
1432         BlockFieldMatrix<Fraction> m = new BlockFieldMatrix<Fraction>(testData);
1433         assertEquals(m,UnitTestUtils.serializeAndRecover(m));
1434     }
1435 
1436     private static class SetVisitor extends DefaultFieldMatrixChangingVisitor<Fraction> {
1437         public SetVisitor() {
1438             super(Fraction.ZERO);
1439         }
1440         @Override
1441         public Fraction visit(int i, int j, Fraction value) {
1442             return new Fraction(i * 11 + j, 11);
1443         }
1444     }
1445 
1446     private static class GetVisitor extends DefaultFieldMatrixPreservingVisitor<Fraction> {
1447         private int count;
1448         public GetVisitor() {
1449             super(Fraction.ZERO);
1450             count = 0;
1451         }
1452         @Override
1453         public void visit(int i, int j, Fraction value) {
1454             ++count;
1455             assertEquals(new Fraction(i * 11 + j, 11), value);
1456         }
1457         public int getCount() {
1458             return count;
1459         }
1460     }
1461 
1462     private BlockFieldMatrix<Fraction> createRandomMatrix(Random r, int rows, int columns) {
1463         BlockFieldMatrix<Fraction> m =
1464             new BlockFieldMatrix<Fraction>(FractionField.getInstance(), rows, columns);
1465         for (int i = 0; i < rows; ++i) {
1466             for (int j = 0; j < columns; ++j) {
1467                 int p = r.nextInt(20) - 10;
1468                 int q = r.nextInt(20) - 10;
1469                 if (q == 0) {
1470                     q = 1;
1471                 }
1472                 m.setEntry(i, j, new Fraction(p, q));
1473             }
1474         }
1475         return m;
1476     }
1477 }
1478