001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     * 
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.math.linear;
018    
019    import java.util.Arrays;
020    import java.util.Random;
021    
022    import junit.framework.Test;
023    import junit.framework.TestCase;
024    import junit.framework.TestSuite;
025    
026    import org.apache.commons.math.TestUtils;
027    import org.apache.commons.math.fraction.Fraction;
028    import org.apache.commons.math.fraction.FractionField;
029    
030    /**
031     * Test cases for the {@link BlockFieldMatrix} class.
032     *
033     * @version $Revision: 790243 $ $Date: 2009-07-01 12:03:28 -0400 (Wed, 01 Jul 2009) $
034     */
035    
036    public final class BlockFieldMatrixTest extends TestCase {
037        
038        // 3 x 3 identity matrix
039        protected Fraction[][] id = {
040                {new Fraction(1),new Fraction(0),new Fraction(0)},
041                {new Fraction(0),new Fraction(1),new Fraction(0)},
042                {new Fraction(0),new Fraction(0),new Fraction(1)}
043        };
044        
045        // Test data for group operations
046        protected Fraction[][] testData = {
047                {new Fraction(1),new Fraction(2),new Fraction(3)},
048                {new Fraction(2),new Fraction(5),new Fraction(3)},
049                {new Fraction(1),new Fraction(0),new Fraction(8)}
050        };
051        protected Fraction[][] testDataLU = {
052                {new Fraction(2), new Fraction(5), new Fraction(3)},
053                {new Fraction(1, 2), new Fraction(-5, 2), new Fraction(13, 2)},
054                {new Fraction(1, 2), new Fraction(1, 5), new Fraction(1, 5)}
055        };
056        protected Fraction[][] testDataPlus2 = {
057                {new Fraction(3),new Fraction(4),new Fraction(5)},
058                {new Fraction(4),new Fraction(7),new Fraction(5)},
059                {new Fraction(3),new Fraction(2),new Fraction(10)}
060        };
061        protected Fraction[][] testDataMinus = {
062                {new Fraction(-1),new Fraction(-2),new Fraction(-3)},
063                {new Fraction(-2),new Fraction(-5),new Fraction(-3)}, 
064                {new Fraction(-1),new Fraction(0),new Fraction(-8)}
065        };
066        protected Fraction[] testDataRow1 = {new Fraction(1),new Fraction(2),new Fraction(3)};
067        protected Fraction[] testDataCol3 = {new Fraction(3),new Fraction(3),new Fraction(8)};
068        protected Fraction[][] testDataInv = {
069                {new Fraction(-40),new Fraction(16),new Fraction(9)},
070                {new Fraction(13),new Fraction(-5),new Fraction(-3)},
071                {new Fraction(5),new Fraction(-2),new Fraction(-1)}
072        };
073        protected Fraction[] preMultTest = {new Fraction(8), new Fraction(12), new Fraction(33)};
074        protected Fraction[][] testData2 = {
075                {new Fraction(1),new Fraction(2),new Fraction(3)},
076                {new Fraction(2),new Fraction(5),new Fraction(3)}
077        };
078        protected Fraction[][] testData2T = {
079                {new Fraction(1),new Fraction(2)},
080                {new Fraction(2),new Fraction(5)},
081                {new Fraction(3),new Fraction(3)}
082        };
083        protected Fraction[][] testDataPlusInv = {
084                {new Fraction(-39),new Fraction(18),new Fraction(12)},
085                {new Fraction(15),new Fraction(0),new Fraction(0)},
086                {new Fraction(6),new Fraction(-2),new Fraction(7)}
087        };
088        
089        // lu decomposition tests
090        protected Fraction[][] luData = {
091                {new Fraction(2),new Fraction(3),new Fraction(3)},
092                {new Fraction(0),new Fraction(5),new Fraction(7)},
093                {new Fraction(6),new Fraction(9),new Fraction(8)}
094        };
095        protected Fraction[][] luDataLUDecomposition = {
096                {new Fraction(6),new Fraction(9),new Fraction(8)},
097                {new Fraction(0),new Fraction(5),new Fraction(7)},
098                {new Fraction(1, 3),new Fraction(0),new Fraction(1, 3)}
099        };
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