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 org.apache.commons.math.Field;
020    import org.apache.commons.math.fraction.Fraction;
021    import org.apache.commons.math.fraction.FractionConversionException;
022    import org.apache.commons.math.fraction.FractionField;
023    
024    import junit.framework.Test;
025    import junit.framework.TestCase;
026    import junit.framework.TestSuite;
027    
028    /**
029     * Test cases for the {@link SparseFieldMatrix} class.
030     *
031     * @version $Revision: 799857 $ $Date: 2009-08-01 09:07:12 -0400 (Sat, 01 Aug 2009) $
032     */
033    public class SparseFieldMatrixTest extends TestCase {
034        // 3 x 3 identity matrix
035        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) } };
036        // Test data for group operations
037        protected Fraction[][] testData = { { new Fraction(1), new Fraction(2), new Fraction(3) }, { new Fraction(2), new Fraction(5), new Fraction(3) },
038                { new Fraction(1), new Fraction(0), new Fraction(8) } };
039        protected Fraction[][] testDataLU = null;
040        protected Fraction[][] testDataPlus2 = { { new Fraction(3), new Fraction(4), new Fraction(5) }, { new Fraction(4), new Fraction(7), new Fraction(5) },
041                { new Fraction(3), new Fraction(2), new Fraction(10) } };
042        protected Fraction[][] testDataMinus = { { new Fraction(-1), new Fraction(-2), new Fraction(-3) },
043                { new Fraction(-2), new Fraction(-5), new Fraction(-3) }, { 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 = { { new Fraction(-40), new Fraction(16), new Fraction(9) }, { new Fraction(13), new Fraction(-5), new Fraction(-3) },
047                { 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 = { { new Fraction(-39), new Fraction(18), new Fraction(12) },
052                { 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 = null;
057    
058        // singular matrices
059        protected Fraction[][] singular = { { new Fraction(2), new Fraction(3) }, { new Fraction(2), new Fraction(3) } };
060        protected Fraction[][] bigSingular = { { new Fraction(1), new Fraction(2), new Fraction(3), new Fraction(4) },
061                { new Fraction(2), new Fraction(5), new Fraction(3), new Fraction(4) }, { 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
062    
063        // row
064        // =
065        // 1st
066        // +
067        // 2nd
068        protected Fraction[][] detData = { { new Fraction(1), new Fraction(2), new Fraction(3) }, { new Fraction(4), new Fraction(5), new Fraction(6) },
069                { new Fraction(7), new Fraction(8), new Fraction(10) } };
070        protected Fraction[][] detData2 = { { new Fraction(1), new Fraction(3) }, { new Fraction(2), new Fraction(4) } };
071    
072        // vectors
073        protected Fraction[] testVector = { new Fraction(1), new Fraction(2), new Fraction(3) };
074        protected Fraction[] testVector2 = { new Fraction(1), new Fraction(2), new Fraction(3), new Fraction(4) };
075    
076        // submatrix accessor tests
077        protected Fraction[][] subTestData = null;
078    
079        // array selections
080        protected Fraction[][] subRows02Cols13 = { {new Fraction(2), new Fraction(4) }, { new Fraction(4), new Fraction(8) } };
081        protected Fraction[][] subRows03Cols12 = { { new Fraction(2), new Fraction(3) }, { new Fraction(5), new Fraction(6) } };
082        protected Fraction[][] subRows03Cols123 = { { new Fraction(2), new Fraction(3), new Fraction(4) }, { new Fraction(5), new Fraction(6), new Fraction(7) } };
083    
084        // effective permutations
085        protected Fraction[][] subRows20Cols123 = { { new Fraction(4), new Fraction(6), new Fraction(8) }, { new Fraction(2), new Fraction(3), new Fraction(4) } };
086        protected Fraction[][] subRows31Cols31 = null;
087    
088        // contiguous ranges
089        protected Fraction[][] subRows01Cols23 = null;
090        protected Fraction[][] subRows23Cols00 = { { new Fraction(2) }, { new Fraction(4) } };
091        protected Fraction[][] subRows00Cols33 = { { new Fraction(4) } };
092    
093        // row matrices
094        protected Fraction[][] subRow0 = { { new Fraction(1), new Fraction(2), new Fraction(3), new Fraction(4) } };
095        protected Fraction[][] subRow3 = { { new Fraction(4), new Fraction(5), new Fraction(6), new Fraction(7) } };
096    
097        // column matrices
098        protected Fraction[][] subColumn1 = null;
099        protected Fraction[][] subColumn3 = null;
100    
101        // tolerances
102        protected double entryTolerance = 10E-16;
103        protected double normTolerance = 10E-14;
104        protected Field<Fraction> field = FractionField.getInstance();
105    
106        public SparseFieldMatrixTest(String name) {
107            super(name);
108            setupFractionArrays();
109        }
110    
111        private void setupFractionArrays() {
112            try {
113                testDataLU = new Fraction[][]{ { new Fraction(2), new Fraction(5), new Fraction(3) }, { new Fraction(.5d), new Fraction(-2.5d), new Fraction(6.5d) },
114                        { new Fraction(0.5d), new Fraction(0.2d), new Fraction(.2d) } };
115                luDataLUDecomposition = new Fraction[][]{ { new Fraction(6), new Fraction(9), new Fraction(8) },
116                    { new Fraction(0), new Fraction(5), new Fraction(7) }, { new Fraction(0.33333333333333), new Fraction(0), new Fraction(0.33333333333333) } };
117                subTestData = new Fraction [][]{ { new Fraction(1), new Fraction(2), new Fraction(3), new Fraction(4) },
118                        { new Fraction(1.5), new Fraction(2.5), new Fraction(3.5), new Fraction(4.5) }, { new Fraction(2), new Fraction(4), new Fraction(6), new Fraction(8) }, { new Fraction(4), new Fraction(5), new Fraction(6), new Fraction(7) } };
119                subRows31Cols31 = new Fraction[][]{ { new Fraction(7), new Fraction(5) }, { new Fraction(4.5), new Fraction(2.5) } };
120                subRows01Cols23 = new Fraction[][]{ { new Fraction(3), new Fraction(4) }, { new Fraction(3.5), new Fraction(4.5) } };
121                subColumn1 = new Fraction [][]{ { new Fraction(2) }, { new Fraction(2.5) }, { new Fraction(4) }, { new Fraction(5) } };
122                subColumn3 = new Fraction[][]{ { new Fraction(4) }, { new Fraction(4.5) }, { new Fraction(8) }, { new Fraction(7) } };
123            } catch (FractionConversionException e) {
124                // ignore, can't happen
125            }
126            
127                    
128        }
129    
130        public static Test suite() {
131            TestSuite suite = new TestSuite(SparseFieldMatrixTest.class);
132            suite.setName("SparseFieldMatrix<Fraction> Tests");
133            return suite;
134        }
135    
136        /** test dimensions */
137        public void testDimensions() {
138            SparseFieldMatrix<Fraction> m = createSparseMatrix(testData);
139            SparseFieldMatrix<Fraction> m2 = createSparseMatrix(testData2);
140            assertEquals("testData row dimension", 3, m.getRowDimension());
141            assertEquals("testData column dimension", 3, m.getColumnDimension());
142            assertTrue("testData is square", m.isSquare());
143            assertEquals("testData2 row dimension", m2.getRowDimension(), 2);
144            assertEquals("testData2 column dimension", m2.getColumnDimension(), 3);
145            assertTrue("testData2 is not square", !m2.isSquare());
146        }
147    
148        /** test copy functions */
149        public void testCopyFunctions() {
150            SparseFieldMatrix<Fraction> m1 = createSparseMatrix(testData);
151            FieldMatrix<Fraction> m2 = m1.copy();
152            assertEquals(m1.getClass(), m2.getClass());
153            assertEquals((m2), m1);
154            SparseFieldMatrix<Fraction> m3 = createSparseMatrix(testData);
155            FieldMatrix<Fraction> m4 = m3.copy();
156            assertEquals(m3.getClass(), m4.getClass());
157            assertEquals((m4), m3);
158        }
159    
160        /** test add */
161        public void testAdd() {
162            SparseFieldMatrix<Fraction> m = createSparseMatrix(testData);
163            SparseFieldMatrix<Fraction> mInv = createSparseMatrix(testDataInv);
164            SparseFieldMatrix<Fraction> mDataPlusInv = createSparseMatrix(testDataPlusInv);
165            FieldMatrix<Fraction> mPlusMInv = m.add(mInv);
166            for (int row = 0; row < m.getRowDimension(); row++) {
167                for (int col = 0; col < m.getColumnDimension(); col++) {
168                    assertEquals("sum entry entry", 
169                        mDataPlusInv.getEntry(row, col).doubleValue(), mPlusMInv.getEntry(row, col).doubleValue(), 
170                        entryTolerance);
171                }
172            }
173        }
174    
175        /** test add failure */
176        public void testAddFail() {
177            SparseFieldMatrix<Fraction> m = createSparseMatrix(testData);
178            SparseFieldMatrix<Fraction> m2 = createSparseMatrix(testData2);
179            try {
180                m.add(m2);
181                fail("IllegalArgumentException expected");
182            } catch (IllegalArgumentException ex) {
183                // ignored
184            }
185        }
186    
187        
188        /** test m-n = m + -n */
189        public void testPlusMinus() {
190            SparseFieldMatrix<Fraction> m = createSparseMatrix(testData);
191            SparseFieldMatrix<Fraction> n = createSparseMatrix(testDataInv);
192            assertClose("m-n = m + -n", m.subtract(n),
193                n.scalarMultiply(new Fraction(-1)).add(m), entryTolerance);
194            try {
195                m.subtract(createSparseMatrix(testData2));
196                fail("Expecting illegalArgumentException");
197            } catch (IllegalArgumentException ex) {
198                // ignored
199            }
200        }
201    
202        /** test multiply */
203        public void testMultiply() {
204            SparseFieldMatrix<Fraction> m = createSparseMatrix(testData);
205            SparseFieldMatrix<Fraction> mInv = createSparseMatrix(testDataInv);
206            SparseFieldMatrix<Fraction> identity = createSparseMatrix(id);
207            SparseFieldMatrix<Fraction> m2 = createSparseMatrix(testData2);
208            assertClose("inverse multiply", m.multiply(mInv), identity,
209                    entryTolerance);
210            assertClose("inverse multiply", m.multiply(new Array2DRowFieldMatrix<Fraction>(testDataInv)), identity,
211                        entryTolerance);
212            assertClose("inverse multiply", mInv.multiply(m), identity,
213                    entryTolerance);
214            assertClose("identity multiply", m.multiply(identity), m,
215                    entryTolerance);
216            assertClose("identity multiply", identity.multiply(mInv), mInv,
217                    entryTolerance);
218            assertClose("identity multiply", m2.multiply(identity), m2,
219                    entryTolerance);
220            try {
221                m.multiply(createSparseMatrix(bigSingular));
222                fail("Expecting illegalArgumentException");
223            } catch (IllegalArgumentException ex) {
224                // ignored
225            }
226        }
227    
228        // Additional Test for Array2DRowRealMatrixTest.testMultiply
229    
230        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) } };
231        private Fraction[][] d4 = new Fraction[][] { { new Fraction(1) }, { new Fraction(2) }, { new Fraction(3) }, { new Fraction(4) } };
232        private Fraction[][] d5 = new Fraction[][] { { new Fraction(30) }, { new Fraction(70) } };
233    
234        public void testMultiply2() {
235            FieldMatrix<Fraction> m3 = createSparseMatrix(d3);
236            FieldMatrix<Fraction> m4 = createSparseMatrix(d4);
237            FieldMatrix<Fraction> m5 = createSparseMatrix(d5);
238            assertClose("m3*m4=m5", m3.multiply(m4), m5, entryTolerance);
239        }
240    
241        /** test trace */
242        public void testTrace() {
243            FieldMatrix<Fraction> m = createSparseMatrix(id);
244            assertEquals("identity trace", 3d, m.getTrace().doubleValue(), entryTolerance);
245            m = createSparseMatrix(testData2);
246            try {
247                m.getTrace();
248                fail("Expecting NonSquareMatrixException");
249            } catch (NonSquareMatrixException ex) {
250                // ignored
251            }
252        }
253    
254        /** test sclarAdd */
255        public void testScalarAdd() {
256            FieldMatrix<Fraction> m = createSparseMatrix(testData);
257            assertClose("scalar add", createSparseMatrix(testDataPlus2), 
258                m.scalarAdd(new Fraction(2)), entryTolerance);
259        }
260    
261        /** test operate */
262        public void testOperate() {
263            FieldMatrix<Fraction> m = createSparseMatrix(id);
264            assertClose("identity operate", testVector, m.operate(testVector),
265                    entryTolerance);
266            assertClose("identity operate", testVector, m.operate(
267                    new ArrayFieldVector<Fraction>(testVector)).getData(), entryTolerance);
268            m = createSparseMatrix(bigSingular);
269            try {
270                m.operate(testVector);
271                fail("Expecting illegalArgumentException");
272            } catch (IllegalArgumentException ex) {
273                // ignored
274            }
275        }
276    
277        /** test issue MATH-209 */
278        public void testMath209() {
279            FieldMatrix<Fraction> a = createSparseMatrix(new Fraction[][] {
280                    { new Fraction(1), new Fraction(2) }, { new Fraction(3), new Fraction(4) }, { new Fraction(5), new Fraction(6) } });
281            Fraction[] b = a.operate(new Fraction[] { new Fraction(1), new Fraction(1) });
282            assertEquals(a.getRowDimension(), b.length);
283            assertEquals(3.0, b[0].doubleValue(), 1.0e-12);
284            assertEquals(7.0, b[1].doubleValue(), 1.0e-12);
285            assertEquals(11.0, b[2].doubleValue(), 1.0e-12);
286        }
287    
288        /** test transpose */
289        public void testTranspose() {
290            
291            FieldMatrix<Fraction> m = createSparseMatrix(testData); 
292            FieldMatrix<Fraction> mIT = new FieldLUDecompositionImpl<Fraction>(m).getSolver().getInverse().transpose();
293            FieldMatrix<Fraction> mTI = new FieldLUDecompositionImpl<Fraction>(m.transpose()).getSolver().getInverse();
294            assertClose("inverse-transpose", mIT, mTI, normTolerance);
295            m = createSparseMatrix(testData2);
296            FieldMatrix<Fraction> mt = createSparseMatrix(testData2T);
297            assertClose("transpose",mt,m.transpose(),normTolerance);
298        }
299    
300        /** test preMultiply by vector */
301        public void testPremultiplyVector() {
302            FieldMatrix<Fraction> m = createSparseMatrix(testData);
303            assertClose("premultiply", m.preMultiply(testVector), preMultTest,
304                normTolerance);
305            assertClose("premultiply", m.preMultiply(
306                new ArrayFieldVector<Fraction>(testVector).getData()), preMultTest, normTolerance);
307            m = createSparseMatrix(bigSingular);
308            try {
309                m.preMultiply(testVector);
310                fail("expecting IllegalArgumentException");
311            } catch (IllegalArgumentException ex) {
312                // ignored
313            }
314        }
315    
316        public void testPremultiply() {
317            FieldMatrix<Fraction> m3 = createSparseMatrix(d3);
318            FieldMatrix<Fraction> m4 = createSparseMatrix(d4);
319            FieldMatrix<Fraction> m5 = createSparseMatrix(d5);
320            assertClose("m3*m4=m5", m4.preMultiply(m3), m5, entryTolerance);
321    
322            SparseFieldMatrix<Fraction> m = createSparseMatrix(testData);
323            SparseFieldMatrix<Fraction> mInv = createSparseMatrix(testDataInv);
324            SparseFieldMatrix<Fraction> identity = createSparseMatrix(id);
325            assertClose("inverse multiply", m.preMultiply(mInv), identity,
326                    entryTolerance);
327            assertClose("inverse multiply", mInv.preMultiply(m), identity,
328                    entryTolerance);
329            assertClose("identity multiply", m.preMultiply(identity), m,
330                    entryTolerance);
331            assertClose("identity multiply", identity.preMultiply(mInv), mInv,
332                    entryTolerance);
333            try {
334                m.preMultiply(createSparseMatrix(bigSingular));
335                fail("Expecting illegalArgumentException");
336            } catch (IllegalArgumentException ex) {
337                // ignored
338            }
339        }
340    
341        public void testGetVectors() {
342            FieldMatrix<Fraction> m = createSparseMatrix(testData);
343            assertClose("get row", m.getRow(0), testDataRow1, entryTolerance);
344            assertClose("get col", m.getColumn(2), testDataCol3, entryTolerance);
345            try {
346                m.getRow(10);
347                fail("expecting MatrixIndexException");
348            } catch (MatrixIndexException ex) {
349                // ignored
350            }
351            try {
352                m.getColumn(-1);
353                fail("expecting MatrixIndexException");
354            } catch (MatrixIndexException ex) {
355                // ignored
356            }
357        }
358    
359        public void testGetEntry() {
360            FieldMatrix<Fraction> m = createSparseMatrix(testData);
361            assertEquals("get entry", m.getEntry(0, 1).doubleValue(), 2d, entryTolerance);
362            try {
363                m.getEntry(10, 4);
364                fail("Expecting MatrixIndexException");
365            } catch (MatrixIndexException ex) {
366                // expected
367            }
368        }
369    
370        /** test examples in user guide */
371        public void testExamples() {
372            // Create a real matrix with two rows and three columns
373            Fraction[][] matrixData = { { new Fraction(1), new Fraction(2), new Fraction(3) }, { new Fraction(2), new Fraction(5), new Fraction(3) } };
374            FieldMatrix<Fraction> m = createSparseMatrix(matrixData);
375            // One more with three rows, two columns
376            Fraction[][] matrixData2 = { { new Fraction(1), new Fraction(2) }, { new Fraction(2), new Fraction(5) }, { new Fraction(1), new Fraction(7) } };
377            FieldMatrix<Fraction> n = createSparseMatrix(matrixData2);
378            // Now multiply m by n
379            FieldMatrix<Fraction> p = m.multiply(n);
380            assertEquals(2, p.getRowDimension());
381            assertEquals(2, p.getColumnDimension());
382            // Invert p
383            FieldMatrix<Fraction> pInverse = new FieldLUDecompositionImpl<Fraction>(p).getSolver().getInverse(); 
384            assertEquals(2, pInverse.getRowDimension());
385            assertEquals(2, pInverse.getColumnDimension());
386    
387            // Solve example
388            Fraction[][] coefficientsData = { { new Fraction(2), new Fraction(3), new Fraction(-2) }, { new Fraction(-1), new Fraction(7), new Fraction(6) },
389                    { new Fraction(4), new Fraction(-3), new Fraction(-5) } };
390            FieldMatrix<Fraction> coefficients = createSparseMatrix(coefficientsData);
391            Fraction[] constants = { new Fraction(1), new Fraction(-2), new Fraction(1) };
392            Fraction[] solution = new FieldLUDecompositionImpl<Fraction>(coefficients).getSolver().solve(constants);
393            assertEquals((new Fraction(2).multiply((solution[0])).add(new Fraction(3).multiply(solution[1])).subtract(new Fraction(2).multiply(solution[2]))).doubleValue(),
394                    constants[0].doubleValue(), 1E-12);
395            assertEquals(((new Fraction(-1).multiply(solution[0])).add(new Fraction(7).multiply(solution[1])).add(new Fraction(6).multiply(solution[2]))).doubleValue(),
396                    constants[1].doubleValue(), 1E-12);
397            assertEquals(((new Fraction(4).multiply(solution[0])).subtract(new Fraction(3).multiply( solution[1])).subtract(new Fraction(5).multiply(solution[2]))).doubleValue(),
398                    constants[2].doubleValue(), 1E-12);
399    
400        }
401    
402        // test submatrix accessors
403        public void testSubMatrix() {
404            FieldMatrix<Fraction> m = createSparseMatrix(subTestData);
405            FieldMatrix<Fraction> mRows23Cols00 = createSparseMatrix(subRows23Cols00);
406            FieldMatrix<Fraction> mRows00Cols33 = createSparseMatrix(subRows00Cols33);
407            FieldMatrix<Fraction> mRows01Cols23 = createSparseMatrix(subRows01Cols23);
408            FieldMatrix<Fraction> mRows02Cols13 = createSparseMatrix(subRows02Cols13);
409            FieldMatrix<Fraction> mRows03Cols12 = createSparseMatrix(subRows03Cols12);
410            FieldMatrix<Fraction> mRows03Cols123 = createSparseMatrix(subRows03Cols123);
411            FieldMatrix<Fraction> mRows20Cols123 = createSparseMatrix(subRows20Cols123);
412            FieldMatrix<Fraction> mRows31Cols31 = createSparseMatrix(subRows31Cols31);
413            assertEquals("Rows23Cols00", mRows23Cols00, m.getSubMatrix(2, 3, 0, 0));
414            assertEquals("Rows00Cols33", mRows00Cols33, m.getSubMatrix(0, 0, 3, 3));
415            assertEquals("Rows01Cols23", mRows01Cols23, m.getSubMatrix(0, 1, 2, 3));
416            assertEquals("Rows02Cols13", mRows02Cols13, 
417                m.getSubMatrix(new int[] { 0, 2 }, new int[] { 1, 3 }));
418            assertEquals("Rows03Cols12", mRows03Cols12, 
419                m.getSubMatrix(new int[] { 0, 3 }, new int[] { 1, 2 }));
420            assertEquals("Rows03Cols123", mRows03Cols123, 
421                m.getSubMatrix(new int[] { 0, 3 }, new int[] { 1, 2, 3 }));
422            assertEquals("Rows20Cols123", mRows20Cols123, 
423                m.getSubMatrix(new int[] { 2, 0 }, new int[] { 1, 2, 3 }));
424            assertEquals("Rows31Cols31", mRows31Cols31, 
425                m.getSubMatrix(new int[] { 3, 1 }, new int[] { 3, 1 }));
426            assertEquals("Rows31Cols31", mRows31Cols31, 
427                m.getSubMatrix(new int[] { 3, 1 }, new int[] { 3, 1 }));
428    
429            try {
430                m.getSubMatrix(1, 0, 2, 4);
431                fail("Expecting MatrixIndexException");
432            } catch (MatrixIndexException ex) {
433                // expected
434            }
435            try {
436                m.getSubMatrix(-1, 1, 2, 2);
437                fail("Expecting MatrixIndexException");
438            } catch (MatrixIndexException ex) {
439                // expected
440            }
441            try {
442                m.getSubMatrix(1, 0, 2, 2);
443                fail("Expecting MatrixIndexException");
444            } catch (MatrixIndexException ex) {
445                // expected
446            }
447            try {
448                m.getSubMatrix(1, 0, 2, 4);
449                fail("Expecting MatrixIndexException");
450            } catch (MatrixIndexException ex) {
451                // expected
452            }
453            try {
454                m.getSubMatrix(new int[] {}, new int[] { 0 });
455                fail("Expecting MatrixIndexException");
456            } catch (MatrixIndexException ex) {
457                // expected
458            }
459            try {
460                m.getSubMatrix(new int[] { 0 }, new int[] { 4 });
461                fail("Expecting MatrixIndexException");
462            } catch (MatrixIndexException ex) {
463                // expected
464            }
465        }
466    
467        public void testGetRowMatrix() {
468            FieldMatrix<Fraction> m = createSparseMatrix(subTestData);
469            FieldMatrix<Fraction> mRow0 = createSparseMatrix(subRow0);
470            FieldMatrix<Fraction> mRow3 = createSparseMatrix(subRow3);
471            assertEquals("Row0", mRow0, m.getRowMatrix(0));
472            assertEquals("Row3", mRow3, m.getRowMatrix(3));
473            try {
474                m.getRowMatrix(-1);
475                fail("Expecting MatrixIndexException");
476            } catch (MatrixIndexException ex) {
477                // expected
478            }
479            try {
480                m.getRowMatrix(4);
481                fail("Expecting MatrixIndexException");
482            } catch (MatrixIndexException ex) {
483                // expected
484            }
485        }
486    
487        public void testGetColumnMatrix() {
488            FieldMatrix<Fraction> m = createSparseMatrix(subTestData);
489            FieldMatrix<Fraction> mColumn1 = createSparseMatrix(subColumn1);
490            FieldMatrix<Fraction> mColumn3 = createSparseMatrix(subColumn3);
491            assertEquals("Column1", mColumn1, m.getColumnMatrix(1));
492            assertEquals("Column3", mColumn3, m.getColumnMatrix(3));
493            try {
494                m.getColumnMatrix(-1);
495                fail("Expecting MatrixIndexException");
496            } catch (MatrixIndexException ex) {
497                // expected
498            }
499            try {
500                m.getColumnMatrix(4);
501                fail("Expecting MatrixIndexException");
502            } catch (MatrixIndexException ex) {
503                // expected
504            }
505        }
506    
507        public void testGetRowVector() {
508            FieldMatrix<Fraction> m = createSparseMatrix(subTestData);
509            FieldVector<Fraction> mRow0 = new ArrayFieldVector<Fraction>(subRow0[0]);
510            FieldVector<Fraction> mRow3 = new ArrayFieldVector<Fraction>(subRow3[0]);
511            assertEquals("Row0", mRow0, m.getRowVector(0));
512            assertEquals("Row3", mRow3, m.getRowVector(3));
513            try {
514                m.getRowVector(-1);
515                fail("Expecting MatrixIndexException");
516            } catch (MatrixIndexException ex) {
517                // expected
518            }
519            try {
520                m.getRowVector(4);
521                fail("Expecting MatrixIndexException");
522            } catch (MatrixIndexException ex) {
523                // expected
524            }
525        }
526    
527        public void testGetColumnVector() {
528            FieldMatrix<Fraction> m = createSparseMatrix(subTestData);
529            FieldVector<Fraction> mColumn1 = columnToVector(subColumn1);
530            FieldVector<Fraction> mColumn3 = columnToVector(subColumn3);
531            assertEquals("Column1", mColumn1, m.getColumnVector(1));
532            assertEquals("Column3", mColumn3, m.getColumnVector(3));
533            try {
534                m.getColumnVector(-1);
535                fail("Expecting MatrixIndexException");
536            } catch (MatrixIndexException ex) {
537                // expected
538            }
539            try {
540                m.getColumnVector(4);
541                fail("Expecting MatrixIndexException");
542            } catch (MatrixIndexException ex) {
543                // expected
544            }
545        }
546    
547        private FieldVector<Fraction> columnToVector(Fraction[][] column) {
548            Fraction[] data = new Fraction[column.length];
549            for (int i = 0; i < data.length; ++i) {
550                data[i] = column[i][0];
551            }
552            return new ArrayFieldVector<Fraction>(data, false);
553        }
554    
555        public void testEqualsAndHashCode() {
556            SparseFieldMatrix<Fraction> m = createSparseMatrix(testData);
557            SparseFieldMatrix<Fraction> m1 = (SparseFieldMatrix<Fraction>) m.copy();
558            SparseFieldMatrix<Fraction> mt = (SparseFieldMatrix<Fraction>) m.transpose();
559            assertTrue(m.hashCode() != mt.hashCode());
560            assertEquals(m.hashCode(), m1.hashCode());
561            assertEquals(m, m);
562            assertEquals(m, m1);
563            assertFalse(m.equals(null));
564            assertFalse(m.equals(mt));
565            assertFalse(m.equals(createSparseMatrix(bigSingular)));
566        }
567    
568        /* Disable for now
569        public void testToString() {
570            SparseFieldMatrix<Fraction> m = createSparseMatrix(testData);
571            assertEquals("SparseFieldMatrix<Fraction>{{1.0,2.0,3.0},{2.0,5.0,3.0},{1.0,0.0,8.0}}", 
572                m.toString());
573            m = new SparseFieldMatrix<Fraction>(field, 1, 1);
574            assertEquals("SparseFieldMatrix<Fraction>{{0.0}}", m.toString());
575        }
576        */
577    
578        public void testSetSubMatrix() throws Exception {
579            SparseFieldMatrix<Fraction> m = createSparseMatrix(testData);
580            m.setSubMatrix(detData2, 1, 1);
581            FieldMatrix<Fraction> expected = createSparseMatrix(new Fraction[][] {
582                    { 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) } });
583            assertEquals(expected, m);
584    
585            m.setSubMatrix(detData2, 0, 0);
586            expected = createSparseMatrix(new Fraction[][] {
587                    { 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) } });
588            assertEquals(expected, m);
589    
590            m.setSubMatrix(testDataPlus2, 0, 0);
591            expected = createSparseMatrix(new Fraction[][] {
592                    { 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) } });
593            assertEquals(expected, m);
594    
595            // javadoc example
596            SparseFieldMatrix<Fraction> matrix = 
597                createSparseMatrix(new Fraction[][] { 
598            { 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(9), new Fraction(0), new Fraction(1), new Fraction(2) } });
599            matrix.setSubMatrix(new Fraction[][] { { new Fraction(3), new Fraction(4) }, { new Fraction(5), new Fraction(6) } }, 1, 1);
600            expected = createSparseMatrix(new Fraction[][] {
601                    { new Fraction(1), new Fraction(2), new Fraction(3), new Fraction(4) }, { new Fraction(5), new Fraction(3), new Fraction(4), new Fraction(8) }, { new Fraction(9), new Fraction(5), new Fraction(6), new Fraction(2) } });
602            assertEquals(expected, matrix);
603    
604            // dimension overflow
605            try {
606                m.setSubMatrix(testData, 1, 1);
607                fail("expecting MatrixIndexException");
608            } catch (MatrixIndexException e) {
609                // expected
610            }
611            // dimension underflow
612            try {
613                m.setSubMatrix(testData, -1, 1);
614                fail("expecting MatrixIndexException");
615            } catch (MatrixIndexException e) {
616                // expected
617            }
618            try {
619                m.setSubMatrix(testData, 1, -1);
620                fail("expecting MatrixIndexException");
621            } catch (MatrixIndexException e) {
622                // expected
623            }
624    
625            // null
626            try {
627                m.setSubMatrix(null, 1, 1);
628                fail("expecting NullPointerException");
629            } catch (NullPointerException e) {
630                // expected
631            }
632            try {
633                new SparseFieldMatrix<Fraction>(field, 0, 0);
634                fail("expecting IllegalArgumentException");
635            } catch (IllegalArgumentException e) {
636                // expected
637            }
638    
639            // ragged
640            try {
641                m.setSubMatrix(new Fraction[][] { { new Fraction(1) }, { new Fraction(2), new Fraction(3) } }, 0, 0);
642                fail("expecting IllegalArgumentException");
643            } catch (IllegalArgumentException e) {
644                // expected
645            }
646    
647            // empty
648            try {
649                m.setSubMatrix(new Fraction[][] { {} }, 0, 0);
650                fail("expecting IllegalArgumentException");
651            } catch (IllegalArgumentException e) {
652                // expected
653            }
654    
655        }
656    
657        // --------------- -----------------Protected methods
658    
659        /** verifies that two matrices are close (1-norm) */
660        protected void assertClose(String msg, FieldMatrix<Fraction> m, FieldMatrix<Fraction> n,
661                double tolerance) {
662            for(int i=0; i < m.getRowDimension(); i++){
663                for(int j=0; j < m.getColumnDimension(); j++){
664                    assertEquals(msg, m.getEntry(i,j).doubleValue(), n.getEntry(i,j).doubleValue(), tolerance);
665                }
666                
667            }
668        }
669    
670        /** verifies that two vectors are close (sup norm) */
671        protected void assertClose(String msg, Fraction[] m, Fraction[] n,
672                double tolerance) {
673            if (m.length != n.length) {
674                fail("vectors not same length");
675            }
676            for (int i = 0; i < m.length; i++) {
677                assertEquals(msg + " " + i + " elements differ", m[i].doubleValue(), n[i].doubleValue(),
678                        tolerance);
679            }
680        }
681        
682        private SparseFieldMatrix<Fraction> createSparseMatrix(Fraction[][] data) {
683            SparseFieldMatrix<Fraction> matrix = new SparseFieldMatrix<Fraction>(field, data.length, data[0].length);
684            for (int row = 0; row < data.length; row++) {
685                for (int col = 0; col < data[row].length; col++) {
686                    matrix.setEntry(row, col, data[row][col]);
687                }
688            }
689            return matrix;
690        }
691    
692    }