    1   /*
    2    * Copyright 2004 The Apache Software Foundation.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *      http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  package org.apache.commons.math.linear;
    17
    18  import junit.framework.Test;
    19  import junit.framework.TestCase;
    20  import junit.framework.TestSuite;
    21
    22  import java.math.BigDecimal;
    23
    24  /***
    25   * Test cases for the {@link BigMatrixImpl} class.
    26   *
    27   * @version $Revision: 1.5 $ $Date: 2004/10/25 03:13:31 $
    28   */
    29
    30  public final class BigMatrixImplTest extends TestCase {
    31
    32      // Test data for String constructors
    33      protected  String[][] testDataString = { {"1","2","3"}, {"2","5","3"}, {"1","0","8"} };
    34
    35      // 3 x 3 identity matrix
    36      protected double[][] id = { {1d,0d,0d}, {0d,1d,0d}, {0d,0d,1d} };
    37
    38      // Test data for group operations
    39      protected double[][] testData = { {1d,2d,3d}, {2d,5d,3d}, {1d,0d,8d} };
    40      protected double[][] testDataLU = {{2d, 5d, 3d}, {.5d, -2.5d, 6.5d}, {0.5d, 0.2d, .2d}};
    41      protected double[][] testDataPlus2 = { {3d,4d,5d}, {4d,7d,5d}, {3d,2d,10d} };
    42      protected double[][] testDataMinus = { {-1d,-2d,-3d}, {-2d,-5d,-3d},
    43              {-1d,0d,-8d} };
    44      protected double[] testDataRow1 = {1d,2d,3d};
    45      protected double[] testDataCol3 = {3d,3d,8d};
    46      protected double[][] testDataInv =
    47          { {-40d,16d,9d}, {13d,-5d,-3d}, {5d,-2d,-1d} };
    48      protected double[] preMultTest = {8,12,33};
    49      protected double[][] testData2 ={ {1d,2d,3d}, {2d,5d,3d}};
    50      protected double[][] testData2T = { {1d,2d}, {2d,5d}, {3d,3d}};
    51      protected double[][] testDataPlusInv =
    52          { {-39d,18d,12d}, {15d,0d,0d}, {6d,-2d,7d} };
    53
    54      // lu decomposition tests
    55      protected double[][] luData = { {2d,3d,3d}, {0d,5d,7d}, {6d,9d,8d} };
    56      protected double[][] luDataLUDecomposition = { {6d,9d,8d}, {0d,5d,7d},
    57              {0.33333333333333,0d,0.33333333333333} };
    58
    59      // singular matrices
    60      protected double[][] singular = { {2d,3d}, {2d,3d} };
    61      protected double[][] bigSingular = {{1d,2d,3d,4d}, {2d,5d,3d,4d},
    62              {7d,3d,256d,1930d}, {3d,7d,6d,8d}}; // 4th row = 1st + 2nd
    63      protected double[][] detData = { {1d,2d,3d}, {4d,5d,6d}, {7d,8d,10d} };
    64      protected double[][] detData2 = { {1d, 3d}, {2d, 4d}};
    65
    66      // vectors
    67      protected double[] testVector = {1,2,3};
    68      protected double[] testVector2 = {1,2,3,4};
    69
    70      // submatrix accessor tests
    71      protected double[][] subTestData = {{1, 2, 3, 4}, {1.5, 2.5, 3.5, 4.5},
    72              {2, 4, 6, 8}, {4, 5, 6, 7}};
    73      // array selections
    74      protected double[][] subRows02Cols13 = { {2, 4}, {4, 8}};
    75      protected double[][] subRows03Cols12 = { {2, 3}, {5, 6}};
    76      protected double[][] subRows03Cols123 = { {2, 3, 4} , {5, 6, 7}};
    77      // effective permutations
    78      protected double[][] subRows20Cols123 = { {4, 6, 8} , {2, 3, 4}};
    79      protected double[][] subRows31Cols31 = {{7, 5}, {4.5, 2.5}};
    80      // contiguous ranges
    81      protected double[][] subRows01Cols23 = {{3,4} , {3.5, 4.5}};
    82      protected double[][] subRows23Cols00 = {{2} , {4}};
    83      protected double[][] subRows00Cols33 = {{4}};
    84      // row matrices
    85      protected double[][] subRow0 = {{1,2,3,4}};
    86      protected double[][] subRow3 = {{4,5,6,7}};
    87      // column matrices
    88      protected double[][] subColumn1 = {{2}, {2.5}, {4}, {5}};
    89      protected double[][] subColumn3 = {{4}, {4.5}, {8}, {7}};
    90
    91      // tolerances
    92      protected double entryTolerance = 10E-16;
    93      protected double normTolerance = 10E-14;
    94
    95      public BigMatrixImplTest(String name) {
    96          super(name);
    97      }
    98
    99      public void setUp() {
    100
    101     }
    102
    103     public static Test suite() {
    104         TestSuite suite = new TestSuite(BigMatrixImplTest.class);
    105         suite.setName("BigMatrixImpl Tests");
    106         return suite;
    107     }
    108
    109     public static final double[] asDouble(BigDecimal[] data) {
    110         double d[] = new double[data.length];
    111         for (int i=0;i<d.length;i++) {
    112             d[i] = data[i].doubleValue();
    113         }
    114         return d;
    115     }
    116
    117     public static final double[][] asDouble(BigDecimal[][] data) {
    118         double d[][] = new double[data.length][data[0].length];
    119         for (int i=0;i<d.length;i++) {
    120             for (int j=0;j<d[i].length;j++)
    121             d[i][j] = data[i][j].doubleValue();
    122         }
    123         return d;
    124     }
    125
    126     public static final BigDecimal[] asBigDecimal(double [] data) {
    127         BigDecimal d[] = new BigDecimal[data.length];
    128         for (int i=0;i<d.length;i++) {
    129             d[i] = new BigDecimal(data[i]);
    130         }
    131         return d;
    132     }
    133
    134     public static final BigDecimal[][] asBigDecimal(double [][] data) {
    135         BigDecimal d[][] = new BigDecimal[data.length][data[0].length];
    136         for (int i=0;i<d.length;i++) {
    137             for (int j=0;j<data[i].length;j++) {
    138                 d[i][j] = new BigDecimal(data[i][j]);
    139             }
    140         }
    141         return d;
    142     }
    143
    144     /*** test dimensions */
    145     public void testDimensions() {
    146         BigMatrixImpl m = new BigMatrixImpl(testData);
    147         BigMatrixImpl m2 = new BigMatrixImpl(testData2);
    148         assertEquals("testData row dimension",3,m.getRowDimension());
    149         assertEquals("testData column dimension",3,m.getColumnDimension());
    150         assertTrue("testData is square",m.isSquare());
    151         assertEquals("testData2 row dimension",m2.getRowDimension(),2);
    152         assertEquals("testData2 column dimension",m2.getColumnDimension(),3);
    153         assertTrue("testData2 is not square",!m2.isSquare());
    154     }
    155
    156     /*** test copy functions */
    157     public void testCopyFunctions() {
    158         BigMatrixImpl m = new BigMatrixImpl(testData);
    159         BigMatrixImpl m2 = new BigMatrixImpl(m.getData());
    160         assertEquals(m2,m);
    161     }
    162
    163     /*** test constructors */
    164     public void testConstructors() {
    165         BigMatrix m1 = new BigMatrixImpl(testData);
    166         BigMatrix m2 = new BigMatrixImpl(testDataString);
    167         BigMatrix m3 = new BigMatrixImpl(asBigDecimal(testData));
    168         assertClose("double, string", m1, m2, Double.MIN_VALUE);
    169         assertClose("double, BigDecimal", m1, m3, Double.MIN_VALUE);
    170         assertClose("string, BigDecimal", m2, m3, Double.MIN_VALUE);
    171         try {
    172             BigMatrix m4 = new BigMatrixImpl(new String[][] {{"0", "hello", "1"}});
    173             fail("Expecting NumberFormatException");
    174         } catch (NumberFormatException ex) {
    175             // expected
    176         }
    177     }
    178
    179     /*** test add */
    180     public void testAdd() {
    181         BigMatrixImpl m = new BigMatrixImpl(testData);
    182         BigMatrixImpl mInv = new BigMatrixImpl(testDataInv);
    183         BigMatrixImpl mPlusMInv = (BigMatrixImpl)m.add(mInv);
    184         double[][] sumEntries = asDouble(mPlusMInv.getData());
    185         for (int row = 0; row < m.getRowDimension(); row++) {
    186             for (int col = 0; col < m.getColumnDimension(); col++) {
    187                 assertEquals("sum entry entry",
    188                     testDataPlusInv[row][col],sumEntries[row][col],
    189                         entryTolerance);
    190             }
    191         }
    192     }
    193
    194     /*** test add failure */
    195     public void testAddFail() {
    196         BigMatrixImpl m = new BigMatrixImpl(testData);
    197         BigMatrixImpl m2 = new BigMatrixImpl(testData2);
    198         try {
    199             BigMatrixImpl mPlusMInv = (BigMatrixImpl)m.add(m2);
    200             fail("IllegalArgumentException expected");
    201         } catch (IllegalArgumentException ex) {
    202             ;
    203         }
    204     }
    205
    206     /*** test norm */
    207     public void testNorm() {
    208         BigMatrixImpl m = new BigMatrixImpl(testData);
    209         BigMatrixImpl m2 = new BigMatrixImpl(testData2);
    210         assertEquals("testData norm",14d,m.getNorm().doubleValue(),entryTolerance);
    211         assertEquals("testData2 norm",7d,m2.getNorm().doubleValue(),entryTolerance);
    212     }
    213
    214      /*** test m-n = m + -n */
    215     public void testPlusMinus() {
    216         BigMatrixImpl m = new BigMatrixImpl(testData);
    217         BigMatrixImpl m2 = new BigMatrixImpl(testDataInv);
    218         assertClose("m-n = m + -n",m.subtract(m2),
    219             m2.scalarMultiply(new BigDecimal(-1d)).add(m),entryTolerance);
    220         try {
    221             BigMatrix a = m.subtract(new BigMatrixImpl(testData2));
    222             fail("Expecting illegalArgumentException");
    223         } catch (IllegalArgumentException ex) {
    224             ;
    225         }
    226     }
    227
    228     /*** test multiply */
    229      public void testMultiply() {
    230         BigMatrixImpl m = new BigMatrixImpl(testData);
    231         BigMatrixImpl mInv = new BigMatrixImpl(testDataInv);
    232         BigMatrixImpl identity = new BigMatrixImpl(id);
    233         BigMatrixImpl m2 = new BigMatrixImpl(testData2);
    234         assertClose("inverse multiply",m.multiply(mInv),
    235             identity,entryTolerance);
    236         assertClose("inverse multiply",mInv.multiply(m),
    237             identity,entryTolerance);
    238         assertClose("identity multiply",m.multiply(identity),
    239             m,entryTolerance);
    240         assertClose("identity multiply",identity.multiply(mInv),
    241             mInv,entryTolerance);
    242         assertClose("identity multiply",m2.multiply(identity),
    243             m2,entryTolerance);
    244         try {
    245             BigMatrix a = m.multiply(new BigMatrixImpl(bigSingular));
    246             fail("Expecting illegalArgumentException");
    247         } catch (IllegalArgumentException ex) {
    248             ;
    249         }
    250     }
    251
    252     //Additional Test for BigMatrixImplTest.testMultiply
    253
    254     private double[][] d3 = new double[][] {{1,2,3,4},{5,6,7,8}};
    255     private double[][] d4 = new double[][] {{1},{2},{3},{4}};
    256     private double[][] d5 = new double[][] {{30},{70}};
    257
    258     public void testMultiply2() {
    259        BigMatrix m3 = new BigMatrixImpl(d3);
    260        BigMatrix m4 = new BigMatrixImpl(d4);
    261        BigMatrix m5 = new BigMatrixImpl(d5);
    262        assertClose("m3*m4=m5", m3.multiply(m4), m5, entryTolerance);
    263    }
    264
    265     /*** test isSingular */
    266     public void testIsSingular() {
    267         BigMatrixImpl m = new BigMatrixImpl(singular);
    268         assertTrue("singular",m.isSingular());
    269         m = new BigMatrixImpl(bigSingular);
    270         assertTrue("big singular",m.isSingular());
    271         m = new BigMatrixImpl(id);
    272         assertTrue("identity nonsingular",!m.isSingular());
    273         m = new BigMatrixImpl(testData);
    274         assertTrue("testData nonsingular",!m.isSingular());
    275     }
    276
    277     /*** test inverse */
    278     public void testInverse() {
    279         BigMatrixImpl m = new BigMatrixImpl(testData);
    280         BigMatrix mInv = new BigMatrixImpl(testDataInv);
    281         assertClose("inverse",mInv,m.inverse(),normTolerance);
    282         assertClose("inverse^2",m,m.inverse().inverse(),10E-12);
    283
    284         // Not square
    285         m = new BigMatrixImpl(testData2);
    286         try {
    287             m.inverse();
    288             fail("Expecting InvalidMatrixException");
    289         } catch (InvalidMatrixException ex) {
    290             // expected
    291         }
    292
    293         // Singular
    294         m = new BigMatrixImpl(singular);
    295         try {
    296             m.inverse();
    297             fail("Expecting InvalidMatrixException");
    298         } catch (InvalidMatrixException ex) {
    299             // expected
    300         }
    301     }
    302
    303     /*** test solve */
    304     public void testSolve() {
    305         BigMatrixImpl m = new BigMatrixImpl(testData);
    306         BigMatrix mInv = new BigMatrixImpl(testDataInv);
    307         // being a bit slothful here -- actually testing that X = A^-1 * B
    308         assertClose("inverse-operate",
    309                     asDouble(mInv.operate(asBigDecimal(testVector))),
    310                     asDouble(m.solve(asBigDecimal(testVector))),
    311                     normTolerance);
    312         try {
    313             double[] x = asDouble(m.solve(asBigDecimal(testVector2)));
    314             fail("expecting IllegalArgumentException");
    315         } catch (IllegalArgumentException ex) {
    316             ;
    317         }
    318         BigMatrix bs = new BigMatrixImpl(bigSingular);
    319         try {
    320             BigMatrix a = bs.solve(bs);
    321             fail("Expecting InvalidMatrixException");
    322         } catch (InvalidMatrixException ex) {
    323             ;
    324         }
    325         try {
    326             BigMatrix a = m.solve(bs);
    327             fail("Expecting IllegalArgumentException");
    328         } catch (IllegalArgumentException ex) {
    329             ;
    330         }
    331         try {
    332             BigMatrix a = (new BigMatrixImpl(testData2)).solve(bs);
    333             fail("Expecting illegalArgumentException");
    334         } catch (IllegalArgumentException ex) {
    335             ;
    336         }
    337         try {
    338             (new BigMatrixImpl(testData2)).luDecompose();
    339             fail("Expecting InvalidMatrixException");
    340         } catch (InvalidMatrixException ex) {
    341             ;
    342         }
    343     }
    344
    345     /*** test determinant */
    346     public void testDeterminant() {
    347         BigMatrix m = new BigMatrixImpl(bigSingular);
    348         assertEquals("singular determinant",0,m.getDeterminant().doubleValue(),0);
    349         m = new BigMatrixImpl(detData);
    350         assertEquals("nonsingular test",-3d,m.getDeterminant().doubleValue(),normTolerance);
    351
    352         // Examples verified against R (version 1.8.1, Red Hat Linux 9)
    353         m = new BigMatrixImpl(detData2);
    354         assertEquals("nonsingular R test 1",-2d,m.getDeterminant().doubleValue(),normTolerance);
    355         m = new BigMatrixImpl(testData);
    356         assertEquals("nonsingular  R test 2",-1d,m.getDeterminant().doubleValue(),normTolerance);
    357
    358         try {
    359             double a = new BigMatrixImpl(testData2).getDeterminant().doubleValue();
    360             fail("Expecting InvalidMatrixException");
    361         } catch (InvalidMatrixException ex) {
    362             ;
    363         }
    364     }
    365
    366     /*** test trace */
    367     public void testTrace() {
    368         BigMatrix m = new BigMatrixImpl(id);
    369         assertEquals("identity trace",3d,m.getTrace().doubleValue(),entryTolerance);
    370         m = new BigMatrixImpl(testData2);
    371         try {
    372             double x = m.getTrace().doubleValue();
    373             fail("Expecting illegalArgumentException");
    374         } catch (IllegalArgumentException ex) {
    375             ;
    376         }
    377     }
    378
    379     /*** test sclarAdd */
    380     public void testScalarAdd() {
    381         BigMatrix m = new BigMatrixImpl(testData);
    382         assertClose("scalar add",new BigMatrixImpl(testDataPlus2),
    383             m.scalarAdd(new BigDecimal(2d)),entryTolerance);
    384     }
    385
    386     /*** test operate */
    387     public void testOperate() {
    388         BigMatrix m = new BigMatrixImpl(id);
    389         double[] x = asDouble(m.operate(asBigDecimal(testVector)));
    390         assertClose("identity operate",testVector,x,entryTolerance);
    391         m = new BigMatrixImpl(bigSingular);
    392         try {
    393             x = asDouble(m.operate(asBigDecimal(testVector)));
    394             fail("Expecting illegalArgumentException");
    395         } catch (IllegalArgumentException ex) {
    396             ;
    397         }
    398     }
    399
    400     /*** test transpose */
    401     public void testTranspose() {
    402         BigMatrix m = new BigMatrixImpl(testData);
    403         assertClose("inverse-transpose",m.inverse().transpose(),
    404             m.transpose().inverse(),normTolerance);
    405         m = new BigMatrixImpl(testData2);
    406         BigMatrix mt = new BigMatrixImpl(testData2T);
    407         assertClose("transpose",mt,m.transpose(),normTolerance);
    408     }
    409
    410     /*** test preMultiply by vector */
    411     public void testPremultiplyVector() {
    412         BigMatrix m = new BigMatrixImpl(testData);
    413         assertClose("premultiply",asDouble(m.preMultiply(asBigDecimal(testVector))),preMultTest,normTolerance);
    414         m = new BigMatrixImpl(bigSingular);
    415         try {
    416             m.preMultiply(asBigDecimal(testVector));
    417             fail("expecting IllegalArgumentException");
    418         } catch (IllegalArgumentException ex) {
    419             ;
    420         }
    421     }
    422
    423     public void testPremultiply() {
    424         BigMatrix m3 = new BigMatrixImpl(d3);
    425         BigMatrix m4 = new BigMatrixImpl(d4);
    426         BigMatrix m5 = new BigMatrixImpl(d5);
    427         assertClose("m3*m4=m5", m4.preMultiply(m3), m5, entryTolerance);
    428
    429         BigMatrixImpl m = new BigMatrixImpl(testData);
    430         BigMatrixImpl mInv = new BigMatrixImpl(testDataInv);
    431         BigMatrixImpl identity = new BigMatrixImpl(id);
    432         BigMatrixImpl m2 = new BigMatrixImpl(testData2);
    433         assertClose("inverse multiply",m.preMultiply(mInv),
    434                 identity,entryTolerance);
    435         assertClose("inverse multiply",mInv.preMultiply(m),
    436                 identity,entryTolerance);
    437         assertClose("identity multiply",m.preMultiply(identity),
    438                 m,entryTolerance);
    439         assertClose("identity multiply",identity.preMultiply(mInv),
    440                 mInv,entryTolerance);
    441         try {
    442             BigMatrix a = m.preMultiply(new BigMatrixImpl(bigSingular));
    443             fail("Expecting illegalArgumentException");
    444         } catch (IllegalArgumentException ex) {
    445             ;
    446         }
    447     }
    448
    449     public void testGetVectors() {
    450         BigMatrix m = new BigMatrixImpl(testData);
    451         assertClose("get row",m.getRowAsDoubleArray(0),testDataRow1,entryTolerance);
    452         assertClose("get col",m.getColumnAsDoubleArray(2),testDataCol3,entryTolerance);
    453         try {
    454             double[] x = m.getRowAsDoubleArray(10);
    455             fail("expecting MatrixIndexException");
    456         } catch (MatrixIndexException ex) {
    457             ;
    458         }
    459         try {
    460             double[] x = m.getColumnAsDoubleArray(-1);
    461             fail("expecting MatrixIndexException");
    462         } catch (MatrixIndexException ex) {
    463             ;
    464         }
    465     }
    466
    467     public void testLUDecomposition() throws Exception {
    468         BigMatrixImpl m = new BigMatrixImpl(testData);
    469         BigMatrix lu = m.getLUMatrix();
    470         assertClose("LU decomposition", lu, (BigMatrix) new BigMatrixImpl(testDataLU), normTolerance);
    471         verifyDecomposition(m, lu);
    472         m = new BigMatrixImpl(luData);
    473         lu = m.getLUMatrix();
    474         assertClose("LU decomposition", lu, (BigMatrix) new BigMatrixImpl(luDataLUDecomposition), normTolerance);
    475         verifyDecomposition(m, lu);
    476         m = new BigMatrixImpl(testDataMinus);
    477         lu = m.getLUMatrix();
    478         verifyDecomposition(m, lu);
    479         m = new BigMatrixImpl(id);
    480         lu = m.getLUMatrix();
    481         verifyDecomposition(m, lu);
    482         try {
    483             m = new BigMatrixImpl(bigSingular); // singular
    484             lu = m.getLUMatrix();
    485             fail("Expecting InvalidMatrixException");
    486         } catch (InvalidMatrixException ex) {
    487             // expected
    488         }
    489         try {
    490             m = new BigMatrixImpl(testData2);  // not square
    491             lu = m.getLUMatrix();
    492             fail("Expecting InvalidMatrixException");
    493         } catch (InvalidMatrixException ex) {
    494             // expected
    495         }
    496     }
    497
    498    /***
    499     * test submatrix accessors
    500     */
    501     public void testSubMatrix() {
    502         BigMatrix m = new BigMatrixImpl(subTestData);
    503         BigMatrix mRows23Cols00 = new BigMatrixImpl(subRows23Cols00);
    504         BigMatrix mRows00Cols33 = new BigMatrixImpl(subRows00Cols33);
    505         BigMatrix mRows01Cols23 = new BigMatrixImpl(subRows01Cols23);
    506         BigMatrix mRows02Cols13 = new BigMatrixImpl(subRows02Cols13);
    507         BigMatrix mRows03Cols12 = new BigMatrixImpl(subRows03Cols12);
    508         BigMatrix mRows03Cols123 = new BigMatrixImpl(subRows03Cols123);
    509         BigMatrix mRows20Cols123 = new BigMatrixImpl(subRows20Cols123);
    510         BigMatrix mRows31Cols31 = new BigMatrixImpl(subRows31Cols31);
    511         assertEquals("Rows23Cols00", mRows23Cols00,
    512                 m.getSubMatrix(2 , 3 , 0, 0));
    513         assertEquals("Rows00Cols33", mRows00Cols33,
    514                 m.getSubMatrix(0 , 0 , 3, 3));
    515         assertEquals("Rows01Cols23", mRows01Cols23,
    516                 m.getSubMatrix(0 , 1 , 2, 3));
    517         assertEquals("Rows02Cols13", mRows02Cols13,
    518                 m.getSubMatrix(new int[] {0,2}, new int[] {1,3}));
    519         assertEquals("Rows03Cols12", mRows03Cols12,
    520                 m.getSubMatrix(new int[] {0,3}, new int[] {1,2}));
    521         assertEquals("Rows03Cols123", mRows03Cols123,
    522                 m.getSubMatrix(new int[] {0,3}, new int[] {1,2,3}));
    523         assertEquals("Rows20Cols123", mRows20Cols123,
    524                 m.getSubMatrix(new int[] {2,0}, new int[] {1,2,3}));
    525         assertEquals("Rows31Cols31", mRows31Cols31,
    526                 m.getSubMatrix(new int[] {3,1}, new int[] {3,1}));
    527         assertEquals("Rows31Cols31", mRows31Cols31,
    528                 m.getSubMatrix(new int[] {3,1}, new int[] {3,1}));
    529
    530         try {
    531             m.getSubMatrix(1,0,2,4);
    532             fail("Expecting MatrixIndexException");
    533         } catch (MatrixIndexException ex) {
    534             // expected
    535         }
    536         try {
    537             m.getSubMatrix(-1,1,2,2);
    538             fail("Expecting MatrixIndexException");
    539         } catch (MatrixIndexException ex) {
    540             // expected
    541         }
    542         try {
    543             m.getSubMatrix(1,0,2,2);
    544             fail("Expecting MatrixIndexException");
    545         } catch (MatrixIndexException ex) {
    546             // expected
    547         }
    548         try {
    549             m.getSubMatrix(1,0,2,4);
    550             fail("Expecting MatrixIndexException");
    551         } catch (MatrixIndexException ex) {
    552             // expected
    553         }
    554         try {
    555             m.getSubMatrix(new int[] {}, new int[] {0});
    556             fail("Expecting MatrixIndexException");
    557         } catch (MatrixIndexException ex) {
    558             // expected
    559         }
    560         try {
    561             m.getSubMatrix(new int[] {0}, new int[] {4});
    562             fail("Expecting MatrixIndexException");
    563         } catch (MatrixIndexException ex) {
    564             // expected
    565         }
    566     }
    567
    568     public void testGetColumnMatrix() {
    569         BigMatrix m = new BigMatrixImpl(subTestData);
    570         BigMatrix mColumn1 = new BigMatrixImpl(subColumn1);
    571         BigMatrix mColumn3 = new BigMatrixImpl(subColumn3);
    572         assertEquals("Column1", mColumn1,
    573                 m.getColumnMatrix(1));
    574         assertEquals("Column3", mColumn3,
    575                 m.getColumnMatrix(3));
    576         try {
    577             m.getColumnMatrix(-1);
    578             fail("Expecting MatrixIndexException");
    579         } catch (MatrixIndexException ex) {
    580             // expected
    581         }
    582         try {
    583             m.getColumnMatrix(4);
    584             fail("Expecting MatrixIndexException");
    585         } catch (MatrixIndexException ex) {
    586             // expected
    587         }
    588     }
    589
    590     public void testGetRowMatrix() {
    591         BigMatrix m = new BigMatrixImpl(subTestData);
    592         BigMatrix mRow0 = new BigMatrixImpl(subRow0);
    593         BigMatrix mRow3 = new BigMatrixImpl(subRow3);
    594         assertEquals("Row0", mRow0,
    595                 m.getRowMatrix(0));
    596         assertEquals("Row3", mRow3,
    597                 m.getRowMatrix(3));
    598         try {
    599             m.getRowMatrix(-1);
    600             fail("Expecting MatrixIndexException");
    601         } catch (MatrixIndexException ex) {
    602             // expected
    603         }
    604         try {
    605             m.getRowMatrix(4);
    606             fail("Expecting MatrixIndexException");
    607         } catch (MatrixIndexException ex) {
    608             // expected
    609         }
    610     }
    611
    612     public void testEqualsAndHashCode() {
    613         BigMatrixImpl m = new BigMatrixImpl(testData);
    614         BigMatrixImpl m1 = (BigMatrixImpl) m.copy();
    615         BigMatrixImpl mt = (BigMatrixImpl) m.transpose();
    616         assertTrue(m.hashCode() != mt.hashCode());
    617         assertEquals(m.hashCode(), m1.hashCode());
    618         assertEquals(m, m);
    619         assertEquals(m, m1);
    620         assertFalse(m.equals(null));
    621         assertFalse(m.equals(mt));
    622         assertFalse(m.equals(new BigMatrixImpl(bigSingular)));
    623         // Different scales make BigDecimals, so matrices unequal
    624         m = new BigMatrixImpl(new String[][] {{"2.0"}});
    625         m1 = new BigMatrixImpl(new String[][] {{"2.00"}});
    626         assertTrue(m.hashCode() != m1.hashCode());
    627         assertFalse(m.equals(m1));
    628     }
    629
    630     public void testToString() {
    631         BigMatrixImpl m = new BigMatrixImpl(testData);
    632         assertEquals("BigMatrixImpl{{1,2,3},{2,5,3},{1,0,8}}",
    633                 m.toString());
    634         m = new BigMatrixImpl();
    635         assertEquals("BigMatrixImpl{}",
    636                 m.toString());
    637     }
    638
    639     //--------------- -----------------Protected methods
    640
    641     /*** verifies that two matrices are close (1-norm) */
    642     protected void assertClose(String msg, BigMatrix m, BigMatrix n,
    643         double tolerance) {
    644         assertTrue(msg,m.subtract(n).getNorm().doubleValue() < tolerance);
    645     }
    646
    647     /*** verifies that two vectors are close (sup norm) */
    648     protected void assertClose(String msg, double[] m, double[] n,
    649         double tolerance) {
    650         if (m.length != n.length) {
    651             fail("vectors not same length");
    652         }
    653         for (int i = 0; i < m.length; i++) {
    654             assertEquals(msg + " " +  i + " elements differ",
    655                 m[i],n[i],tolerance);
    656         }
    657     }
    658
    659     /*** extracts the l  and u matrices from compact lu representation */
    660     protected void splitLU(BigMatrix lu, BigDecimal[][] lowerData, BigDecimal[][] upperData) throws InvalidMatrixException {
    661         if (!lu.isSquare() || lowerData.length != lowerData[0].length || upperData.length != upperData[0].length ||
    662                 lowerData.length != upperData.length
    663                 || lowerData.length != lu.getRowDimension()) {
    664             throw new InvalidMatrixException("incorrect dimensions");
    665         }
    666         int n = lu.getRowDimension();
    667         for (int i = 0; i < n; i++) {
    668             for (int j = 0; j < n; j++) {
    669                 if (j < i) {
    670                     lowerData[i][j] = lu.getEntry(i, j);
    671                     upperData[i][j] = new BigDecimal(0);
    672                 } else if (i == j) {
    673                     lowerData[i][j] = new BigDecimal(1);
    674                     upperData[i][j] = lu.getEntry(i, j);
    675                 } else {
    676                     lowerData[i][j] = new BigDecimal(0);
    677                     upperData[i][j] = lu.getEntry(i, j);
    678                 }
    679             }
    680         }
    681     }
    682
    683     /*** Returns the result of applying the given row permutation to the matrix */
    684     protected BigMatrix permuteRows(BigMatrix matrix, int[] permutation) {
    685         if (!matrix.isSquare() || matrix.getRowDimension() != permutation.length) {
    686             throw new IllegalArgumentException("dimension mismatch");
    687         }
    688         int n = matrix.getRowDimension();
    689         int m = matrix.getColumnDimension();
    690         BigDecimal out[][] = new BigDecimal[m][n];
    691         for (int i = 0; i < n; i++) {
    692             for (int j = 0; j < m; j++) {
    693                 out[i][j] = matrix.getEntry(permutation[i], j);
    694             }
    695         }
    696         return new BigMatrixImpl(out);
    697     }
    698
    699     /*** Extracts l and u matrices from lu and verifies that matrix = l times u modulo permutation */
    700     protected void verifyDecomposition(BigMatrix matrix, BigMatrix lu) throws Exception{
    701         int n = matrix.getRowDimension();
    702         BigDecimal[][] lowerData = new BigDecimal[n][n];
    703         BigDecimal[][] upperData = new BigDecimal[n][n];
    704         splitLU(lu, lowerData, upperData);
    705         BigMatrix lower =new BigMatrixImpl(lowerData);
    706         BigMatrix upper = new BigMatrixImpl(upperData);
    707         int[] permutation = ((BigMatrixImpl) matrix).getPermutation();
    708         BigMatrix permuted = permuteRows(matrix, permutation);
    709         assertClose("lu decomposition does not work", permuted,
    710                 lower.multiply(upper), normTolerance);
    711     }
    712
    713     /*** Useful for debugging */
    714     private void dumpMatrix(BigMatrix m) {
    715           for (int i = 0; i < m.getRowDimension(); i++) {
    716               String os = "";
    717               for (int j = 0; j < m.getColumnDimension(); j++) {
    718                   os += m.getEntry(i, j) + " ";
    719               }
    720               System.out.println(os);
    721           }
    722     }
    723
    724 }
    725