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 java.math.BigDecimal; 024 025 026 /** 027 * Test cases for the {@link BigMatrixImpl} class. 028 * 029 * @version $Revision: 790372 $ $Date: 2009-07-01 16:48:19 -0400 (Wed, 01 Jul 2009) $ 030 */ 031 @Deprecated 032 public final class BigMatrixImplTest extends TestCase { 033 034 // Test data for String constructors 035 protected String[][] testDataString = { {"1","2","3"}, {"2","5","3"}, {"1","0","8"} }; 036 037 // 3 x 3 identity matrix 038 protected double[][] id = { {1d,0d,0d}, {0d,1d,0d}, {0d,0d,1d} }; 039 040 // Test data for group operations 041 protected double[][] testData = { {1d,2d,3d}, {2d,5d,3d}, {1d,0d,8d} }; 042 protected double[][] testDataLU = {{2d, 5d, 3d}, {.5d, -2.5d, 6.5d}, {0.5d, 0.2d, .2d}}; 043 protected double[][] testDataPlus2 = { {3d,4d,5d}, {4d,7d,5d}, {3d,2d,10d} }; 044 protected double[][] testDataMinus = { {-1d,-2d,-3d}, {-2d,-5d,-3d}, 045 {-1d,0d,-8d} }; 046 protected double[] testDataRow1 = {1d,2d,3d}; 047 protected double[] testDataCol3 = {3d,3d,8d}; 048 protected double[][] testDataInv = 049 { {-40d,16d,9d}, {13d,-5d,-3d}, {5d,-2d,-1d} }; 050 protected double[] preMultTest = {8,12,33}; 051 protected double[][] testData2 ={ {1d,2d,3d}, {2d,5d,3d}}; 052 protected double[][] testData2T = { {1d,2d}, {2d,5d}, {3d,3d}}; 053 protected double[][] testDataPlusInv = 054 { {-39d,18d,12d}, {15d,0d,0d}, {6d,-2d,7d} }; 055 056 // lu decomposition tests 057 protected double[][] luData = { {2d,3d,3d}, {0d,5d,7d}, {6d,9d,8d} }; 058 protected double[][] luDataLUDecomposition = { {6d,9d,8d}, {0d,5d,7d}, 059 {0.33333333333333,0d,0.33333333333333} }; 060 061 // singular matrices 062 protected double[][] singular = { {2d,3d}, {2d,3d} }; 063 protected double[][] bigSingular = {{1d,2d,3d,4d}, {2d,5d,3d,4d}, 064 {7d,3d,256d,1930d}, {3d,7d,6d,8d}}; // 4th row = 1st + 2nd 065 protected double[][] detData = { {1d,2d,3d}, {4d,5d,6d}, {7d,8d,10d} }; 066 protected double[][] detData2 = { {1d, 3d}, {2d, 4d}}; 067 068 // vectors 069 protected double[] testVector = {1,2,3}; 070 protected double[] testVector2 = {1,2,3,4}; 071 072 // submatrix accessor tests 073 protected double[][] subTestData = {{1, 2, 3, 4}, {1.5, 2.5, 3.5, 4.5}, 074 {2, 4, 6, 8}, {4, 5, 6, 7}}; 075 // array selections 076 protected double[][] subRows02Cols13 = { {2, 4}, {4, 8}}; 077 protected double[][] subRows03Cols12 = { {2, 3}, {5, 6}}; 078 protected double[][] subRows03Cols123 = { {2, 3, 4} , {5, 6, 7}}; 079 // effective permutations 080 protected double[][] subRows20Cols123 = { {4, 6, 8} , {2, 3, 4}}; 081 protected double[][] subRows31Cols31 = {{7, 5}, {4.5, 2.5}}; 082 // contiguous ranges 083 protected double[][] subRows01Cols23 = {{3,4} , {3.5, 4.5}}; 084 protected double[][] subRows23Cols00 = {{2} , {4}}; 085 protected double[][] subRows00Cols33 = {{4}}; 086 // row matrices 087 protected double[][] subRow0 = {{1,2,3,4}}; 088 protected double[][] subRow3 = {{4,5,6,7}}; 089 // column matrices 090 protected double[][] subColumn1 = {{2}, {2.5}, {4}, {5}}; 091 protected double[][] subColumn3 = {{4}, {4.5}, {8}, {7}}; 092 093 // tolerances 094 protected double entryTolerance = 10E-16; 095 protected double normTolerance = 10E-14; 096 097 public BigMatrixImplTest(String name) { 098 super(name); 099 } 100 101 public static Test suite() { 102 TestSuite suite = new TestSuite(BigMatrixImplTest.class); 103 suite.setName("BigMatrixImpl Tests"); 104 return suite; 105 } 106 107 public static final double[] asDouble(BigDecimal[] data) { 108 double d[] = new double[data.length]; 109 for (int i=0;i<d.length;i++) { 110 d[i] = data[i].doubleValue(); 111 } 112 return d; 113 } 114 115 public static final double[][] asDouble(BigDecimal[][] data) { 116 double d[][] = new double[data.length][data[0].length]; 117 for (int i=0;i<d.length;i++) { 118 for (int j=0;j<d[i].length;j++) 119 d[i][j] = data[i][j].doubleValue(); 120 } 121 return d; 122 } 123 124 public static final BigDecimal[] asBigDecimal(double [] data) { 125 BigDecimal d[] = new BigDecimal[data.length]; 126 for (int i=0;i<d.length;i++) { 127 d[i] = new BigDecimal(data[i]); 128 } 129 return d; 130 } 131 132 public static final BigDecimal[][] asBigDecimal(double [][] data) { 133 BigDecimal d[][] = new BigDecimal[data.length][data[0].length]; 134 for (int i=0;i<d.length;i++) { 135 for (int j=0;j<data[i].length;j++) { 136 d[i][j] = new BigDecimal(data[i][j]); 137 } 138 } 139 return d; 140 } 141 142 /** test dimensions */ 143 public void testDimensions() { 144 BigMatrixImpl m = new BigMatrixImpl(testData); 145 BigMatrixImpl m2 = new BigMatrixImpl(testData2); 146 assertEquals("testData row dimension",3,m.getRowDimension()); 147 assertEquals("testData column dimension",3,m.getColumnDimension()); 148 assertTrue("testData is square",m.isSquare()); 149 assertEquals("testData2 row dimension",m2.getRowDimension(),2); 150 assertEquals("testData2 column dimension",m2.getColumnDimension(),3); 151 assertTrue("testData2 is not square",!m2.isSquare()); 152 } 153 154 /** test copy functions */ 155 public void testCopyFunctions() { 156 BigMatrixImpl m1 = new BigMatrixImpl(testData); 157 BigMatrixImpl m2 = new BigMatrixImpl(m1.getData()); 158 assertEquals(m2,m1); 159 BigMatrixImpl m3 = new BigMatrixImpl(testData); 160 BigMatrixImpl m4 = new BigMatrixImpl(m3.getData(), false); 161 assertEquals(m4,m3); 162 } 163 164 /** test constructors */ 165 public void testConstructors() { 166 BigMatrix m1 = new BigMatrixImpl(testData); 167 BigMatrix m2 = new BigMatrixImpl(testDataString); 168 BigMatrix m3 = new BigMatrixImpl(asBigDecimal(testData)); 169 BigMatrix m4 = new BigMatrixImpl(asBigDecimal(testData), true); 170 BigMatrix m5 = new BigMatrixImpl(asBigDecimal(testData), false); 171 assertClose("double, string", m1, m2, Double.MIN_VALUE); 172 assertClose("double, BigDecimal", m1, m3, Double.MIN_VALUE); 173 assertClose("string, BigDecimal", m2, m3, Double.MIN_VALUE); 174 assertClose("double, BigDecimal/true", m1, m4, Double.MIN_VALUE); 175 assertClose("double, BigDecimal/false", m1, m5, Double.MIN_VALUE); 176 try { 177 new BigMatrixImpl(new String[][] {{"0", "hello", "1"}}); 178 fail("Expecting NumberFormatException"); 179 } catch (NumberFormatException ex) { 180 // expected 181 } 182 try { 183 new BigMatrixImpl(new String[][] {}); 184 fail("Expecting IllegalArgumentException"); 185 } catch (IllegalArgumentException ex) { 186 // expected 187 } 188 try { 189 new BigMatrixImpl(new String[][] {{},{}}); 190 fail("Expecting IllegalArgumentException"); 191 } catch (IllegalArgumentException ex) { 192 // expected 193 } 194 try { 195 new BigMatrixImpl(new String[][] {{"a", "b"},{"c"}}); 196 fail("Expecting IllegalArgumentException"); 197 } catch (IllegalArgumentException ex) { 198 // expected 199 } 200 201 try { 202 new BigMatrixImpl(0, 1); 203 fail("Expecting IllegalArgumentException"); 204 } catch (IllegalArgumentException ex) { 205 // expected 206 } 207 try { 208 new BigMatrixImpl(1, 0); 209 fail("Expecting IllegalArgumentException"); 210 } catch (IllegalArgumentException ex) { 211 // expected 212 } 213 } 214 215 /** test add */ 216 public void testAdd() { 217 BigMatrixImpl m = new BigMatrixImpl(testData); 218 BigMatrixImpl mInv = new BigMatrixImpl(testDataInv); 219 BigMatrix mPlusMInv = m.add(mInv); 220 double[][] sumEntries = asDouble(mPlusMInv.getData()); 221 for (int row = 0; row < m.getRowDimension(); row++) { 222 for (int col = 0; col < m.getColumnDimension(); col++) { 223 assertEquals("sum entry entry", 224 testDataPlusInv[row][col],sumEntries[row][col], 225 entryTolerance); 226 } 227 } 228 } 229 230 /** test add failure */ 231 public void testAddFail() { 232 BigMatrixImpl m = new BigMatrixImpl(testData); 233 BigMatrixImpl m2 = new BigMatrixImpl(testData2); 234 try { 235 m.add(m2); 236 fail("IllegalArgumentException expected"); 237 } catch (IllegalArgumentException ex) { 238 // ignored 239 } 240 } 241 242 /** test norm */ 243 public void testNorm() { 244 BigMatrixImpl m = new BigMatrixImpl(testData); 245 BigMatrixImpl m2 = new BigMatrixImpl(testData2); 246 assertEquals("testData norm",14d,m.getNorm().doubleValue(),entryTolerance); 247 assertEquals("testData2 norm",7d,m2.getNorm().doubleValue(),entryTolerance); 248 } 249 250 /** test m-n = m + -n */ 251 public void testPlusMinus() { 252 BigMatrixImpl m = new BigMatrixImpl(testData); 253 BigMatrixImpl m2 = new BigMatrixImpl(testDataInv); 254 assertClose("m-n = m + -n",m.subtract(m2), 255 m2.scalarMultiply(new BigDecimal(-1d)).add(m),entryTolerance); 256 try { 257 m.subtract(new BigMatrixImpl(testData2)); 258 fail("Expecting illegalArgumentException"); 259 } catch (IllegalArgumentException ex) { 260 // ignored 261 } 262 } 263 264 /** test multiply */ 265 public void testMultiply() { 266 BigMatrixImpl m = new BigMatrixImpl(testData); 267 BigMatrixImpl mInv = new BigMatrixImpl(testDataInv); 268 BigMatrixImpl identity = new BigMatrixImpl(id); 269 BigMatrixImpl m2 = new BigMatrixImpl(testData2); 270 assertClose("inverse multiply",m.multiply(mInv), 271 identity,entryTolerance); 272 assertClose("inverse multiply",mInv.multiply(m), 273 identity,entryTolerance); 274 assertClose("identity multiply",m.multiply(identity), 275 m,entryTolerance); 276 assertClose("identity multiply",identity.multiply(mInv), 277 mInv,entryTolerance); 278 assertClose("identity multiply",m2.multiply(identity), 279 m2,entryTolerance); 280 try { 281 m.multiply(new BigMatrixImpl(bigSingular)); 282 fail("Expecting illegalArgumentException"); 283 } catch (IllegalArgumentException ex) { 284 // ignored 285 } 286 } 287 288 //Additional Test for BigMatrixImplTest.testMultiply 289 290 private double[][] d3 = new double[][] {{1,2,3,4},{5,6,7,8}}; 291 private double[][] d4 = new double[][] {{1},{2},{3},{4}}; 292 private double[][] d5 = new double[][] {{30},{70}}; 293 294 public void testMultiply2() { 295 BigMatrix m3 = new BigMatrixImpl(d3); 296 BigMatrix m4 = new BigMatrixImpl(d4); 297 BigMatrix m5 = new BigMatrixImpl(d5); 298 assertClose("m3*m4=m5", m3.multiply(m4), m5, entryTolerance); 299 } 300 301 /** test isSingular */ 302 public void testIsSingular() { 303 BigMatrixImpl m = new BigMatrixImpl(singular); 304 assertTrue("singular",m.isSingular()); 305 m = new BigMatrixImpl(bigSingular); 306 assertTrue("big singular",m.isSingular()); 307 m = new BigMatrixImpl(id); 308 assertTrue("identity nonsingular",!m.isSingular()); 309 m = new BigMatrixImpl(testData); 310 assertTrue("testData nonsingular",!m.isSingular()); 311 } 312 313 /** test inverse */ 314 public void testInverse() { 315 BigMatrixImpl m = new BigMatrixImpl(testData); 316 BigMatrix mInv = new BigMatrixImpl(testDataInv); 317 assertClose("inverse",mInv,m.inverse(),normTolerance); 318 assertClose("inverse^2",m,m.inverse().inverse(),10E-12); 319 320 // Not square 321 m = new BigMatrixImpl(testData2); 322 try { 323 m.inverse(); 324 fail("Expecting InvalidMatrixException"); 325 } catch (InvalidMatrixException ex) { 326 // expected 327 } 328 329 // Singular 330 m = new BigMatrixImpl(singular); 331 try { 332 m.inverse(); 333 fail("Expecting InvalidMatrixException"); 334 } catch (InvalidMatrixException ex) { 335 // expected 336 } 337 } 338 339 /** test solve */ 340 public void testSolve() { 341 BigMatrixImpl m = new BigMatrixImpl(testData); 342 BigMatrix mInv = new BigMatrixImpl(testDataInv); 343 // being a bit slothful here -- actually testing that X = A^-1 * B 344 assertClose("inverse-operate", 345 asDouble(mInv.operate(asBigDecimal(testVector))), 346 asDouble(m.solve(asBigDecimal(testVector))), 347 normTolerance); 348 try { 349 asDouble(m.solve(asBigDecimal(testVector2))); 350 fail("expecting IllegalArgumentException"); 351 } catch (IllegalArgumentException ex) { 352 // ignored 353 } 354 BigMatrix bs = new BigMatrixImpl(bigSingular); 355 try { 356 bs.solve(bs); 357 fail("Expecting InvalidMatrixException"); 358 } catch (InvalidMatrixException ex) { 359 // ignored 360 } 361 try { 362 m.solve(bs); 363 fail("Expecting IllegalArgumentException"); 364 } catch (IllegalArgumentException ex) { 365 // ignored 366 } 367 try { 368 new BigMatrixImpl(testData2).solve(bs); 369 fail("Expecting illegalArgumentException"); 370 } catch (IllegalArgumentException ex) { 371 // ignored 372 } 373 try { 374 (new BigMatrixImpl(testData2)).luDecompose(); 375 fail("Expecting InvalidMatrixException"); 376 } catch (InvalidMatrixException ex) { 377 // ignored 378 } 379 } 380 381 /** test determinant */ 382 public void testDeterminant() { 383 BigMatrix m = new BigMatrixImpl(bigSingular); 384 assertEquals("singular determinant",0,m.getDeterminant().doubleValue(),0); 385 m = new BigMatrixImpl(detData); 386 assertEquals("nonsingular test",-3d,m.getDeterminant().doubleValue(),normTolerance); 387 388 // Examples verified against R (version 1.8.1, Red Hat Linux 9) 389 m = new BigMatrixImpl(detData2); 390 assertEquals("nonsingular R test 1",-2d,m.getDeterminant().doubleValue(),normTolerance); 391 m = new BigMatrixImpl(testData); 392 assertEquals("nonsingular R test 2",-1d,m.getDeterminant().doubleValue(),normTolerance); 393 394 try { 395 double d = new BigMatrixImpl(testData2).getDeterminant().doubleValue(); 396 fail("Expecting InvalidMatrixException, got " + d); 397 } catch (InvalidMatrixException ex) { 398 // ignored 399 } 400 } 401 402 /** test trace */ 403 public void testTrace() { 404 BigMatrix m = new BigMatrixImpl(id); 405 assertEquals("identity trace",3d,m.getTrace().doubleValue(),entryTolerance); 406 m = new BigMatrixImpl(testData2); 407 try { 408 double t = m.getTrace().doubleValue(); 409 fail("Expecting NonSquareMatrixException, got " + t); 410 } catch (NonSquareMatrixException ex) { 411 // ignored 412 } 413 } 414 415 /** test sclarAdd */ 416 public void testScalarAdd() { 417 BigMatrix m = new BigMatrixImpl(testData); 418 assertClose("scalar add",new BigMatrixImpl(testDataPlus2), 419 m.scalarAdd(new BigDecimal(2d)),entryTolerance); 420 } 421 422 /** test operate */ 423 public void testOperate() { 424 BigMatrix m = new BigMatrixImpl(id); 425 double[] x = asDouble(m.operate(asBigDecimal(testVector))); 426 assertClose("identity operate",testVector,x,entryTolerance); 427 m = new BigMatrixImpl(bigSingular); 428 try { 429 asDouble(m.operate(asBigDecimal(testVector))); 430 fail("Expecting illegalArgumentException"); 431 } catch (IllegalArgumentException ex) { 432 // ignored 433 } 434 } 435 436 /** test issue MATH-209 */ 437 public void testMath209() { 438 BigMatrix a = new BigMatrixImpl(new BigDecimal[][] { 439 { new BigDecimal(1), new BigDecimal(2) }, 440 { new BigDecimal(3), new BigDecimal(4) }, 441 { new BigDecimal(5), new BigDecimal(6) } 442 }, false); 443 BigDecimal[] b = a.operate(new BigDecimal[] { new BigDecimal(1), new BigDecimal(1) }); 444 assertEquals(a.getRowDimension(), b.length); 445 assertEquals( 3.0, b[0].doubleValue(), 1.0e-12); 446 assertEquals( 7.0, b[1].doubleValue(), 1.0e-12); 447 assertEquals(11.0, b[2].doubleValue(), 1.0e-12); 448 } 449 450 /** test transpose */ 451 public void testTranspose() { 452 BigMatrix m = new BigMatrixImpl(testData); 453 assertClose("inverse-transpose",m.inverse().transpose(), 454 m.transpose().inverse(),normTolerance); 455 m = new BigMatrixImpl(testData2); 456 BigMatrix mt = new BigMatrixImpl(testData2T); 457 assertClose("transpose",mt,m.transpose(),normTolerance); 458 } 459 460 /** test preMultiply by vector */ 461 public void testPremultiplyVector() { 462 BigMatrix m = new BigMatrixImpl(testData); 463 assertClose("premultiply",asDouble(m.preMultiply(asBigDecimal(testVector))),preMultTest,normTolerance); 464 m = new BigMatrixImpl(bigSingular); 465 try { 466 m.preMultiply(asBigDecimal(testVector)); 467 fail("expecting IllegalArgumentException"); 468 } catch (IllegalArgumentException ex) { 469 // ignored 470 } 471 } 472 473 public void testPremultiply() { 474 BigMatrix m3 = new BigMatrixImpl(d3); 475 BigMatrix m4 = new BigMatrixImpl(d4); 476 BigMatrix m5 = new BigMatrixImpl(d5); 477 assertClose("m3*m4=m5", m4.preMultiply(m3), m5, entryTolerance); 478 479 BigMatrixImpl m = new BigMatrixImpl(testData); 480 BigMatrixImpl mInv = new BigMatrixImpl(testDataInv); 481 BigMatrixImpl identity = new BigMatrixImpl(id); 482 new BigMatrixImpl(testData2); 483 assertClose("inverse multiply",m.preMultiply(mInv), 484 identity,entryTolerance); 485 assertClose("inverse multiply",mInv.preMultiply(m), 486 identity,entryTolerance); 487 assertClose("identity multiply",m.preMultiply(identity), 488 m,entryTolerance); 489 assertClose("identity multiply",identity.preMultiply(mInv), 490 mInv,entryTolerance); 491 try { 492 m.preMultiply(new BigMatrixImpl(bigSingular)); 493 fail("Expecting illegalArgumentException"); 494 } catch (IllegalArgumentException ex) { 495 // ignored 496 } 497 } 498 499 public void testGetVectors() { 500 BigMatrix m = new BigMatrixImpl(testData); 501 assertClose("get row",m.getRowAsDoubleArray(0),testDataRow1,entryTolerance); 502 assertClose("get col",m.getColumnAsDoubleArray(2),testDataCol3,entryTolerance); 503 try { 504 m.getRowAsDoubleArray(10); 505 fail("expecting MatrixIndexException"); 506 } catch (MatrixIndexException ex) { 507 // ignored 508 } 509 try { 510 m.getColumnAsDoubleArray(-1); 511 fail("expecting MatrixIndexException"); 512 } catch (MatrixIndexException ex) { 513 // ignored 514 } 515 } 516 517 public void testLUDecomposition() throws Exception { 518 BigMatrixImpl m = new BigMatrixImpl(testData); 519 BigMatrix lu = m.getLUMatrix(); 520 assertClose("LU decomposition", lu, new BigMatrixImpl(testDataLU), normTolerance); 521 verifyDecomposition(m, lu); 522 m = new BigMatrixImpl(luData); 523 lu = m.getLUMatrix(); 524 assertClose("LU decomposition", lu, new BigMatrixImpl(luDataLUDecomposition), normTolerance); 525 verifyDecomposition(m, lu); 526 m = new BigMatrixImpl(testDataMinus); 527 lu = m.getLUMatrix(); 528 verifyDecomposition(m, lu); 529 m = new BigMatrixImpl(id); 530 lu = m.getLUMatrix(); 531 verifyDecomposition(m, lu); 532 try { 533 m = new BigMatrixImpl(bigSingular); // singular 534 lu = m.getLUMatrix(); 535 fail("Expecting InvalidMatrixException"); 536 } catch (InvalidMatrixException ex) { 537 // expected 538 } 539 try { 540 m = new BigMatrixImpl(testData2); // not square 541 lu = m.getLUMatrix(); 542 fail("Expecting InvalidMatrixException"); 543 } catch (InvalidMatrixException ex) { 544 // expected 545 } 546 } 547 548 /** 549 * test submatrix accessors 550 */ 551 public void testSubMatrix() { 552 BigMatrix m = new BigMatrixImpl(subTestData); 553 BigMatrix mRows23Cols00 = new BigMatrixImpl(subRows23Cols00); 554 BigMatrix mRows00Cols33 = new BigMatrixImpl(subRows00Cols33); 555 BigMatrix mRows01Cols23 = new BigMatrixImpl(subRows01Cols23); 556 BigMatrix mRows02Cols13 = new BigMatrixImpl(subRows02Cols13); 557 BigMatrix mRows03Cols12 = new BigMatrixImpl(subRows03Cols12); 558 BigMatrix mRows03Cols123 = new BigMatrixImpl(subRows03Cols123); 559 BigMatrix mRows20Cols123 = new BigMatrixImpl(subRows20Cols123); 560 BigMatrix mRows31Cols31 = new BigMatrixImpl(subRows31Cols31); 561 assertEquals("Rows23Cols00", mRows23Cols00, 562 m.getSubMatrix(2 , 3 , 0, 0)); 563 assertEquals("Rows00Cols33", mRows00Cols33, 564 m.getSubMatrix(0 , 0 , 3, 3)); 565 assertEquals("Rows01Cols23", mRows01Cols23, 566 m.getSubMatrix(0 , 1 , 2, 3)); 567 assertEquals("Rows02Cols13", mRows02Cols13, 568 m.getSubMatrix(new int[] {0,2}, new int[] {1,3})); 569 assertEquals("Rows03Cols12", mRows03Cols12, 570 m.getSubMatrix(new int[] {0,3}, new int[] {1,2})); 571 assertEquals("Rows03Cols123", mRows03Cols123, 572 m.getSubMatrix(new int[] {0,3}, new int[] {1,2,3})); 573 assertEquals("Rows20Cols123", mRows20Cols123, 574 m.getSubMatrix(new int[] {2,0}, new int[] {1,2,3})); 575 assertEquals("Rows31Cols31", mRows31Cols31, 576 m.getSubMatrix(new int[] {3,1}, new int[] {3,1})); 577 assertEquals("Rows31Cols31", mRows31Cols31, 578 m.getSubMatrix(new int[] {3,1}, new int[] {3,1})); 579 580 try { 581 m.getSubMatrix(1,0,2,4); 582 fail("Expecting MatrixIndexException"); 583 } catch (MatrixIndexException ex) { 584 // expected 585 } 586 try { 587 m.getSubMatrix(-1,1,2,2); 588 fail("Expecting MatrixIndexException"); 589 } catch (MatrixIndexException ex) { 590 // expected 591 } 592 try { 593 m.getSubMatrix(1,0,2,2); 594 fail("Expecting MatrixIndexException"); 595 } catch (MatrixIndexException ex) { 596 // expected 597 } 598 try { 599 m.getSubMatrix(1,0,2,4); 600 fail("Expecting MatrixIndexException"); 601 } catch (MatrixIndexException ex) { 602 // expected 603 } 604 try { 605 m.getSubMatrix(new int[] {}, new int[] {0}); 606 fail("Expecting MatrixIndexException"); 607 } catch (MatrixIndexException ex) { 608 // expected 609 } 610 try { 611 m.getSubMatrix(new int[] {0}, new int[] {4}); 612 fail("Expecting MatrixIndexException"); 613 } catch (MatrixIndexException ex) { 614 // expected 615 } 616 } 617 618 public void testGetColumnMatrix() { 619 BigMatrix m = new BigMatrixImpl(subTestData); 620 BigMatrix mColumn1 = new BigMatrixImpl(subColumn1); 621 BigMatrix mColumn3 = new BigMatrixImpl(subColumn3); 622 assertEquals("Column1", mColumn1, 623 m.getColumnMatrix(1)); 624 assertEquals("Column3", mColumn3, 625 m.getColumnMatrix(3)); 626 try { 627 m.getColumnMatrix(-1); 628 fail("Expecting MatrixIndexException"); 629 } catch (MatrixIndexException ex) { 630 // expected 631 } 632 try { 633 m.getColumnMatrix(4); 634 fail("Expecting MatrixIndexException"); 635 } catch (MatrixIndexException ex) { 636 // expected 637 } 638 } 639 640 public void testGetRowMatrix() { 641 BigMatrix m = new BigMatrixImpl(subTestData); 642 BigMatrix mRow0 = new BigMatrixImpl(subRow0); 643 BigMatrix mRow3 = new BigMatrixImpl(subRow3); 644 assertEquals("Row0", mRow0, 645 m.getRowMatrix(0)); 646 assertEquals("Row3", mRow3, 647 m.getRowMatrix(3)); 648 try { 649 m.getRowMatrix(-1); 650 fail("Expecting MatrixIndexException"); 651 } catch (MatrixIndexException ex) { 652 // expected 653 } 654 try { 655 m.getRowMatrix(4); 656 fail("Expecting MatrixIndexException"); 657 } catch (MatrixIndexException ex) { 658 // expected 659 } 660 } 661 662 public void testEqualsAndHashCode() { 663 BigMatrixImpl m = new BigMatrixImpl(testData); 664 BigMatrixImpl m1 = (BigMatrixImpl) m.copy(); 665 BigMatrixImpl mt = (BigMatrixImpl) m.transpose(); 666 assertTrue(m.hashCode() != mt.hashCode()); 667 assertEquals(m.hashCode(), m1.hashCode()); 668 assertEquals(m, m); 669 assertEquals(m, m1); 670 assertFalse(m.equals(null)); 671 assertFalse(m.equals(mt)); 672 assertFalse(m.equals(new BigMatrixImpl(bigSingular))); 673 // Different scales make BigDecimals, so matrices unequal 674 m = new BigMatrixImpl(new String[][] {{"2.0"}}); 675 m1 = new BigMatrixImpl(new String[][] {{"2.00"}}); 676 assertTrue(m.hashCode() != m1.hashCode()); 677 assertFalse(m.equals(m1)); 678 } 679 680 public void testToString() { 681 BigMatrixImpl m = new BigMatrixImpl(testData); 682 assertEquals("BigMatrixImpl{{1,2,3},{2,5,3},{1,0,8}}", 683 m.toString()); 684 m = new BigMatrixImpl(); 685 assertEquals("BigMatrixImpl{}", 686 m.toString()); 687 } 688 689 public void testSetSubMatrix() throws Exception { 690 BigDecimal[][] detData3 = 691 MatrixUtils.createBigMatrix(detData2).getData(); 692 BigMatrixImpl m = new BigMatrixImpl(testData); 693 m.setSubMatrix(detData3,1,1); 694 BigMatrix expected = MatrixUtils.createBigMatrix 695 (new double[][] {{1.0,2.0,3.0},{2.0,1.0,3.0},{1.0,2.0,4.0}}); 696 assertEquals(expected, m); 697 698 m.setSubMatrix(detData3,0,0); 699 expected = MatrixUtils.createBigMatrix 700 (new double[][] {{1.0,3.0,3.0},{2.0,4.0,3.0},{1.0,2.0,4.0}}); 701 assertEquals(expected, m); 702 703 BigDecimal[][] testDataPlus3 = 704 MatrixUtils.createBigMatrix(testDataPlus2).getData(); 705 m.setSubMatrix(testDataPlus3,0,0); 706 expected = MatrixUtils.createBigMatrix 707 (new double[][] {{3.0,4.0,5.0},{4.0,7.0,5.0},{3.0,2.0,10.0}}); 708 assertEquals(expected, m); 709 710 // javadoc example 711 BigMatrixImpl matrix = (BigMatrixImpl) MatrixUtils.createBigMatrix 712 (new double[][] {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 0, 1 , 2}}); 713 matrix.setSubMatrix(new BigDecimal[][] {{new BigDecimal(3), 714 new BigDecimal(4)}, {new BigDecimal(5), new BigDecimal(6)}}, 1, 1); 715 expected = MatrixUtils.createBigMatrix 716 (new BigDecimal[][] {{new BigDecimal(1), new BigDecimal(2), 717 new BigDecimal(3), new BigDecimal(4)}, {new BigDecimal(5), 718 new BigDecimal(3), new BigDecimal(4), new BigDecimal(8)}, 719 {new BigDecimal(9), new BigDecimal(5) , new BigDecimal(6), 720 new BigDecimal(2)}}); 721 assertEquals(expected, matrix); 722 723 // dimension overflow 724 try { 725 m.setSubMatrix(matrix.getData(),1,1); 726 fail("expecting MatrixIndexException"); 727 } catch (MatrixIndexException e) { 728 // expected 729 } 730 731 // null 732 try { 733 m.setSubMatrix(null,1,1); 734 fail("expecting NullPointerException"); 735 } catch (NullPointerException e) { 736 // expected 737 } 738 739 // ragged 740 try { 741 m.setSubMatrix(new BigDecimal[][] {{new BigDecimal(1)}, 742 {new BigDecimal(2), new BigDecimal(3)}}, 0, 0); 743 fail("expecting IllegalArgumentException"); 744 } catch (IllegalArgumentException e) { 745 // expected 746 } 747 748 // empty 749 try { 750 m.setSubMatrix(new BigDecimal[][] {{}}, 0, 0); 751 fail("expecting IllegalArgumentException"); 752 } catch (IllegalArgumentException e) { 753 // expected 754 } 755 756 } 757 758 //--------------- -----------------Protected methods 759 760 /** verifies that two matrices are close (1-norm) */ 761 protected void assertClose(String msg, BigMatrix m, BigMatrix n, 762 double tolerance) { 763 assertTrue(msg,m.subtract(n).getNorm().doubleValue() < tolerance); 764 } 765 766 /** verifies that two vectors are close (sup norm) */ 767 protected void assertClose(String msg, double[] m, double[] n, 768 double tolerance) { 769 if (m.length != n.length) { 770 fail("vectors not same length"); 771 } 772 for (int i = 0; i < m.length; i++) { 773 assertEquals(msg + " " + i + " elements differ", 774 m[i],n[i],tolerance); 775 } 776 } 777 778 /** extracts the l and u matrices from compact lu representation */ 779 protected void splitLU(BigMatrix lu, BigDecimal[][] lowerData, BigDecimal[][] upperData) throws InvalidMatrixException { 780 if (!lu.isSquare() || lowerData.length != lowerData[0].length || upperData.length != upperData[0].length || 781 lowerData.length != upperData.length 782 || lowerData.length != lu.getRowDimension()) { 783 throw new InvalidMatrixException("incorrect dimensions"); 784 } 785 int n = lu.getRowDimension(); 786 for (int i = 0; i < n; i++) { 787 for (int j = 0; j < n; j++) { 788 if (j < i) { 789 lowerData[i][j] = lu.getEntry(i, j); 790 upperData[i][j] = new BigDecimal(0); 791 } else if (i == j) { 792 lowerData[i][j] = new BigDecimal(1); 793 upperData[i][j] = lu.getEntry(i, j); 794 } else { 795 lowerData[i][j] = new BigDecimal(0); 796 upperData[i][j] = lu.getEntry(i, j); 797 } 798 } 799 } 800 } 801 802 /** Returns the result of applying the given row permutation to the matrix */ 803 protected BigMatrix permuteRows(BigMatrix matrix, int[] permutation) { 804 if (!matrix.isSquare() || matrix.getRowDimension() != permutation.length) { 805 throw new IllegalArgumentException("dimension mismatch"); 806 } 807 int n = matrix.getRowDimension(); 808 int m = matrix.getColumnDimension(); 809 BigDecimal out[][] = new BigDecimal[m][n]; 810 for (int i = 0; i < n; i++) { 811 for (int j = 0; j < m; j++) { 812 out[i][j] = matrix.getEntry(permutation[i], j); 813 } 814 } 815 return new BigMatrixImpl(out); 816 } 817 818 /** Extracts l and u matrices from lu and verifies that matrix = l times u modulo permutation */ 819 protected void verifyDecomposition(BigMatrix matrix, BigMatrix lu) throws Exception{ 820 int n = matrix.getRowDimension(); 821 BigDecimal[][] lowerData = new BigDecimal[n][n]; 822 BigDecimal[][] upperData = new BigDecimal[n][n]; 823 splitLU(lu, lowerData, upperData); 824 BigMatrix lower =new BigMatrixImpl(lowerData); 825 BigMatrix upper = new BigMatrixImpl(upperData); 826 int[] permutation = ((BigMatrixImpl) matrix).getPermutation(); 827 BigMatrix permuted = permuteRows(matrix, permutation); 828 assertClose("lu decomposition does not work", permuted, 829 lower.multiply(upper), normTolerance); 830 } 831 832 // /** Useful for debugging */ 833 // private void dumpMatrix(BigMatrix m) { 834 // for (int i = 0; i < m.getRowDimension(); i++) { 835 // String os = ""; 836 // for (int j = 0; j < m.getColumnDimension(); j++) { 837 // os += m.getEntry(i, j) + " "; 838 // } 839 // System.out.println(os); 840 // } 841 // } 842 843 } 844