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 junit.framework.Test;
020    import junit.framework.TestCase;
021    import junit.framework.TestSuite;
022    
023    import org.apache.commons.math.TestUtils;
024    import org.apache.commons.math.fraction.Fraction;
025    import org.apache.commons.math.fraction.FractionField;
026    
027    /**
028     * Test cases for the {@link Array2DRowFieldMatrix} class.
029     *
030     * @version $Revision: 790243 $ $Date: 2009-07-01 12:03:28 -0400 (Wed, 01 Jul 2009) $
031     */
032    
033    public final class FieldMatrixImplTest extends TestCase {
034        
035        // 3 x 3 identity matrix
036        protected Fraction[][] id = { {new Fraction(1),new Fraction(0),new Fraction(0)}, {new Fraction(0),new Fraction(1),new Fraction(0)}, {new Fraction(0),new Fraction(0),new Fraction(1)} };
037        
038        // Test data for group operations
039        protected Fraction[][] testData = { {new Fraction(1),new Fraction(2),new Fraction(3)}, {new Fraction(2),new Fraction(5),new Fraction(3)}, {new Fraction(1),new Fraction(0),new Fraction(8)} };
040        protected Fraction[][] testDataLU = {{new Fraction(2), new Fraction(5), new Fraction(3)}, {new Fraction(1, 2), new Fraction(-5, 2), new Fraction(13, 2)}, {new Fraction(1, 2), new Fraction(1, 5), new Fraction(1, 5)}};
041        protected Fraction[][] testDataPlus2 = { {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)} };
042        protected Fraction[][] testDataMinus = { {new Fraction(-1),new Fraction(-2),new Fraction(-3)}, {new Fraction(-2),new Fraction(-5),new Fraction(-3)}, 
043           {new Fraction(-1),new Fraction(0),new Fraction(-8)} };
044        protected Fraction[] testDataRow1 = {new Fraction(1),new Fraction(2),new Fraction(3)};
045        protected Fraction[] testDataCol3 = {new Fraction(3),new Fraction(3),new Fraction(8)};
046        protected Fraction[][] testDataInv = 
047            { {new Fraction(-40),new Fraction(16),new Fraction(9)}, {new Fraction(13),new Fraction(-5),new Fraction(-3)}, {new Fraction(5),new Fraction(-2),new Fraction(-1)} };
048        protected Fraction[] preMultTest = {new Fraction(8),new Fraction(12),new Fraction(33)};
049        protected Fraction[][] testData2 ={ {new Fraction(1),new Fraction(2),new Fraction(3)}, {new Fraction(2),new Fraction(5),new Fraction(3)}};
050        protected Fraction[][] testData2T = { {new Fraction(1),new Fraction(2)}, {new Fraction(2),new Fraction(5)}, {new Fraction(3),new Fraction(3)}};
051        protected Fraction[][] testDataPlusInv = 
052            { {new Fraction(-39),new Fraction(18),new Fraction(12)}, {new Fraction(15),new Fraction(0),new Fraction(0)}, {new Fraction(6),new Fraction(-2),new Fraction(7)} };
053        
054        // lu decomposition tests
055        protected Fraction[][] luData = { {new Fraction(2),new Fraction(3),new Fraction(3)}, {new Fraction(0),new Fraction(5),new Fraction(7)}, {new Fraction(6),new Fraction(9),new Fraction(8)} };
056        protected Fraction[][] luDataLUDecomposition = { {new Fraction(6),new Fraction(9),new Fraction(8)}, {new Fraction(0),new Fraction(5),new Fraction(7)},
057                {new Fraction(1, 3),new Fraction(0),new Fraction(1, 3)} };
058        
059        // singular matrices
060        protected Fraction[][] singular = { {new Fraction(2),new Fraction(3)}, {new Fraction(2),new Fraction(3)} };
061        protected Fraction[][] bigSingular = {{new Fraction(1),new Fraction(2),new Fraction(3),new Fraction(4)}, {new Fraction(2),new Fraction(5),new Fraction(3),new Fraction(4)},
062            {new Fraction(7),new Fraction(3),new Fraction(256),new Fraction(1930)}, {new Fraction(3),new Fraction(7),new Fraction(6),new Fraction(8)}}; // 4th row = 1st + 2nd
063        protected Fraction[][] detData = { {new Fraction(1),new Fraction(2),new Fraction(3)}, {new Fraction(4),new Fraction(5),new Fraction(6)}, {new Fraction(7),new Fraction(8),new Fraction(10)} };
064        protected Fraction[][] detData2 = { {new Fraction(1), new Fraction(3)}, {new Fraction(2), new Fraction(4)}};
065        
066        // vectors
067        protected Fraction[] testVector = {new Fraction(1),new Fraction(2),new Fraction(3)};
068        protected Fraction[] testVector2 = {new Fraction(1),new Fraction(2),new Fraction(3),new Fraction(4)};
069        
070        // submatrix accessor tests
071        protected Fraction[][] subTestData = {{new Fraction(1), new Fraction(2), new Fraction(3), new Fraction(4)}, {new Fraction(3, 2), new Fraction(5, 2), new Fraction(7, 2), new Fraction(9, 2)},
072                {new Fraction(2), new Fraction(4), new Fraction(6), new Fraction(8)}, {new Fraction(4), new Fraction(5), new Fraction(6), new Fraction(7)}}; 
073        // array selections
074        protected Fraction[][] subRows02Cols13 = { {new Fraction(2), new Fraction(4)}, {new Fraction(4), new Fraction(8)}};
075        protected Fraction[][] subRows03Cols12 = { {new Fraction(2), new Fraction(3)}, {new Fraction(5), new Fraction(6)}};
076        protected Fraction[][] subRows03Cols123 = { {new Fraction(2), new Fraction(3), new Fraction(4)} , {new Fraction(5), new Fraction(6), new Fraction(7)}};
077        // effective permutations
078        protected Fraction[][] subRows20Cols123 = { {new Fraction(4), new Fraction(6), new Fraction(8)} , {new Fraction(2), new Fraction(3), new Fraction(4)}};
079        protected Fraction[][] subRows31Cols31 = {{new Fraction(7), new Fraction(5)}, {new Fraction(9, 2), new Fraction(5, 2)}};
080        // contiguous ranges
081        protected Fraction[][] subRows01Cols23 = {{new Fraction(3),new Fraction(4)} , {new Fraction(7, 2), new Fraction(9, 2)}};
082        protected Fraction[][] subRows23Cols00 = {{new Fraction(2)} , {new Fraction(4)}};
083        protected Fraction[][] subRows00Cols33 = {{new Fraction(4)}};
084        // row matrices
085        protected Fraction[][] subRow0 = {{new Fraction(1),new Fraction(2),new Fraction(3),new Fraction(4)}};
086        protected Fraction[][] subRow3 = {{new Fraction(4),new Fraction(5),new Fraction(6),new Fraction(7)}};
087        // column matrices
088        protected Fraction[][] subColumn1 = {{new Fraction(2)}, {new Fraction(5, 2)}, {new Fraction(4)}, {new Fraction(5)}};
089        protected Fraction[][] subColumn3 = {{new Fraction(4)}, {new Fraction(9, 2)}, {new Fraction(8)}, {new Fraction(7)}};
090        
091        // tolerances
092        protected double entryTolerance = 10E-16;
093        protected double normTolerance = 10E-14;
094        
095        public FieldMatrixImplTest(String name) {
096            super(name);
097        }
098        
099        public static Test suite() {
100            TestSuite suite = new TestSuite(FieldMatrixImplTest.class);
101            suite.setName("Array2DRowFieldMatrix<Fraction> Tests");
102            return suite;
103        }
104        
105        /** test dimensions */
106        public void testDimensions() {
107            Array2DRowFieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(testData);
108            Array2DRowFieldMatrix<Fraction> m2 = new Array2DRowFieldMatrix<Fraction>(testData2);
109            assertEquals("testData row dimension",3,m.getRowDimension());
110            assertEquals("testData column dimension",3,m.getColumnDimension());
111            assertTrue("testData is square",m.isSquare());
112            assertEquals("testData2 row dimension",m2.getRowDimension(),2);
113            assertEquals("testData2 column dimension",m2.getColumnDimension(),3);
114            assertTrue("testData2 is not square",!m2.isSquare());
115        } 
116        
117        /** test copy functions */
118        public void testCopyFunctions() {
119            Array2DRowFieldMatrix<Fraction> m1 = new Array2DRowFieldMatrix<Fraction>(testData);
120            Array2DRowFieldMatrix<Fraction> m2 = new Array2DRowFieldMatrix<Fraction>(m1.getData());
121            assertEquals(m2,m1);
122            Array2DRowFieldMatrix<Fraction> m3 = new Array2DRowFieldMatrix<Fraction>(testData);
123            Array2DRowFieldMatrix<Fraction> m4 = new Array2DRowFieldMatrix<Fraction>(m3.getData(), false);
124            assertEquals(m4,m3);
125        }           
126        
127        /** test add */
128        public void testAdd() {
129            Array2DRowFieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(testData);
130            Array2DRowFieldMatrix<Fraction> mInv = new Array2DRowFieldMatrix<Fraction>(testDataInv);
131            FieldMatrix<Fraction> mPlusMInv = m.add(mInv);
132            Fraction[][] sumEntries = mPlusMInv.getData();
133            for (int row = 0; row < m.getRowDimension(); row++) {
134                for (int col = 0; col < m.getColumnDimension(); col++) {
135                    assertEquals(testDataPlusInv[row][col],sumEntries[row][col]);
136                }
137            }    
138        }
139        
140        /** test add failure */
141        public void testAddFail() {
142            Array2DRowFieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(testData);
143            Array2DRowFieldMatrix<Fraction> m2 = new Array2DRowFieldMatrix<Fraction>(testData2);
144            try {
145                m.add(m2);
146                fail("IllegalArgumentException expected");
147            } catch (IllegalArgumentException ex) {
148                // ignored
149            }
150        }
151        
152         /** test m-n = m + -n */
153        public void testPlusMinus() {
154            Array2DRowFieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(testData);
155            Array2DRowFieldMatrix<Fraction> m2 = new Array2DRowFieldMatrix<Fraction>(testDataInv);
156            TestUtils.assertEquals(m.subtract(m2),m2.scalarMultiply(new Fraction(-1)).add(m));        
157            try {
158                m.subtract(new Array2DRowFieldMatrix<Fraction>(testData2));
159                fail("Expecting illegalArgumentException");
160            } catch (IllegalArgumentException ex) {
161                // ignored
162            }      
163        }
164       
165        /** test multiply */
166         public void testMultiply() {
167            Array2DRowFieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(testData);
168            Array2DRowFieldMatrix<Fraction> mInv = new Array2DRowFieldMatrix<Fraction>(testDataInv);
169            Array2DRowFieldMatrix<Fraction> identity = new Array2DRowFieldMatrix<Fraction>(id);
170            Array2DRowFieldMatrix<Fraction> m2 = new Array2DRowFieldMatrix<Fraction>(testData2);
171            TestUtils.assertEquals(m.multiply(mInv), identity);
172            TestUtils.assertEquals(mInv.multiply(m), identity);
173            TestUtils.assertEquals(m.multiply(identity), m);
174            TestUtils.assertEquals(identity.multiply(mInv), mInv);
175            TestUtils.assertEquals(m2.multiply(identity), m2); 
176            try {
177                m.multiply(new Array2DRowFieldMatrix<Fraction>(bigSingular));
178                fail("Expecting illegalArgumentException");
179            } catch (IllegalArgumentException ex) {
180                // ignored
181            }      
182        }   
183        
184        //Additional Test for Array2DRowFieldMatrix<Fraction>Test.testMultiply
185    
186        private Fraction[][] d3 = new Fraction[][] {{new Fraction(1),new Fraction(2),new Fraction(3),new Fraction(4)},{new Fraction(5),new Fraction(6),new Fraction(7),new Fraction(8)}};
187        private Fraction[][] d4 = new Fraction[][] {{new Fraction(1)},{new Fraction(2)},{new Fraction(3)},{new Fraction(4)}};
188        private Fraction[][] d5 = new Fraction[][] {{new Fraction(30)},{new Fraction(70)}};
189         
190        public void testMultiply2() { 
191           FieldMatrix<Fraction> m3 = new Array2DRowFieldMatrix<Fraction>(d3);   
192           FieldMatrix<Fraction> m4 = new Array2DRowFieldMatrix<Fraction>(d4);
193           FieldMatrix<Fraction> m5 = new Array2DRowFieldMatrix<Fraction>(d5);
194           TestUtils.assertEquals(m3.multiply(m4), m5);
195       }  
196            
197        /** test trace */
198        public void testTrace() {
199            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(id);
200            assertEquals("identity trace",new Fraction(3),m.getTrace());
201            m = new Array2DRowFieldMatrix<Fraction>(testData2);
202            try {
203                m.getTrace();
204                fail("Expecting NonSquareMatrixException");
205            } catch (NonSquareMatrixException ex) {
206                // ignored
207            }      
208        }
209        
210        /** test sclarAdd */
211        public void testScalarAdd() {
212            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(testData);
213            TestUtils.assertEquals(new Array2DRowFieldMatrix<Fraction>(testDataPlus2), m.scalarAdd(new Fraction(2)));
214        }
215                        
216        /** test operate */
217        public void testOperate() {
218            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(id);
219            TestUtils.assertEquals(testVector, m.operate(testVector));
220            TestUtils.assertEquals(testVector, m.operate(new ArrayFieldVector<Fraction>(testVector)).getData());
221            m = new Array2DRowFieldMatrix<Fraction>(bigSingular);
222            try {
223                m.operate(testVector);
224                fail("Expecting illegalArgumentException");
225            } catch (IllegalArgumentException ex) {
226                // ignored
227            }      
228        }
229    
230        /** test issue MATH-209 */
231        public void testMath209() {
232            FieldMatrix<Fraction> a = new Array2DRowFieldMatrix<Fraction>(new Fraction[][] {
233                    { new Fraction(1), new Fraction(2) }, { new Fraction(3), new Fraction(4) }, { new Fraction(5), new Fraction(6) }
234            }, false);
235            Fraction[] b = a.operate(new Fraction[] { new Fraction(1), new Fraction(1) });
236            assertEquals(a.getRowDimension(), b.length);
237            assertEquals( new Fraction(3), b[0]);
238            assertEquals( new Fraction(7), b[1]);
239            assertEquals(new Fraction(11), b[2]);
240        }
241        
242        /** test transpose */
243        public void testTranspose() {
244            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(testData); 
245            FieldMatrix<Fraction> mIT = new FieldLUDecompositionImpl<Fraction>(m).getSolver().getInverse().transpose();
246            FieldMatrix<Fraction> mTI = new FieldLUDecompositionImpl<Fraction>(m.transpose()).getSolver().getInverse();
247            TestUtils.assertEquals(mIT, mTI);
248            m = new Array2DRowFieldMatrix<Fraction>(testData2);
249            FieldMatrix<Fraction> mt = new Array2DRowFieldMatrix<Fraction>(testData2T);
250            TestUtils.assertEquals(mt, m.transpose());
251        }
252        
253        /** test preMultiply by vector */
254        public void testPremultiplyVector() {
255            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(testData);
256            TestUtils.assertEquals(m.preMultiply(testVector), preMultTest);
257            TestUtils.assertEquals(m.preMultiply(new ArrayFieldVector<Fraction>(testVector).getData()),
258                                   preMultTest);
259            m = new Array2DRowFieldMatrix<Fraction>(bigSingular);
260            try {
261                m.preMultiply(testVector);
262                fail("expecting IllegalArgumentException");
263            } catch (IllegalArgumentException ex) {
264                // ignored
265            }
266        }
267        
268        public void testPremultiply() {
269            FieldMatrix<Fraction> m3 = new Array2DRowFieldMatrix<Fraction>(d3);   
270            FieldMatrix<Fraction> m4 = new Array2DRowFieldMatrix<Fraction>(d4);
271            FieldMatrix<Fraction> m5 = new Array2DRowFieldMatrix<Fraction>(d5);
272            TestUtils.assertEquals(m4.preMultiply(m3), m5);
273            
274            Array2DRowFieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(testData);
275            Array2DRowFieldMatrix<Fraction> mInv = new Array2DRowFieldMatrix<Fraction>(testDataInv);
276            Array2DRowFieldMatrix<Fraction> identity = new Array2DRowFieldMatrix<Fraction>(id);
277            TestUtils.assertEquals(m.preMultiply(mInv), identity);
278            TestUtils.assertEquals(mInv.preMultiply(m), identity);
279            TestUtils.assertEquals(m.preMultiply(identity), m);
280            TestUtils.assertEquals(identity.preMultiply(mInv), mInv);
281            try {
282                m.preMultiply(new Array2DRowFieldMatrix<Fraction>(bigSingular));
283                fail("Expecting illegalArgumentException");
284            } catch (IllegalArgumentException ex) {
285                // ignored
286            }      
287        }
288        
289        public void testGetVectors() {
290            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(testData);
291            TestUtils.assertEquals(m.getRow(0), testDataRow1);
292            TestUtils.assertEquals(m.getColumn(2), testDataCol3);
293            try {
294                m.getRow(10);
295                fail("expecting MatrixIndexException");
296            } catch (MatrixIndexException ex) {
297                // ignored
298            }
299            try {
300                m.getColumn(-1);
301                fail("expecting MatrixIndexException");
302            } catch (MatrixIndexException ex) {
303                // ignored
304            }
305        }
306        
307        public void testGetEntry() {
308            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(testData);
309            assertEquals("get entry",m.getEntry(0,1),new Fraction(2));
310            try {
311                m.getEntry(10, 4);
312                fail ("Expecting MatrixIndexException");
313            } catch (MatrixIndexException ex) {
314                // expected
315            }
316        }
317            
318        /** test examples in user guide */
319        public void testExamples() {
320            // Create a real matrix with two rows and three columns
321            Fraction[][] matrixData = {
322                    {new Fraction(1),new Fraction(2),new Fraction(3)},
323                    {new Fraction(2),new Fraction(5),new Fraction(3)}
324            };
325            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(matrixData);
326            // One more with three rows, two columns
327            Fraction[][] matrixData2 = {
328                    {new Fraction(1),new Fraction(2)},
329                    {new Fraction(2),new Fraction(5)},
330                    {new Fraction(1), new Fraction(7)}
331            };
332            FieldMatrix<Fraction> n = new Array2DRowFieldMatrix<Fraction>(matrixData2);
333            // Now multiply m by n
334            FieldMatrix<Fraction> p = m.multiply(n);
335            assertEquals(2, p.getRowDimension());
336            assertEquals(2, p.getColumnDimension());
337            // Invert p
338            FieldMatrix<Fraction> pInverse = new FieldLUDecompositionImpl<Fraction>(p).getSolver().getInverse(); 
339            assertEquals(2, pInverse.getRowDimension());
340            assertEquals(2, pInverse.getColumnDimension());
341            
342            // Solve example
343            Fraction[][] coefficientsData = {
344                    {new Fraction(2), new Fraction(3), new Fraction(-2)},
345                    {new Fraction(-1), new Fraction(7), new Fraction(6)},
346                    {new Fraction(4), new Fraction(-3), new Fraction(-5)}
347            };
348            FieldMatrix<Fraction> coefficients = new Array2DRowFieldMatrix<Fraction>(coefficientsData);
349            Fraction[] constants = {new Fraction(1), new Fraction(-2), new Fraction(1)};
350            Fraction[] solution = new FieldLUDecompositionImpl<Fraction>(coefficients).getSolver().solve(constants);
351            assertEquals(new Fraction(2).multiply(solution[0]).
352                         add(new Fraction(3).multiply(solution[1])).
353                         subtract(new Fraction(2).multiply(solution[2])), constants[0]);
354            assertEquals(new Fraction(-1).multiply(solution[0]).
355                         add(new Fraction(7).multiply(solution[1])).
356                         add(new Fraction(6).multiply(solution[2])), constants[1]);
357            assertEquals(new Fraction(4).multiply(solution[0]).
358                         subtract(new Fraction(3).multiply(solution[1])).
359                         subtract(new Fraction(5).multiply(solution[2])), constants[2]);   
360            
361        }
362        
363        // test submatrix accessors
364        public void testGetSubMatrix() {
365            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(subTestData);
366            checkGetSubMatrix(m, subRows23Cols00,  2 , 3 , 0, 0);
367            checkGetSubMatrix(m, subRows00Cols33,  0 , 0 , 3, 3);
368            checkGetSubMatrix(m, subRows01Cols23,  0 , 1 , 2, 3);   
369            checkGetSubMatrix(m, subRows02Cols13,  new int[] { 0, 2 }, new int[] { 1, 3 });  
370            checkGetSubMatrix(m, subRows03Cols12,  new int[] { 0, 3 }, new int[] { 1, 2 });  
371            checkGetSubMatrix(m, subRows03Cols123, new int[] { 0, 3 }, new int[] { 1, 2, 3 }); 
372            checkGetSubMatrix(m, subRows20Cols123, new int[] { 2, 0 }, new int[] { 1, 2, 3 }); 
373            checkGetSubMatrix(m, subRows31Cols31,  new int[] { 3, 1 }, new int[] { 3, 1 }); 
374            checkGetSubMatrix(m, subRows31Cols31,  new int[] { 3, 1 }, new int[] { 3, 1 }); 
375            checkGetSubMatrix(m, null,  1, 0, 2, 4);
376            checkGetSubMatrix(m, null, -1, 1, 2, 2);
377            checkGetSubMatrix(m, null,  1, 0, 2, 2);
378            checkGetSubMatrix(m, null,  1, 0, 2, 4);
379            checkGetSubMatrix(m, null, new int[] {},    new int[] { 0 });
380            checkGetSubMatrix(m, null, new int[] { 0 }, new int[] { 4 });
381        }
382    
383        private void checkGetSubMatrix(FieldMatrix<Fraction> m, Fraction[][] reference,
384                                       int startRow, int endRow, int startColumn, int endColumn) {
385            try {
386                FieldMatrix<Fraction> sub = m.getSubMatrix(startRow, endRow, startColumn, endColumn);
387                if (reference != null) {
388                    assertEquals(new Array2DRowFieldMatrix<Fraction>(reference), sub);
389                } else {
390                    fail("Expecting MatrixIndexException");
391                }
392            } catch (MatrixIndexException e) {
393                if (reference != null) {
394                    throw e;
395                }
396            }
397        }
398        
399        private void checkGetSubMatrix(FieldMatrix<Fraction> m, Fraction[][] reference,
400                                       int[] selectedRows, int[] selectedColumns) {
401            try {
402                FieldMatrix<Fraction> sub = m.getSubMatrix(selectedRows, selectedColumns);
403                if (reference != null) {
404                    assertEquals(new Array2DRowFieldMatrix<Fraction>(reference), sub);
405                } else {
406                    fail("Expecting MatrixIndexException");
407                }
408            } catch (MatrixIndexException e) {
409                if (reference != null) {
410                    throw e;
411                }
412            }
413        }
414    
415        public void testCopySubMatrix() {
416            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(subTestData);
417            checkCopy(m, subRows23Cols00,  2 , 3 , 0, 0);
418            checkCopy(m, subRows00Cols33,  0 , 0 , 3, 3);
419            checkCopy(m, subRows01Cols23,  0 , 1 , 2, 3);   
420            checkCopy(m, subRows02Cols13,  new int[] { 0, 2 }, new int[] { 1, 3 });  
421            checkCopy(m, subRows03Cols12,  new int[] { 0, 3 }, new int[] { 1, 2 });  
422            checkCopy(m, subRows03Cols123, new int[] { 0, 3 }, new int[] { 1, 2, 3 }); 
423            checkCopy(m, subRows20Cols123, new int[] { 2, 0 }, new int[] { 1, 2, 3 }); 
424            checkCopy(m, subRows31Cols31,  new int[] { 3, 1 }, new int[] { 3, 1 }); 
425            checkCopy(m, subRows31Cols31,  new int[] { 3, 1 }, new int[] { 3, 1 }); 
426            
427            checkCopy(m, null,  1, 0, 2, 4);
428            checkCopy(m, null, -1, 1, 2, 2);
429            checkCopy(m, null,  1, 0, 2, 2);
430            checkCopy(m, null,  1, 0, 2, 4);
431            checkCopy(m, null, new int[] {},    new int[] { 0 });
432            checkCopy(m, null, new int[] { 0 }, new int[] { 4 });
433        }
434    
435        private void checkCopy(FieldMatrix<Fraction> m, Fraction[][] reference,
436                               int startRow, int endRow, int startColumn, int endColumn) {
437            try {
438                Fraction[][] sub = (reference == null) ?
439                                 new Fraction[1][1] :
440                                 new Fraction[reference.length][reference[0].length];
441                m.copySubMatrix(startRow, endRow, startColumn, endColumn, sub);
442                if (reference != null) {
443                    assertEquals(new Array2DRowFieldMatrix<Fraction>(reference), new Array2DRowFieldMatrix<Fraction>(sub));
444                } else {
445                    fail("Expecting MatrixIndexException");
446                }
447            } catch (MatrixIndexException e) {
448                if (reference != null) {
449                    throw e;
450                }
451            }
452        }
453        
454        private void checkCopy(FieldMatrix<Fraction> m, Fraction[][] reference,
455                               int[] selectedRows, int[] selectedColumns) {
456            try {
457                Fraction[][] sub = (reference == null) ?
458                        new Fraction[1][1] :
459                        new Fraction[reference.length][reference[0].length];
460                m.copySubMatrix(selectedRows, selectedColumns, sub);
461                if (reference != null) {
462                    assertEquals(new Array2DRowFieldMatrix<Fraction>(reference), new Array2DRowFieldMatrix<Fraction>(sub));
463                } else {
464                    fail("Expecting MatrixIndexException");
465                }
466            } catch (MatrixIndexException e) {
467                if (reference != null) {
468                    throw e;
469                }
470            }
471        }
472    
473        public void testGetRowMatrix() {
474            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(subTestData);
475            FieldMatrix<Fraction> mRow0 = new Array2DRowFieldMatrix<Fraction>(subRow0);
476            FieldMatrix<Fraction> mRow3 = new Array2DRowFieldMatrix<Fraction>(subRow3);
477            assertEquals("Row0", mRow0, 
478                    m.getRowMatrix(0));
479            assertEquals("Row3", mRow3, 
480                    m.getRowMatrix(3));
481            try {
482                m.getRowMatrix(-1);
483                fail("Expecting MatrixIndexException");
484            } catch (MatrixIndexException ex) {
485                // expected
486            }
487            try {
488                m.getRowMatrix(4);
489                fail("Expecting MatrixIndexException");
490            } catch (MatrixIndexException ex) {
491                // expected
492            }
493        }
494        
495        public void testSetRowMatrix() {
496            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(subTestData);
497            FieldMatrix<Fraction> mRow3 = new Array2DRowFieldMatrix<Fraction>(subRow3);
498            assertNotSame(mRow3, m.getRowMatrix(0));
499            m.setRowMatrix(0, mRow3);
500            assertEquals(mRow3, m.getRowMatrix(0));
501            try {
502                m.setRowMatrix(-1, mRow3);
503                fail("Expecting MatrixIndexException");
504            } catch (MatrixIndexException ex) {
505                // expected
506            }
507            try {
508                m.setRowMatrix(0, m);
509                fail("Expecting InvalidMatrixException");
510            } catch (InvalidMatrixException ex) {
511                // expected
512            }
513        }
514        
515        public void testGetColumnMatrix() {
516            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(subTestData);
517            FieldMatrix<Fraction> mColumn1 = new Array2DRowFieldMatrix<Fraction>(subColumn1);
518            FieldMatrix<Fraction> mColumn3 = new Array2DRowFieldMatrix<Fraction>(subColumn3);
519            assertEquals("Column1", mColumn1, 
520                    m.getColumnMatrix(1));
521            assertEquals("Column3", mColumn3, 
522                    m.getColumnMatrix(3));
523            try {
524                m.getColumnMatrix(-1);
525                fail("Expecting MatrixIndexException");
526            } catch (MatrixIndexException ex) {
527                // expected
528            }
529            try {
530                m.getColumnMatrix(4);
531                fail("Expecting MatrixIndexException");
532            } catch (MatrixIndexException ex) {
533                // expected
534            }
535        }
536    
537        public void testSetColumnMatrix() {
538            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(subTestData);
539            FieldMatrix<Fraction> mColumn3 = new Array2DRowFieldMatrix<Fraction>(subColumn3);
540            assertNotSame(mColumn3, m.getColumnMatrix(1));
541            m.setColumnMatrix(1, mColumn3);
542            assertEquals(mColumn3, m.getColumnMatrix(1));
543            try {
544                m.setColumnMatrix(-1, mColumn3);
545                fail("Expecting MatrixIndexException");
546            } catch (MatrixIndexException ex) {
547                // expected
548            }
549            try {
550                m.setColumnMatrix(0, m);
551                fail("Expecting InvalidMatrixException");
552            } catch (InvalidMatrixException ex) {
553                // expected
554            }
555        }
556    
557        public void testGetRowVector() {
558            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(subTestData);
559            FieldVector<Fraction> mRow0 = new ArrayFieldVector<Fraction>(subRow0[0]);
560            FieldVector<Fraction> mRow3 = new ArrayFieldVector<Fraction>(subRow3[0]);
561            assertEquals("Row0", mRow0, m.getRowVector(0));
562            assertEquals("Row3", mRow3, m.getRowVector(3));
563            try {
564                m.getRowVector(-1);
565                fail("Expecting MatrixIndexException");
566            } catch (MatrixIndexException ex) {
567                // expected
568            }
569            try {
570                m.getRowVector(4);
571                fail("Expecting MatrixIndexException");
572            } catch (MatrixIndexException ex) {
573                // expected
574            }
575        }
576    
577        public void testSetRowVector() {
578            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(subTestData);
579            FieldVector<Fraction> mRow3 = new ArrayFieldVector<Fraction>(subRow3[0]);
580            assertNotSame(mRow3, m.getRowMatrix(0));
581            m.setRowVector(0, mRow3);
582            assertEquals(mRow3, m.getRowVector(0));
583            try {
584                m.setRowVector(-1, mRow3);
585                fail("Expecting MatrixIndexException");
586            } catch (MatrixIndexException ex) {
587                // expected
588            }
589            try {
590                m.setRowVector(0, new ArrayFieldVector<Fraction>(FractionField.getInstance(), 5));
591                fail("Expecting InvalidMatrixException");
592            } catch (InvalidMatrixException ex) {
593                // expected
594            }
595        }
596        
597        public void testGetColumnVector() {
598            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(subTestData);
599            FieldVector<Fraction> mColumn1 = columnToVector(subColumn1);
600            FieldVector<Fraction> mColumn3 = columnToVector(subColumn3);
601            assertEquals("Column1", mColumn1, m.getColumnVector(1));
602            assertEquals("Column3", mColumn3, m.getColumnVector(3));
603            try {
604                m.getColumnVector(-1);
605                fail("Expecting MatrixIndexException");
606            } catch (MatrixIndexException ex) {
607                // expected
608            }
609            try {
610                m.getColumnVector(4);
611                fail("Expecting MatrixIndexException");
612            } catch (MatrixIndexException ex) {
613                // expected
614            }
615        }
616    
617        public void testSetColumnVector() {
618            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(subTestData);
619            FieldVector<Fraction> mColumn3 = columnToVector(subColumn3);
620            assertNotSame(mColumn3, m.getColumnVector(1));
621            m.setColumnVector(1, mColumn3);
622            assertEquals(mColumn3, m.getColumnVector(1));
623            try {
624                m.setColumnVector(-1, mColumn3);
625                fail("Expecting MatrixIndexException");
626            } catch (MatrixIndexException ex) {
627                // expected
628            }
629            try {
630                m.setColumnVector(0, new ArrayFieldVector<Fraction>(FractionField.getInstance(), 5));
631                fail("Expecting InvalidMatrixException");
632            } catch (InvalidMatrixException ex) {
633                // expected
634            }
635        }
636    
637        private FieldVector<Fraction> columnToVector(Fraction[][] column) {
638            Fraction[] data = new Fraction[column.length];
639            for (int i = 0; i < data.length; ++i) {
640                data[i] = column[i][0];
641            }
642            return new ArrayFieldVector<Fraction>(data, false);
643        }
644    
645        public void testGetRow() {
646            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(subTestData);
647            checkArrays(subRow0[0], m.getRow(0));
648            checkArrays(subRow3[0], m.getRow(3));
649            try {
650                m.getRow(-1);
651                fail("Expecting MatrixIndexException");
652            } catch (MatrixIndexException ex) {
653                // expected
654            }
655            try {
656                m.getRow(4);
657                fail("Expecting MatrixIndexException");
658            } catch (MatrixIndexException ex) {
659                // expected
660            }
661        }
662    
663        public void testSetRow() {
664            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(subTestData);
665            assertTrue(subRow3[0][0] != m.getRow(0)[0]);
666            m.setRow(0, subRow3[0]);
667            checkArrays(subRow3[0], m.getRow(0));
668            try {
669                m.setRow(-1, subRow3[0]);
670                fail("Expecting MatrixIndexException");
671            } catch (MatrixIndexException ex) {
672                // expected
673            }
674            try {
675                m.setRow(0, new Fraction[5]);
676                fail("Expecting InvalidMatrixException");
677            } catch (InvalidMatrixException ex) {
678                // expected
679            }
680        }
681        
682        public void testGetColumn() {
683            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(subTestData);
684            Fraction[] mColumn1 = columnToArray(subColumn1);
685            Fraction[] mColumn3 = columnToArray(subColumn3);
686            checkArrays(mColumn1, m.getColumn(1));
687            checkArrays(mColumn3, m.getColumn(3));
688            try {
689                m.getColumn(-1);
690                fail("Expecting MatrixIndexException");
691            } catch (MatrixIndexException ex) {
692                // expected
693            }
694            try {
695                m.getColumn(4);
696                fail("Expecting MatrixIndexException");
697            } catch (MatrixIndexException ex) {
698                // expected
699            }
700        }
701    
702        public void testSetColumn() {
703            FieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(subTestData);
704            Fraction[] mColumn3 = columnToArray(subColumn3);
705            assertTrue(mColumn3[0] != m.getColumn(1)[0]);
706            m.setColumn(1, mColumn3);
707            checkArrays(mColumn3, m.getColumn(1));
708            try {
709                m.setColumn(-1, mColumn3);
710                fail("Expecting MatrixIndexException");
711            } catch (MatrixIndexException ex) {
712                // expected
713            }
714            try {
715                m.setColumn(0, new Fraction[5]);
716                fail("Expecting InvalidMatrixException");
717            } catch (InvalidMatrixException ex) {
718                // expected
719            }
720        }
721    
722        private Fraction[] columnToArray(Fraction[][] column) {
723            Fraction[] data = new Fraction[column.length];
724            for (int i = 0; i < data.length; ++i) {
725                data[i] = column[i][0];
726            }
727            return data;
728        }
729    
730        private void checkArrays(Fraction[] expected, Fraction[] actual) {
731            assertEquals(expected.length, actual.length);
732            for (int i = 0; i < expected.length; ++i) {
733                assertEquals(expected[i], actual[i]);            
734            }
735        }
736        
737        public void testEqualsAndHashCode() {
738            Array2DRowFieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(testData);
739            Array2DRowFieldMatrix<Fraction> m1 = (Array2DRowFieldMatrix<Fraction>) m.copy();
740            Array2DRowFieldMatrix<Fraction> mt = (Array2DRowFieldMatrix<Fraction>) m.transpose();
741            assertTrue(m.hashCode() != mt.hashCode());
742            assertEquals(m.hashCode(), m1.hashCode());
743            assertEquals(m, m);
744            assertEquals(m, m1);
745            assertFalse(m.equals(null));
746            assertFalse(m.equals(mt));
747            assertFalse(m.equals(new Array2DRowFieldMatrix<Fraction>(bigSingular))); 
748        }
749        
750        public void testToString() {
751            Array2DRowFieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(testData);
752            assertEquals("Array2DRowFieldMatrix{{1,2,3},{2,5,3},{1,0,8}}", m.toString());
753            m = new Array2DRowFieldMatrix<Fraction>(FractionField.getInstance());
754            assertEquals("Array2DRowFieldMatrix{}", m.toString());
755        }
756        
757        public void testSetSubMatrix() throws Exception {
758            Array2DRowFieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(testData);
759            m.setSubMatrix(detData2,1,1);
760            FieldMatrix<Fraction> expected = new Array2DRowFieldMatrix<Fraction>
761                (new Fraction[][] {
762                        {new Fraction(1),new Fraction(2),new Fraction(3)},
763                        {new Fraction(2),new Fraction(1),new Fraction(3)},
764                        {new Fraction(1),new Fraction(2),new Fraction(4)}
765                 });
766            assertEquals(expected, m);  
767            
768            m.setSubMatrix(detData2,0,0);
769            expected = new Array2DRowFieldMatrix<Fraction>
770                (new Fraction[][] {
771                        {new Fraction(1),new Fraction(3),new Fraction(3)},
772                        {new Fraction(2),new Fraction(4),new Fraction(3)},
773                        {new Fraction(1),new Fraction(2),new Fraction(4)}
774                 });
775            assertEquals(expected, m);  
776            
777            m.setSubMatrix(testDataPlus2,0,0);      
778            expected = new Array2DRowFieldMatrix<Fraction>
779                (new Fraction[][] {
780                        {new Fraction(3),new Fraction(4),new Fraction(5)},
781                        {new Fraction(4),new Fraction(7),new Fraction(5)},
782                        {new Fraction(3),new Fraction(2),new Fraction(10)}
783                 });
784            assertEquals(expected, m);   
785            
786            // dimension overflow
787            try {  
788                m.setSubMatrix(testData,1,1);
789                fail("expecting MatrixIndexException");
790            } catch (MatrixIndexException e) {
791                // expected
792            }
793            // dimension underflow
794            try {  
795                m.setSubMatrix(testData,-1,1);
796                fail("expecting MatrixIndexException");
797            } catch (MatrixIndexException e) {
798                // expected
799            }
800            try {  
801                m.setSubMatrix(testData,1,-1);
802                fail("expecting MatrixIndexException");
803            } catch (MatrixIndexException e) {
804                // expected
805            }
806            
807            // null
808            try {
809                m.setSubMatrix(null,1,1);
810                fail("expecting NullPointerException");
811            } catch (NullPointerException e) {
812                // expected
813            }
814            Array2DRowFieldMatrix<Fraction> m2 = new Array2DRowFieldMatrix<Fraction>(FractionField.getInstance());
815            try {
816                m2.setSubMatrix(testData,0,1);
817                fail("expecting IllegalStateException");
818            } catch (IllegalStateException e) {
819                // expected
820            }
821            try {
822                m2.setSubMatrix(testData,1,0);
823                fail("expecting IllegalStateException");
824            } catch (IllegalStateException e) {
825                // expected
826            }
827            
828            // ragged
829            try {
830                m.setSubMatrix(new Fraction[][] {{new Fraction(1)}, {new Fraction(2), new Fraction(3)}}, 0, 0);
831                fail("expecting IllegalArgumentException");
832            } catch (IllegalArgumentException e) {
833                // expected
834            }
835           
836            // empty
837            try {
838                m.setSubMatrix(new Fraction[][] {{}}, 0, 0);
839                fail("expecting IllegalArgumentException");
840            } catch (IllegalArgumentException e) {
841                // expected
842            }
843            
844        }
845    
846        public void testWalk() {
847            int rows    = 150;
848            int columns = 75;
849    
850            FieldMatrix<Fraction> m =
851                new Array2DRowFieldMatrix<Fraction>(FractionField.getInstance(), rows, columns);
852            m.walkInRowOrder(new SetVisitor());
853            GetVisitor getVisitor = new GetVisitor();
854            m.walkInOptimizedOrder(getVisitor);
855            assertEquals(rows * columns, getVisitor.getCount());
856    
857            m = new Array2DRowFieldMatrix<Fraction>(FractionField.getInstance(), rows, columns);
858            m.walkInRowOrder(new SetVisitor(), 1, rows - 2, 1, columns - 2);
859            getVisitor = new GetVisitor();
860            m.walkInOptimizedOrder(getVisitor, 1, rows - 2, 1, columns - 2);
861            assertEquals((rows - 2) * (columns - 2), getVisitor.getCount());
862            for (int i = 0; i < rows; ++i) {
863                assertEquals(new Fraction(0), m.getEntry(i, 0));                    
864                assertEquals(new Fraction(0), m.getEntry(i, columns - 1));
865            }
866            for (int j = 0; j < columns; ++j) {
867                assertEquals(new Fraction(0), m.getEntry(0, j));                    
868                assertEquals(new Fraction(0), m.getEntry(rows - 1, j));
869            }
870    
871            m = new Array2DRowFieldMatrix<Fraction>(FractionField.getInstance(), rows, columns);
872            m.walkInColumnOrder(new SetVisitor());
873            getVisitor = new GetVisitor();
874            m.walkInOptimizedOrder(getVisitor);
875            assertEquals(rows * columns, getVisitor.getCount());
876    
877            m = new Array2DRowFieldMatrix<Fraction>(FractionField.getInstance(), rows, columns);
878            m.walkInColumnOrder(new SetVisitor(), 1, rows - 2, 1, columns - 2);
879            getVisitor = new GetVisitor();
880            m.walkInOptimizedOrder(getVisitor, 1, rows - 2, 1, columns - 2);
881            assertEquals((rows - 2) * (columns - 2), getVisitor.getCount());
882            for (int i = 0; i < rows; ++i) {
883                assertEquals(new Fraction(0), m.getEntry(i, 0));                    
884                assertEquals(new Fraction(0), m.getEntry(i, columns - 1));
885            }
886            for (int j = 0; j < columns; ++j) {
887                assertEquals(new Fraction(0), m.getEntry(0, j));                    
888                assertEquals(new Fraction(0), m.getEntry(rows - 1, j));
889            }
890    
891            m = new Array2DRowFieldMatrix<Fraction>(FractionField.getInstance(), rows, columns);
892            m.walkInOptimizedOrder(new SetVisitor());
893            getVisitor = new GetVisitor();
894            m.walkInRowOrder(getVisitor);
895            assertEquals(rows * columns, getVisitor.getCount());
896    
897            m = new Array2DRowFieldMatrix<Fraction>(FractionField.getInstance(), rows, columns);
898            m.walkInOptimizedOrder(new SetVisitor(), 1, rows - 2, 1, columns - 2);
899            getVisitor = new GetVisitor();
900            m.walkInRowOrder(getVisitor, 1, rows - 2, 1, columns - 2);
901            assertEquals((rows - 2) * (columns - 2), getVisitor.getCount());
902            for (int i = 0; i < rows; ++i) {
903                assertEquals(new Fraction(0), m.getEntry(i, 0));                    
904                assertEquals(new Fraction(0), m.getEntry(i, columns - 1));
905            }
906            for (int j = 0; j < columns; ++j) {
907                assertEquals(new Fraction(0), m.getEntry(0, j));                    
908                assertEquals(new Fraction(0), m.getEntry(rows - 1, j));
909            }
910    
911            m = new Array2DRowFieldMatrix<Fraction>(FractionField.getInstance(), rows, columns);
912            m.walkInOptimizedOrder(new SetVisitor());
913            getVisitor = new GetVisitor();
914            m.walkInColumnOrder(getVisitor);
915            assertEquals(rows * columns, getVisitor.getCount());
916    
917            m = new Array2DRowFieldMatrix<Fraction>(FractionField.getInstance(), rows, columns);
918            m.walkInOptimizedOrder(new SetVisitor(), 1, rows - 2, 1, columns - 2);
919            getVisitor = new GetVisitor();
920            m.walkInColumnOrder(getVisitor, 1, rows - 2, 1, columns - 2);
921            assertEquals((rows - 2) * (columns - 2), getVisitor.getCount());
922            for (int i = 0; i < rows; ++i) {
923                assertEquals(new Fraction(0), m.getEntry(i, 0));                    
924                assertEquals(new Fraction(0), m.getEntry(i, columns - 1));
925            }
926            for (int j = 0; j < columns; ++j) {
927                assertEquals(new Fraction(0), m.getEntry(0, j));                    
928                assertEquals(new Fraction(0), m.getEntry(rows - 1, j));
929            }
930    
931        }
932    
933        public void testSerial()  {
934            Array2DRowFieldMatrix<Fraction> m = new Array2DRowFieldMatrix<Fraction>(testData);
935            assertEquals(m,TestUtils.serializeAndRecover(m));
936        }
937      
938        private static class SetVisitor extends DefaultFieldMatrixChangingVisitor<Fraction> {
939            public SetVisitor() {
940                super(Fraction.ZERO);
941            }
942            @Override
943            public Fraction visit(int i, int j, Fraction value) {
944                return new Fraction(i * 1024 + j, 1024);
945            }
946        }
947    
948        private static class GetVisitor extends DefaultFieldMatrixPreservingVisitor<Fraction> {
949            private int count;
950            public GetVisitor() {
951                super(Fraction.ZERO);
952                count = 0;
953            }
954            @Override
955            public void visit(int i, int j, Fraction value) {
956                ++count;
957                assertEquals(new Fraction(i * 1024 + j, 1024), value);
958            }
959            public int getCount() {
960                return count;
961            }
962        }
963    
964        //--------------- -----------------Protected methods
965        
966        /** extracts the l  and u matrices from compact lu representation */
967        protected void splitLU(FieldMatrix<Fraction> lu,
968                               Fraction[][] lowerData,
969                               Fraction[][] upperData)
970            throws InvalidMatrixException {   
971            if (!lu.isSquare() ||
972                lowerData.length != lowerData[0].length ||
973                upperData.length != upperData[0].length ||
974                lowerData.length != upperData.length ||
975                lowerData.length != lu.getRowDimension()) {
976                throw new InvalidMatrixException("incorrect dimensions");
977            }    
978            int n = lu.getRowDimension();
979            for (int i = 0; i < n; i++) {
980                for (int j = 0; j < n; j++) {
981                    if (j < i) {
982                        lowerData[i][j] = lu.getEntry(i, j);
983                        upperData[i][j] = Fraction.ZERO;
984                    } else if (i == j) {
985                        lowerData[i][j] = Fraction.ONE;
986                        upperData[i][j] = lu.getEntry(i, j);
987                    } else {
988                        lowerData[i][j] = Fraction.ZERO;
989                        upperData[i][j] = lu.getEntry(i, j);
990                    }   
991                }
992            }
993        }
994        
995        /** Returns the result of applying the given row permutation to the matrix */
996        protected FieldMatrix<Fraction> permuteRows(FieldMatrix<Fraction> matrix, int[] permutation) {
997            if (!matrix.isSquare() || matrix.getRowDimension() != permutation.length) {
998                throw new IllegalArgumentException("dimension mismatch");
999            }
1000            int n = matrix.getRowDimension();
1001            int m = matrix.getColumnDimension();
1002            Fraction out[][] = new Fraction[m][n];
1003            for (int i = 0; i < n; i++) {
1004                for (int j = 0; j < m; j++) {
1005                    out[i][j] = matrix.getEntry(permutation[i], j);
1006                }
1007            }
1008            return new Array2DRowFieldMatrix<Fraction>(out);
1009        }
1010        
1011    }
1012