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