| 1 16 17 package org.apache.commons.math.linear; 18 import java.io.Serializable ; 19 import java.math.BigDecimal ; 20 21 48 public class BigMatrixImpl implements BigMatrix, Serializable { 49 50 51 static final long serialVersionUID = -1011428905656140431L; 52 53 54 private BigDecimal data[][] = null; 55 56 59 private BigDecimal lu[][] = null; 60 61 62 private int[] permutation = null; 63 64 65 private int parity = 1; 66 67 68 private int roundingMode = BigDecimal.ROUND_HALF_UP; 69 70 71 private int scale = 64; 72 73 74 protected static BigDecimal TOO_SMALL = new BigDecimal (10E-12); 75 76 77 static final BigDecimal ZERO = new BigDecimal (0); 78 79 static final BigDecimal ONE = new BigDecimal (1); 80 81 84 public BigMatrixImpl() { 85 } 86 87 95 public BigMatrixImpl(int rowDimension, int columnDimension) { 96 if (rowDimension <=0 || columnDimension <=0) { 97 throw new IllegalArgumentException  98 ("row and column dimensions must be positive"); 99 } 100 data = new BigDecimal [rowDimension][columnDimension]; 101 lu = null; 102 } 103 104 115 public BigMatrixImpl(BigDecimal [][] d) { 116 this.copyIn(d); 117 lu = null; 118 } 119 120 131 public BigMatrixImpl(double[][] d) { 132 int nRows = d.length; 133 if (nRows == 0) { 134 throw new IllegalArgumentException ( 135 "Matrix must have at least one row."); 136 } 137 int nCols = d[0].length; 138 if (nCols == 0) { 139 throw new IllegalArgumentException ( 140 "Matrix must have at least one column."); 141 } 142 for (int row = 1; row < nRows; row++) { 143 if (d[row].length != nCols) { 144 throw new IllegalArgumentException ( 145 "All input rows must have the same length."); 146 } 147 } 148 this.copyIn(d); 149 lu = null; 150 } 151 152 161 public BigMatrixImpl(String [][] d) { 162 int nRows = d.length; 163 if (nRows == 0) { 164 throw new IllegalArgumentException ( 165 "Matrix must have at least one row."); 166 } 167 int nCols = d[0].length; 168 if (nCols == 0) { 169 throw new IllegalArgumentException ( 170 "Matrix must have at least one column."); 171 } 172 for (int row = 1; row < nRows; row++) { 173 if (d[row].length != nCols) { 174 throw new IllegalArgumentException ( 175 "All input rows must have the same length."); 176 } 177 } 178 this.copyIn(d); 179 lu = null; 180 } 181 182 191 public BigMatrixImpl(BigDecimal [] v) { 192 int nRows = v.length; 193 data = new BigDecimal [nRows][1]; 194 for (int row = 0; row < nRows; row++) { 195 data[row][0] = v[row]; 196 } 197 } 198 199 204 public BigMatrix copy() { 205 return new BigMatrixImpl(this.copyOut()); 206 } 207 208 215 public BigMatrix add(BigMatrix m) throws IllegalArgumentException { 216 if (this.getColumnDimension() != m.getColumnDimension() || 217 this.getRowDimension() != m.getRowDimension()) { 218 throw new IllegalArgumentException ("matrix dimension mismatch"); 219 } 220 int rowCount = this.getRowDimension(); 221 int columnCount = this.getColumnDimension(); 222 BigDecimal [][] outData = new BigDecimal [rowCount][columnCount]; 223 for (int row = 0; row < rowCount; row++) { 224 for (int col = 0; col < columnCount; col++) { 225 outData[row][col] = data[row][col].add(m.getEntry(row, col)); 226 } 227 } 228 return new BigMatrixImpl(outData); 229 } 230 231 238 public BigMatrix subtract(BigMatrix m) throws IllegalArgumentException { 239 if (this.getColumnDimension() != m.getColumnDimension() || 240 this.getRowDimension() != m.getRowDimension()) { 241 throw new IllegalArgumentException ("matrix dimension mismatch"); 242 } 243 int rowCount = this.getRowDimension(); 244 int columnCount = this.getColumnDimension(); 245 BigDecimal [][] outData = new BigDecimal [rowCount][columnCount]; 246 for (int row = 0; row < rowCount; row++) { 247 for (int col = 0; col < columnCount; col++) { 248 outData[row][col] = data[row][col].subtract(m.getEntry(row, col)); 249 } 250 } 251 return new BigMatrixImpl(outData); 252 } 253 254 260 public BigMatrix scalarAdd(BigDecimal d) { 261 int rowCount = this.getRowDimension(); 262 int columnCount = this.getColumnDimension(); 263 BigDecimal [][] outData = new BigDecimal [rowCount][columnCount]; 264 for (int row = 0; row < rowCount; row++) { 265 for (int col = 0; col < columnCount; col++) { 266 outData[row][col] = data[row][col].add(d); 267 } 268 } 269 return new BigMatrixImpl(outData); 270 } 271 272 277 public BigMatrix scalarMultiply(BigDecimal d) { 278 int rowCount = this.getRowDimension(); 279 int columnCount = this.getColumnDimension(); 280 BigDecimal [][] outData = new BigDecimal [rowCount][columnCount]; 281 for (int row = 0; row < rowCount; row++) { 282 for (int col = 0; col < columnCount; col++) { 283 outData[row][col] = data[row][col].multiply(d); 284 } 285 } 286 return new BigMatrixImpl(outData); 287 } 288 289 296 public BigMatrix multiply(BigMatrix m) throws IllegalArgumentException { 297 if (this.getColumnDimension() != m.getRowDimension()) { 298 throw new IllegalArgumentException ("Matrices are not multiplication compatible."); 299 } 300 int nRows = this.getRowDimension(); 301 int nCols = m.getColumnDimension(); 302 int nSum = this.getColumnDimension(); 303 BigDecimal [][] outData = new BigDecimal [nRows][nCols]; 304 BigDecimal sum = ZERO; 305 for (int row = 0; row < nRows; row++) { 306 for (int col = 0; col < nCols; col++) { 307 sum = ZERO; 308 for (int i = 0; i < nSum; i++) { 309 sum = sum.add(data[row][i].multiply(m.getEntry(i, col))); 310 } 311 outData[row][col] = sum; 312 } 313 } 314 return new BigMatrixImpl(outData); 315 } 316 317 324 public BigMatrix preMultiply(BigMatrix m) throws IllegalArgumentException { 325 return m.multiply(this); 326 } 327 328 335 public BigDecimal [][] getData() { 336 return copyOut(); 337 } 338 339 347 public double[][] getDataAsDoubleArray() { 348 int nRows = getRowDimension(); 349 int nCols = getColumnDimension(); 350 double d[][] = new double[nRows][nCols]; 351 for (int i = 0; i < nRows; i++) { 352 for (int j=0; j<nCols;j++) { 353 d[i][j] = data[i][j].doubleValue(); 354 } 355 } 356 return d; 357 } 358 359 366 public BigDecimal [][] getDataRef() { 367 return data; 368 } 369 370 376 public int getRoundingMode() { 377 return roundingMode; 378 } 379 380 385 public void setRoundingMode(int roundingMode) { 386 this.roundingMode = roundingMode; 387 } 388 389 395 public int getScale() { 396 return scale; 397 } 398 399 404 public void setScale(int scale) { 405 this.scale = scale; 406 } 407 408 414 public BigDecimal getNorm() { 415 BigDecimal maxColSum = ZERO; 416 for (int col = 0; col < this.getColumnDimension(); col++) { 417 BigDecimal sum = ZERO; 418 for (int row = 0; row < this.getRowDimension(); row++) { 419 sum = sum.add(data[row][col].abs()); 420 } 421 maxColSum = maxColSum.max(sum); 422 } 423 return maxColSum; 424 } 425 426 438 public BigMatrix getSubMatrix(int startRow, int endRow, int startColumn, 439 int endColumn) throws MatrixIndexException { 440 if (startRow < 0 || startRow > endRow || endRow > data.length || 441 startColumn < 0 || startColumn > endColumn || 442 endColumn > data[0].length ) { 443 throw new MatrixIndexException( 444 "invalid row or column index selection"); 445 } 446 BigMatrixImpl subMatrix = new BigMatrixImpl(endRow - startRow+1, 447 endColumn - startColumn+1); 448 BigDecimal [][] subMatrixData = subMatrix.getDataRef(); 449 for (int i = startRow; i <= endRow; i++) { 450 for (int j = startColumn; j <= endColumn; j++) { 451 subMatrixData[i - startRow][j - startColumn] = data[i][j]; 452 } 453 } 454 return subMatrix; 455 } 456 457 468 public BigMatrix getSubMatrix(int[] selectedRows, int[] selectedColumns) 469 throws MatrixIndexException { 470 if (selectedRows.length * selectedColumns.length == 0) { 471 throw new MatrixIndexException( 472 "selected row and column index arrays must be non-empty"); 473 } 474 BigMatrixImpl subMatrix = new BigMatrixImpl(selectedRows.length, 475 selectedColumns.length); 476 BigDecimal [][] subMatrixData = subMatrix.getDataRef(); 477 try { 478 for (int i = 0; i < selectedRows.length; i++) { 479 for (int j = 0; j < selectedColumns.length; j++) { 480 subMatrixData[i][j] = data[selectedRows[i]][selectedColumns[j]]; 481 } 482 } 483 } 484 catch (ArrayIndexOutOfBoundsException e) { 485 throw new MatrixIndexException("matrix dimension mismatch"); 486 } 487 return subMatrix; 488 } 489 490 517 public void setSubMatrix(BigDecimal [][] subMatrix, int row, int column) 518 throws MatrixIndexException { 519 if ((row < 0) || (column < 0)){ 520 throw new MatrixIndexException 521 ("invalid row or column index selection"); 522 } 523 int nRows = subMatrix.length; 524 if (nRows == 0) { 525 throw new IllegalArgumentException ( 526 "Matrix must have at least one row."); 527 } 528 int nCols = subMatrix[0].length; 529 if (nCols == 0) { 530 throw new IllegalArgumentException ( 531 "Matrix must have at least one column."); 532 } 533 for (int r = 1; r < nRows; r++) { 534 if (subMatrix[r].length != nCols) { 535 throw new IllegalArgumentException ( 536 "All input rows must have the same length."); 537 } 538 } 539 if (data == null) { 540 if ((row > 0)||(column > 0)) throw new MatrixIndexException 541 ("matrix must be initialized to perfom this method"); 542 data = new BigDecimal [nRows][nCols]; 543 System.arraycopy(subMatrix, 0, data, 0, subMatrix.length); 544 } 545 if (((nRows + row) > this.getRowDimension()) || 546 (nCols + column > this.getColumnDimension())) 547 throw new MatrixIndexException( 548 "invalid row or column index selection"); 549 for (int i = 0; i < nRows; i++) { 550 System.arraycopy(subMatrix[i], 0, data[row + i], column, nCols); 551 } 552 lu = null; 553 } 554 555 563 public BigMatrix getRowMatrix(int row) throws MatrixIndexException { 564 if ( !isValidCoordinate( row, 0)) { 565 throw new MatrixIndexException("illegal row argument"); 566 } 567 int ncols = this.getColumnDimension(); 568 BigDecimal [][] out = new BigDecimal [1][ncols]; 569 System.arraycopy(data[row], 0, out[0], 0, ncols); 570 return new BigMatrixImpl(out); 571 } 572 573 581 public BigMatrix getColumnMatrix(int column) throws MatrixIndexException { 582 if ( !isValidCoordinate( 0, column)) { 583 throw new MatrixIndexException("illegal column argument"); 584 } 585 int nRows = this.getRowDimension(); 586 BigDecimal [][] out = new BigDecimal [nRows][1]; 587 for (int row = 0; row < nRows; row++) { 588 out[row][0] = data[row][column]; 589 } 590 return new BigMatrixImpl(out); 591 } 592 593 603 public BigDecimal [] getRow(int row) throws MatrixIndexException { 604 if ( !isValidCoordinate( row, 0 ) ) { 605 throw new MatrixIndexException("illegal row argument"); 606 } 607 int ncols = this.getColumnDimension(); 608 BigDecimal [] out = new BigDecimal [ncols]; 609 System.arraycopy(data[row], 0, out, 0, ncols); 610 return out; 611 } 612 613 624 public double[] getRowAsDoubleArray(int row) throws MatrixIndexException { 625 if ( !isValidCoordinate( row, 0 ) ) { 626 throw new MatrixIndexException("illegal row argument"); 627 } 628 int ncols = this.getColumnDimension(); 629 double[] out = new double[ncols]; 630 for (int i=0;i<ncols;i++) { 631 out[i] = data[row][i].doubleValue(); 632 } 633 return out; 634 } 635 636 646 public BigDecimal [] getColumn(int col) throws MatrixIndexException { 647 if ( !isValidCoordinate(0, col) ) { 648 throw new MatrixIndexException("illegal column argument"); 649 } 650 int nRows = this.getRowDimension(); 651 BigDecimal [] out = new BigDecimal [nRows]; 652 for (int i = 0; i < nRows; i++) { 653 out[i] = data[i][col]; 654 } 655 return out; 656 } 657 658 669 public double[] getColumnAsDoubleArray(int col) throws MatrixIndexException { 670 if ( !isValidCoordinate( 0, col ) ) { 671 throw new MatrixIndexException("illegal column argument"); 672 } 673 int nrows = this.getRowDimension(); 674 double[] out = new double[nrows]; 675 for (int i=0;i<nrows;i++) { 676 out[i] = data[i][col].doubleValue(); 677 } 678 return out; 679 } 680 681 696 public BigDecimal getEntry(int row, int column) 697 throws MatrixIndexException { 698 if (!isValidCoordinate(row,column)) { 699 throw new MatrixIndexException("matrix entry does not exist"); 700 } 701 return data[row][column]; 702 } 703 704 720 public double getEntryAsDouble(int row, int column) throws MatrixIndexException { 721 return getEntry(row,column).doubleValue(); 722 } 723 724 729 public BigMatrix transpose() { 730 int nRows = this.getRowDimension(); 731 int nCols = this.getColumnDimension(); 732 BigMatrixImpl out = new BigMatrixImpl(nCols, nRows); 733 BigDecimal [][] outData = out.getDataRef(); 734 for (int row = 0; row < nRows; row++) { 735 for (int col = 0; col < nCols; col++) { 736 outData[col][row] = data[row][col]; 737 } 738 } 739 return out; 740 } 741 742 748 public BigMatrix inverse() throws InvalidMatrixException { 749 return solve(MatrixUtils.createBigIdentityMatrix 750 (this.getRowDimension())); 751 } 752 753 759 public BigDecimal getDeterminant() throws InvalidMatrixException { 760 if (!isSquare()) { 761 throw new InvalidMatrixException("matrix is not square"); 762 } 763 if (isSingular()) { return ZERO; 765 } else { 766 BigDecimal det = (parity == 1) ? ONE : ONE.negate(); 767 for (int i = 0; i < this.getRowDimension(); i++) { 768 det = det.multiply(lu[i][i]); 769 } 770 return det; 771 } 772 } 773 774 778 public boolean isSquare() { 779 return (this.getColumnDimension() == this.getRowDimension()); 780 } 781 782 786 public boolean isSingular() { 787 if (lu == null) { 788 try { 789 luDecompose(); 790 return false; 791 } catch (InvalidMatrixException ex) { 792 return true; 793 } 794 } else { return false; } 797 } 798 799 804 public int getRowDimension() { 805 return data.length; 806 } 807 808 813 public int getColumnDimension() { 814 return data[0].length; 815 } 816 817 825 public BigDecimal getTrace() throws IllegalArgumentException { 826 if (!isSquare()) { 827 throw new IllegalArgumentException ("matrix is not square"); 828 } 829 BigDecimal  |