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