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