1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.commons.math.linear; 19 20 import org.apache.commons.math.MathRuntimeException; 21 import org.apache.commons.math.linear.MatrixVisitorException; 22 import org.apache.commons.math.exception.util.LocalizedFormats; 23 import org.apache.commons.math.util.MathUtils; 24 import org.apache.commons.math.util.FastMath; 25 26 /** 27 * Basic implementation of RealMatrix methods regardless of the underlying storage. 28 * <p>All the methods implemented here use {@link #getEntry(int, int)} to access 29 * matrix elements. Derived class can provide faster implementations. </p> 30 * 31 * @version $Revision: 1073158 $ $Date: 2011-02-21 22:46:52 +0100 (lun. 21 fvr. 2011) $ 32 * @since 2.0 33 */ 34 public abstract class AbstractRealMatrix implements RealMatrix { 35 36 37 /** Cached LU solver. 38 * @deprecated as of release 2.0, since all methods using this are deprecated 39 */ 40 @Deprecated 41 private DecompositionSolver lu; 42 43 /** 44 * Creates a matrix with no data 45 */ 46 protected AbstractRealMatrix() { 47 lu = null; 48 } 49 50 /** 51 * Create a new RealMatrix with the supplied row and column dimensions. 52 * 53 * @param rowDimension the number of rows in the new matrix 54 * @param columnDimension the number of columns in the new matrix 55 * @throws IllegalArgumentException if row or column dimension is not positive 56 */ 57 protected AbstractRealMatrix(final int rowDimension, final int columnDimension) 58 throws IllegalArgumentException { 59 if (rowDimension < 1 ) { 60 throw MathRuntimeException.createIllegalArgumentException( 61 LocalizedFormats.INSUFFICIENT_DIMENSION, rowDimension, 1); 62 } 63 if (columnDimension <= 0) { 64 throw MathRuntimeException.createIllegalArgumentException( 65 LocalizedFormats.INSUFFICIENT_DIMENSION, columnDimension, 1); 66 } 67 lu = null; 68 } 69 70 /** {@inheritDoc} */ 71 public abstract RealMatrix createMatrix(final int rowDimension, final int columnDimension) 72 throws IllegalArgumentException; 73 74 /** {@inheritDoc} */ 75 public abstract RealMatrix copy(); 76 77 /** {@inheritDoc} */ 78 public RealMatrix add(RealMatrix m) throws IllegalArgumentException { 79 80 // safety check 81 MatrixUtils.checkAdditionCompatible(this, m); 82 83 final int rowCount = getRowDimension(); 84 final int columnCount = getColumnDimension(); 85 final RealMatrix out = createMatrix(rowCount, columnCount); 86 for (int row = 0; row < rowCount; ++row) { 87 for (int col = 0; col < columnCount; ++col) { 88 out.setEntry(row, col, getEntry(row, col) + m.getEntry(row, col)); 89 } 90 } 91 92 return out; 93 94 } 95 96 /** {@inheritDoc} */ 97 public RealMatrix subtract(final RealMatrix m) throws IllegalArgumentException { 98 99 // safety check 100 MatrixUtils.checkSubtractionCompatible(this, m); 101 102 final int rowCount = getRowDimension(); 103 final int columnCount = getColumnDimension(); 104 final RealMatrix out = createMatrix(rowCount, columnCount); 105 for (int row = 0; row < rowCount; ++row) { 106 for (int col = 0; col < columnCount; ++col) { 107 out.setEntry(row, col, getEntry(row, col) - m.getEntry(row, col)); 108 } 109 } 110 111 return out; 112 113 } 114 115 /** {@inheritDoc} */ 116 public RealMatrix scalarAdd(final double d) { 117 118 final int rowCount = getRowDimension(); 119 final int columnCount = getColumnDimension(); 120 final RealMatrix out = createMatrix(rowCount, columnCount); 121 for (int row = 0; row < rowCount; ++row) { 122 for (int col = 0; col < columnCount; ++col) { 123 out.setEntry(row, col, getEntry(row, col) + d); 124 } 125 } 126 127 return out; 128 129 } 130 131 /** {@inheritDoc} */ 132 public RealMatrix scalarMultiply(final double d) { 133 134 final int rowCount = getRowDimension(); 135 final int columnCount = getColumnDimension(); 136 final RealMatrix out = createMatrix(rowCount, columnCount); 137 for (int row = 0; row < rowCount; ++row) { 138 for (int col = 0; col < columnCount; ++col) { 139 out.setEntry(row, col, getEntry(row, col) * d); 140 } 141 } 142 143 return out; 144 145 } 146 147 /** {@inheritDoc} */ 148 public RealMatrix multiply(final RealMatrix m) 149 throws IllegalArgumentException { 150 151 // safety check 152 MatrixUtils.checkMultiplicationCompatible(this, m); 153 154 final int nRows = getRowDimension(); 155 final int nCols = m.getColumnDimension(); 156 final int nSum = getColumnDimension(); 157 final RealMatrix out = createMatrix(nRows, nCols); 158 for (int row = 0; row < nRows; ++row) { 159 for (int col = 0; col < nCols; ++col) { 160 double sum = 0; 161 for (int i = 0; i < nSum; ++i) { 162 sum += getEntry(row, i) * m.getEntry(i, col); 163 } 164 out.setEntry(row, col, sum); 165 } 166 } 167 168 return out; 169 170 } 171 172 /** {@inheritDoc} */ 173 public RealMatrix preMultiply(final RealMatrix m) 174 throws IllegalArgumentException { 175 return m.multiply(this); 176 } 177 178 /** {@inheritDoc} */ 179 public double[][] getData() { 180 181 final double[][] data = new double[getRowDimension()][getColumnDimension()]; 182 183 for (int i = 0; i < data.length; ++i) { 184 final double[] dataI = data[i]; 185 for (int j = 0; j < dataI.length; ++j) { 186 dataI[j] = getEntry(i, j); 187 } 188 } 189 190 return data; 191 192 } 193 194 /** {@inheritDoc} */ 195 public double getNorm() { 196 return walkInColumnOrder(new RealMatrixPreservingVisitor() { 197 198 /** Last row index. */ 199 private double endRow; 200 201 /** Sum of absolute values on one column. */ 202 private double columnSum; 203 204 /** Maximal sum across all columns. */ 205 private double maxColSum; 206 207 /** {@inheritDoc} */ 208 public void start(final int rows, final int columns, 209 final int startRow, final int endRow, 210 final int startColumn, final int endColumn) { 211 this.endRow = endRow; 212 columnSum = 0; 213 maxColSum = 0; 214 } 215 216 /** {@inheritDoc} */ 217 public void visit(final int row, final int column, final double value) { 218 columnSum += FastMath.abs(value); 219 if (row == endRow) { 220 maxColSum = FastMath.max(maxColSum, columnSum); 221 columnSum = 0; 222 } 223 } 224 225 /** {@inheritDoc} */ 226 public double end() { 227 return maxColSum; 228 } 229 230 }); 231 } 232 233 /** {@inheritDoc} */ 234 public double getFrobeniusNorm() { 235 return walkInOptimizedOrder(new RealMatrixPreservingVisitor() { 236 237 /** Sum of squared entries. */ 238 private double sum; 239 240 /** {@inheritDoc} */ 241 public void start(final int rows, final int columns, 242 final int startRow, final int endRow, 243 final int startColumn, final int endColumn) { 244 sum = 0; 245 } 246 247 /** {@inheritDoc} */ 248 public void visit(final int row, final int column, final double value) { 249 sum += value * value; 250 } 251 252 /** {@inheritDoc} */ 253 public double end() { 254 return FastMath.sqrt(sum); 255 } 256 257 }); 258 } 259 260 /** {@inheritDoc} */ 261 public RealMatrix getSubMatrix(final int startRow, final int endRow, 262 final int startColumn, final int endColumn) 263 throws MatrixIndexException { 264 265 MatrixUtils.checkSubMatrixIndex(this, startRow, endRow, startColumn, endColumn); 266 267 final RealMatrix subMatrix = 268 createMatrix(endRow - startRow + 1, endColumn - startColumn + 1); 269 for (int i = startRow; i <= endRow; ++i) { 270 for (int j = startColumn; j <= endColumn; ++j) { 271 subMatrix.setEntry(i - startRow, j - startColumn, getEntry(i, j)); 272 } 273 } 274 275 return subMatrix; 276 277 } 278 279 /** {@inheritDoc} */ 280 public RealMatrix getSubMatrix(final int[] selectedRows, final int[] selectedColumns) 281 throws MatrixIndexException { 282 283 // safety checks 284 MatrixUtils.checkSubMatrixIndex(this, selectedRows, selectedColumns); 285 286 // copy entries 287 final RealMatrix subMatrix = 288 createMatrix(selectedRows.length, selectedColumns.length); 289 subMatrix.walkInOptimizedOrder(new DefaultRealMatrixChangingVisitor() { 290 291 /** {@inheritDoc} */ 292 @Override 293 public double visit(final int row, final int column, final double value) { 294 return getEntry(selectedRows[row], selectedColumns[column]); 295 } 296 297 }); 298 299 return subMatrix; 300 301 } 302 303 /** {@inheritDoc} */ 304 public void copySubMatrix(final int startRow, final int endRow, 305 final int startColumn, final int endColumn, 306 final double[][] destination) 307 throws MatrixIndexException, IllegalArgumentException { 308 309 // safety checks 310 MatrixUtils.checkSubMatrixIndex(this, startRow, endRow, startColumn, endColumn); 311 final int rowsCount = endRow + 1 - startRow; 312 final int columnsCount = endColumn + 1 - startColumn; 313 if ((destination.length < rowsCount) || (destination[0].length < columnsCount)) { 314 throw MathRuntimeException.createIllegalArgumentException( 315 LocalizedFormats.DIMENSIONS_MISMATCH_2x2, 316 destination.length, destination[0].length, 317 rowsCount, columnsCount); 318 } 319 320 // copy entries 321 walkInOptimizedOrder(new DefaultRealMatrixPreservingVisitor() { 322 323 /** Initial row index. */ 324 private int startRow; 325 326 /** Initial column index. */ 327 private int startColumn; 328 329 /** {@inheritDoc} */ 330 @Override 331 public void start(final int rows, final int columns, 332 final int startRow, final int endRow, 333 final int startColumn, final int endColumn) { 334 this.startRow = startRow; 335 this.startColumn = startColumn; 336 } 337 338 /** {@inheritDoc} */ 339 @Override 340 public void visit(final int row, final int column, final double value) { 341 destination[row - startRow][column - startColumn] = value; 342 } 343 344 }, startRow, endRow, startColumn, endColumn); 345 346 } 347 348 /** {@inheritDoc} */ 349 public void copySubMatrix(int[] selectedRows, int[] selectedColumns, double[][] destination) 350 throws MatrixIndexException, IllegalArgumentException { 351 352 // safety checks 353 MatrixUtils.checkSubMatrixIndex(this, selectedRows, selectedColumns); 354 if ((destination.length < selectedRows.length) || 355 (destination[0].length < selectedColumns.length)) { 356 throw MathRuntimeException.createIllegalArgumentException( 357 LocalizedFormats.DIMENSIONS_MISMATCH_2x2, 358 destination.length, destination[0].length, 359 selectedRows.length, selectedColumns.length); 360 } 361 362 // copy entries 363 for (int i = 0; i < selectedRows.length; i++) { 364 final double[] destinationI = destination[i]; 365 for (int j = 0; j < selectedColumns.length; j++) { 366 destinationI[j] = getEntry(selectedRows[i], selectedColumns[j]); 367 } 368 } 369 370 } 371 372 /** {@inheritDoc} */ 373 public void setSubMatrix(final double[][] subMatrix, final int row, final int column) 374 throws MatrixIndexException { 375 376 final int nRows = subMatrix.length; 377 if (nRows == 0) { 378 throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_ROW); 379 } 380 381 final int nCols = subMatrix[0].length; 382 if (nCols == 0) { 383 throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_COLUMN); 384 } 385 386 for (int r = 1; r < nRows; ++r) { 387 if (subMatrix[r].length != nCols) { 388 throw MathRuntimeException.createIllegalArgumentException( 389 LocalizedFormats.DIFFERENT_ROWS_LENGTHS, 390 nCols, subMatrix[r].length); 391 } 392 } 393 394 MatrixUtils.checkRowIndex(this, row); 395 MatrixUtils.checkColumnIndex(this, column); 396 MatrixUtils.checkRowIndex(this, nRows + row - 1); 397 MatrixUtils.checkColumnIndex(this, nCols + column - 1); 398 399 for (int i = 0; i < nRows; ++i) { 400 for (int j = 0; j < nCols; ++j) { 401 setEntry(row + i, column + j, subMatrix[i][j]); 402 } 403 } 404 405 lu = null; 406 407 } 408 409 /** {@inheritDoc} */ 410 public RealMatrix getRowMatrix(final int row) 411 throws MatrixIndexException { 412 413 MatrixUtils.checkRowIndex(this, row); 414 final int nCols = getColumnDimension(); 415 final RealMatrix out = createMatrix(1, nCols); 416 for (int i = 0; i < nCols; ++i) { 417 out.setEntry(0, i, getEntry(row, i)); 418 } 419 420 return out; 421 422 } 423 424 /** {@inheritDoc} */ 425 public void setRowMatrix(final int row, final RealMatrix matrix) 426 throws MatrixIndexException, InvalidMatrixException { 427 428 MatrixUtils.checkRowIndex(this, row); 429 final int nCols = getColumnDimension(); 430 if ((matrix.getRowDimension() != 1) || 431 (matrix.getColumnDimension() != nCols)) { 432 throw new InvalidMatrixException( 433 LocalizedFormats.DIMENSIONS_MISMATCH_2x2, 434 matrix.getRowDimension(), matrix.getColumnDimension(), 1, nCols); 435 } 436 for (int i = 0; i < nCols; ++i) { 437 setEntry(row, i, matrix.getEntry(0, i)); 438 } 439 440 } 441 442 /** {@inheritDoc} */ 443 public RealMatrix getColumnMatrix(final int column) 444 throws MatrixIndexException { 445 446 MatrixUtils.checkColumnIndex(this, column); 447 final int nRows = getRowDimension(); 448 final RealMatrix out = createMatrix(nRows, 1); 449 for (int i = 0; i < nRows; ++i) { 450 out.setEntry(i, 0, getEntry(i, column)); 451 } 452 453 return out; 454 455 } 456 457 /** {@inheritDoc} */ 458 public void setColumnMatrix(final int column, final RealMatrix matrix) 459 throws MatrixIndexException, InvalidMatrixException { 460 461 MatrixUtils.checkColumnIndex(this, column); 462 final int nRows = getRowDimension(); 463 if ((matrix.getRowDimension() != nRows) || 464 (matrix.getColumnDimension() != 1)) { 465 throw new InvalidMatrixException( 466 LocalizedFormats.DIMENSIONS_MISMATCH_2x2, 467 matrix.getRowDimension(), matrix.getColumnDimension(), nRows, 1); 468 } 469 for (int i = 0; i < nRows; ++i) { 470 setEntry(i, column, matrix.getEntry(i, 0)); 471 } 472 473 } 474 475 /** {@inheritDoc} */ 476 public RealVector getRowVector(final int row) 477 throws MatrixIndexException { 478 return new ArrayRealVector(getRow(row), false); 479 } 480 481 /** {@inheritDoc} */ 482 public void setRowVector(final int row, final RealVector vector) 483 throws MatrixIndexException, InvalidMatrixException { 484 485 MatrixUtils.checkRowIndex(this, row); 486 final int nCols = getColumnDimension(); 487 if (vector.getDimension() != nCols) { 488 throw new InvalidMatrixException( 489 LocalizedFormats.DIMENSIONS_MISMATCH_2x2, 490 1, vector.getDimension(), 1, nCols); 491 } 492 for (int i = 0; i < nCols; ++i) { 493 setEntry(row, i, vector.getEntry(i)); 494 } 495 496 } 497 498 /** {@inheritDoc} */ 499 public RealVector getColumnVector(final int column) 500 throws MatrixIndexException { 501 return new ArrayRealVector(getColumn(column), false); 502 } 503 504 /** {@inheritDoc} */ 505 public void setColumnVector(final int column, final RealVector vector) 506 throws MatrixIndexException, InvalidMatrixException { 507 508 MatrixUtils.checkColumnIndex(this, column); 509 final int nRows = getRowDimension(); 510 if (vector.getDimension() != nRows) { 511 throw new InvalidMatrixException( 512 LocalizedFormats.DIMENSIONS_MISMATCH_2x2, 513 vector.getDimension(), 1, nRows, 1); 514 } 515 for (int i = 0; i < nRows; ++i) { 516 setEntry(i, column, vector.getEntry(i)); 517 } 518 519 } 520 521 /** {@inheritDoc} */ 522 public double[] getRow(final int row) 523 throws MatrixIndexException { 524 525 MatrixUtils.checkRowIndex(this, row); 526 final int nCols = getColumnDimension(); 527 final double[] out = new double[nCols]; 528 for (int i = 0; i < nCols; ++i) { 529 out[i] = getEntry(row, i); 530 } 531 532 return out; 533 534 } 535 536 /** {@inheritDoc} */ 537 public void setRow(final int row, final double[] array) 538 throws MatrixIndexException, InvalidMatrixException { 539 540 MatrixUtils.checkRowIndex(this, row); 541 final int nCols = getColumnDimension(); 542 if (array.length != nCols) { 543 throw new InvalidMatrixException( 544 LocalizedFormats.DIMENSIONS_MISMATCH_2x2, 545 1, array.length, 1, nCols); 546 } 547 for (int i = 0; i < nCols; ++i) { 548 setEntry(row, i, array[i]); 549 } 550 551 } 552 553 /** {@inheritDoc} */ 554 public double[] getColumn(final int column) 555 throws MatrixIndexException { 556 557 MatrixUtils.checkColumnIndex(this, column); 558 final int nRows = getRowDimension(); 559 final double[] out = new double[nRows]; 560 for (int i = 0; i < nRows; ++i) { 561 out[i] = getEntry(i, column); 562 } 563 564 return out; 565 566 } 567 568 /** {@inheritDoc} */ 569 public void setColumn(final int column, final double[] array) 570 throws MatrixIndexException, InvalidMatrixException { 571 572 MatrixUtils.checkColumnIndex(this, column); 573 final int nRows = getRowDimension(); 574 if (array.length != nRows) { 575 throw new InvalidMatrixException( 576 LocalizedFormats.DIMENSIONS_MISMATCH_2x2, 577 array.length, 1, nRows, 1); 578 } 579 for (int i = 0; i < nRows; ++i) { 580 setEntry(i, column, array[i]); 581 } 582 583 } 584 585 /** {@inheritDoc} */ 586 public abstract double getEntry(int row, int column) 587 throws MatrixIndexException; 588 589 /** {@inheritDoc} */ 590 public abstract void setEntry(int row, int column, double value) 591 throws MatrixIndexException; 592 593 /** {@inheritDoc} */ 594 public abstract void addToEntry(int row, int column, double increment) 595 throws MatrixIndexException; 596 597 /** {@inheritDoc} */ 598 public abstract void multiplyEntry(int row, int column, double factor) 599 throws MatrixIndexException; 600 601 /** {@inheritDoc} */ 602 public RealMatrix transpose() { 603 604 final int nRows = getRowDimension(); 605 final int nCols = getColumnDimension(); 606 final RealMatrix out = createMatrix(nCols, nRows); 607 walkInOptimizedOrder(new DefaultRealMatrixPreservingVisitor() { 608 609 /** {@inheritDoc} */ 610 @Override 611 public void visit(final int row, final int column, final double value) { 612 out.setEntry(column, row, value); 613 } 614 615 }); 616 617 return out; 618 619 } 620 621 /** {@inheritDoc} */ 622 @Deprecated 623 public RealMatrix inverse() 624 throws InvalidMatrixException { 625 if (lu == null) { 626 lu = new LUDecompositionImpl(this, MathUtils.SAFE_MIN).getSolver(); 627 } 628 return lu.getInverse(); 629 } 630 631 /** {@inheritDoc} */ 632 @Deprecated 633 public double getDeterminant() 634 throws InvalidMatrixException { 635 return new LUDecompositionImpl(this, MathUtils.SAFE_MIN).getDeterminant(); 636 } 637 638 /** {@inheritDoc} */ 639 public boolean isSquare() { 640 return getColumnDimension() == getRowDimension(); 641 } 642 643 /** {@inheritDoc} */ 644 @Deprecated 645 public boolean isSingular() { 646 if (lu == null) { 647 lu = new LUDecompositionImpl(this, MathUtils.SAFE_MIN).getSolver(); 648 } 649 return !lu.isNonSingular(); 650 } 651 652 /** {@inheritDoc} */ 653 public abstract int getRowDimension(); 654 655 /** {@inheritDoc} */ 656 public abstract int getColumnDimension(); 657 658 /** {@inheritDoc} */ 659 public double getTrace() 660 throws NonSquareMatrixException { 661 final int nRows = getRowDimension(); 662 final int nCols = getColumnDimension(); 663 if (nRows != nCols) { 664 throw new NonSquareMatrixException(nRows, nCols); 665 } 666 double trace = 0; 667 for (int i = 0; i < nRows; ++i) { 668 trace += getEntry(i, i); 669 } 670 return trace; 671 } 672 673 /** {@inheritDoc} */ 674 public double[] operate(final double[] v) 675 throws IllegalArgumentException { 676 677 final int nRows = getRowDimension(); 678 final int nCols = getColumnDimension(); 679 if (v.length != nCols) { 680 throw MathRuntimeException.createIllegalArgumentException( 681 LocalizedFormats.VECTOR_LENGTH_MISMATCH, 682 v.length, nCols); 683 } 684 685 final double[] out = new double[nRows]; 686 for (int row = 0; row < nRows; ++row) { 687 double sum = 0; 688 for (int i = 0; i < nCols; ++i) { 689 sum += getEntry(row, i) * v[i]; 690 } 691 out[row] = sum; 692 } 693 694 return out; 695 696 } 697 698 /** {@inheritDoc} */ 699 public RealVector operate(final RealVector v) 700 throws IllegalArgumentException { 701 try { 702 return new ArrayRealVector(operate(((ArrayRealVector) v).getDataRef()), false); 703 } catch (ClassCastException cce) { 704 final int nRows = getRowDimension(); 705 final int nCols = getColumnDimension(); 706 if (v.getDimension() != nCols) { 707 throw MathRuntimeException.createIllegalArgumentException( 708 LocalizedFormats.VECTOR_LENGTH_MISMATCH, 709 v.getDimension(), nCols); 710 } 711 712 final double[] out = new double[nRows]; 713 for (int row = 0; row < nRows; ++row) { 714 double sum = 0; 715 for (int i = 0; i < nCols; ++i) { 716 sum += getEntry(row, i) * v.getEntry(i); 717 } 718 out[row] = sum; 719 } 720 721 return new ArrayRealVector(out, false); 722 } 723 } 724 725 /** {@inheritDoc} */ 726 public double[] preMultiply(final double[] v) 727 throws IllegalArgumentException { 728 729 final int nRows = getRowDimension(); 730 final int nCols = getColumnDimension(); 731 if (v.length != nRows) { 732 throw MathRuntimeException.createIllegalArgumentException( 733 LocalizedFormats.VECTOR_LENGTH_MISMATCH, 734 v.length, nRows); 735 } 736 737 final double[] out = new double[nCols]; 738 for (int col = 0; col < nCols; ++col) { 739 double sum = 0; 740 for (int i = 0; i < nRows; ++i) { 741 sum += getEntry(i, col) * v[i]; 742 } 743 out[col] = sum; 744 } 745 746 return out; 747 748 } 749 750 /** {@inheritDoc} */ 751 public RealVector preMultiply(final RealVector v) 752 throws IllegalArgumentException { 753 try { 754 return new ArrayRealVector(preMultiply(((ArrayRealVector) v).getDataRef()), false); 755 } catch (ClassCastException cce) { 756 757 final int nRows = getRowDimension(); 758 final int nCols = getColumnDimension(); 759 if (v.getDimension() != nRows) { 760 throw MathRuntimeException.createIllegalArgumentException( 761 LocalizedFormats.VECTOR_LENGTH_MISMATCH, 762 v.getDimension(), nRows); 763 } 764 765 final double[] out = new double[nCols]; 766 for (int col = 0; col < nCols; ++col) { 767 double sum = 0; 768 for (int i = 0; i < nRows; ++i) { 769 sum += getEntry(i, col) * v.getEntry(i); 770 } 771 out[col] = sum; 772 } 773 774 return new ArrayRealVector(out); 775 776 } 777 } 778 779 /** {@inheritDoc} */ 780 public double walkInRowOrder(final RealMatrixChangingVisitor visitor) 781 throws MatrixVisitorException { 782 final int rows = getRowDimension(); 783 final int columns = getColumnDimension(); 784 visitor.start(rows, columns, 0, rows - 1, 0, columns - 1); 785 for (int row = 0; row < rows; ++row) { 786 for (int column = 0; column < columns; ++column) { 787 final double oldValue = getEntry(row, column); 788 final double newValue = visitor.visit(row, column, oldValue); 789 setEntry(row, column, newValue); 790 } 791 } 792 lu = null; 793 return visitor.end(); 794 } 795 796 /** {@inheritDoc} */ 797 public double walkInRowOrder(final RealMatrixPreservingVisitor visitor) 798 throws MatrixVisitorException { 799 final int rows = getRowDimension(); 800 final int columns = getColumnDimension(); 801 visitor.start(rows, columns, 0, rows - 1, 0, columns - 1); 802 for (int row = 0; row < rows; ++row) { 803 for (int column = 0; column < columns; ++column) { 804 visitor.visit(row, column, getEntry(row, column)); 805 } 806 } 807 return visitor.end(); 808 } 809 810 /** {@inheritDoc} */ 811 public double walkInRowOrder(final RealMatrixChangingVisitor visitor, 812 final int startRow, final int endRow, 813 final int startColumn, final int endColumn) 814 throws MatrixIndexException, MatrixVisitorException { 815 MatrixUtils.checkSubMatrixIndex(this, startRow, endRow, startColumn, endColumn); 816 visitor.start(getRowDimension(), getColumnDimension(), 817 startRow, endRow, startColumn, endColumn); 818 for (int row = startRow; row <= endRow; ++row) { 819 for (int column = startColumn; column <= endColumn; ++column) { 820 final double oldValue = getEntry(row, column); 821 final double newValue = visitor.visit(row, column, oldValue); 822 setEntry(row, column, newValue); 823 } 824 } 825 lu = null; 826 return visitor.end(); 827 } 828 829 /** {@inheritDoc} */ 830 public double walkInRowOrder(final RealMatrixPreservingVisitor visitor, 831 final int startRow, final int endRow, 832 final int startColumn, final int endColumn) 833 throws MatrixIndexException, MatrixVisitorException { 834 MatrixUtils.checkSubMatrixIndex(this, startRow, endRow, startColumn, endColumn); 835 visitor.start(getRowDimension(), getColumnDimension(), 836 startRow, endRow, startColumn, endColumn); 837 for (int row = startRow; row <= endRow; ++row) { 838 for (int column = startColumn; column <= endColumn; ++column) { 839 visitor.visit(row, column, getEntry(row, column)); 840 } 841 } 842 return visitor.end(); 843 } 844 845 /** {@inheritDoc} */ 846 public double walkInColumnOrder(final RealMatrixChangingVisitor visitor) 847 throws MatrixVisitorException { 848 final int rows = getRowDimension(); 849 final int columns = getColumnDimension(); 850 visitor.start(rows, columns, 0, rows - 1, 0, columns - 1); 851 for (int column = 0; column < columns; ++column) { 852 for (int row = 0; row < rows; ++row) { 853 final double oldValue = getEntry(row, column); 854 final double newValue = visitor.visit(row, column, oldValue); 855 setEntry(row, column, newValue); 856 } 857 } 858 lu = null; 859 return visitor.end(); 860 } 861 862 /** {@inheritDoc} */ 863 public double walkInColumnOrder(final RealMatrixPreservingVisitor visitor) 864 throws MatrixVisitorException { 865 final int rows = getRowDimension(); 866 final int columns = getColumnDimension(); 867 visitor.start(rows, columns, 0, rows - 1, 0, columns - 1); 868 for (int column = 0; column < columns; ++column) { 869 for (int row = 0; row < rows; ++row) { 870 visitor.visit(row, column, getEntry(row, column)); 871 } 872 } 873 return visitor.end(); 874 } 875 876 /** {@inheritDoc} */ 877 public double walkInColumnOrder(final RealMatrixChangingVisitor visitor, 878 final int startRow, final int endRow, 879 final int startColumn, final int endColumn) 880 throws MatrixIndexException, MatrixVisitorException { 881 MatrixUtils.checkSubMatrixIndex(this, startRow, endRow, startColumn, endColumn); 882 visitor.start(getRowDimension(), getColumnDimension(), 883 startRow, endRow, startColumn, endColumn); 884 for (int column = startColumn; column <= endColumn; ++column) { 885 for (int row = startRow; row <= endRow; ++row) { 886 final double oldValue = getEntry(row, column); 887 final double newValue = visitor.visit(row, column, oldValue); 888 setEntry(row, column, newValue); 889 } 890 } 891 lu = null; 892 return visitor.end(); 893 } 894 895 /** {@inheritDoc} */ 896 public double walkInColumnOrder(final RealMatrixPreservingVisitor visitor, 897 final int startRow, final int endRow, 898 final int startColumn, final int endColumn) 899 throws MatrixIndexException, MatrixVisitorException { 900 MatrixUtils.checkSubMatrixIndex(this, startRow, endRow, startColumn, endColumn); 901 visitor.start(getRowDimension(), getColumnDimension(), 902 startRow, endRow, startColumn, endColumn); 903 for (int column = startColumn; column <= endColumn; ++column) { 904 for (int row = startRow; row <= endRow; ++row) { 905 visitor.visit(row, column, getEntry(row, column)); 906 } 907 } 908 return visitor.end(); 909 } 910 911 /** {@inheritDoc} */ 912 public double walkInOptimizedOrder(final RealMatrixChangingVisitor visitor) 913 throws MatrixVisitorException { 914 return walkInRowOrder(visitor); 915 } 916 917 /** {@inheritDoc} */ 918 public double walkInOptimizedOrder(final RealMatrixPreservingVisitor visitor) 919 throws MatrixVisitorException { 920 return walkInRowOrder(visitor); 921 } 922 923 /** {@inheritDoc} */ 924 public double walkInOptimizedOrder(final RealMatrixChangingVisitor visitor, 925 final int startRow, final int endRow, 926 final int startColumn, final int endColumn) 927 throws MatrixIndexException, MatrixVisitorException { 928 return walkInRowOrder(visitor, startRow, endRow, startColumn, endColumn); 929 } 930 931 /** {@inheritDoc} */ 932 public double walkInOptimizedOrder(final RealMatrixPreservingVisitor visitor, 933 final int startRow, final int endRow, 934 final int startColumn, final int endColumn) 935 throws MatrixIndexException, MatrixVisitorException { 936 return walkInRowOrder(visitor, startRow, endRow, startColumn, endColumn); 937 } 938 939 /** {@inheritDoc} */ 940 @Deprecated 941 public double[] solve(final double[] b) 942 throws IllegalArgumentException, InvalidMatrixException { 943 if (lu == null) { 944 lu = new LUDecompositionImpl(this, MathUtils.SAFE_MIN).getSolver(); 945 } 946 return lu.solve(b); 947 } 948 949 /** {@inheritDoc} */ 950 @Deprecated 951 public RealMatrix solve(final RealMatrix b) 952 throws IllegalArgumentException, InvalidMatrixException { 953 if (lu == null) { 954 lu = new LUDecompositionImpl(this, MathUtils.SAFE_MIN).getSolver(); 955 } 956 return lu.solve(b); 957 } 958 959 /** 960 * Computes a new 961 * <a href="http://www.math.gatech.edu/~bourbaki/math2601/Web-notes/2num.pdf"> 962 * LU decomposition</a> for this matrix, storing the result for use by other methods. 963 * <p> 964 * <strong>Implementation Note</strong>:<br> 965 * Uses <a href="http://www.damtp.cam.ac.uk/user/fdl/people/sd/lectures/nummeth98/linear.htm"> 966 * Crout's algorithm</a>, with partial pivoting.</p> 967 * <p> 968 * <strong>Usage Note</strong>:<br> 969 * This method should rarely be invoked directly. Its only use is 970 * to force recomputation of the LU decomposition when changes have been 971 * made to the underlying data using direct array references. Changes 972 * made using setXxx methods will trigger recomputation when needed 973 * automatically.</p> 974 * 975 * @throws InvalidMatrixException if the matrix is non-square or singular. 976 * @deprecated as of release 2.0, replaced by {@link LUDecomposition} 977 */ 978 @Deprecated 979 public void luDecompose() 980 throws InvalidMatrixException { 981 if (lu == null) { 982 lu = new LUDecompositionImpl(this, MathUtils.SAFE_MIN).getSolver(); 983 } 984 } 985 986 /** 987 * Get a string representation for this matrix. 988 * @return a string representation for this matrix 989 */ 990 @Override 991 public String toString() { 992 final int nRows = getRowDimension(); 993 final int nCols = getColumnDimension(); 994 final StringBuilder res = new StringBuilder(); 995 String fullClassName = getClass().getName(); 996 String shortClassName = fullClassName.substring(fullClassName.lastIndexOf('.') + 1); 997 res.append(shortClassName).append("{"); 998 999 for (int i = 0; i < nRows; ++i) { 1000 if (i > 0) { 1001 res.append(","); 1002 } 1003 res.append("{"); 1004 for (int j = 0; j < nCols; ++j) { 1005 if (j > 0) { 1006 res.append(","); 1007 } 1008 res.append(getEntry(i, j)); 1009 } 1010 res.append("}"); 1011 } 1012 1013 res.append("}"); 1014 return res.toString(); 1015 1016 } 1017 1018 /** 1019 * Returns true iff <code>object</code> is a 1020 * <code>RealMatrix</code> instance with the same dimensions as this 1021 * and all corresponding matrix entries are equal. 1022 * 1023 * @param object the object to test equality against. 1024 * @return true if object equals this 1025 */ 1026 @Override 1027 public boolean equals(final Object object) { 1028 if (object == this ) { 1029 return true; 1030 } 1031 if (object instanceof RealMatrix == false) { 1032 return false; 1033 } 1034 RealMatrix m = (RealMatrix) object; 1035 final int nRows = getRowDimension(); 1036 final int nCols = getColumnDimension(); 1037 if (m.getColumnDimension() != nCols || m.getRowDimension() != nRows) { 1038 return false; 1039 } 1040 for (int row = 0; row < nRows; ++row) { 1041 for (int col = 0; col < nCols; ++col) { 1042 if (getEntry(row, col) != m.getEntry(row, col)) { 1043 return false; 1044 } 1045 } 1046 } 1047 return true; 1048 } 1049 1050 /** 1051 * Computes a hashcode for the matrix. 1052 * 1053 * @return hashcode for matrix 1054 */ 1055 @Override 1056 public int hashCode() { 1057 int ret = 7; 1058 final int nRows = getRowDimension(); 1059 final int nCols = getColumnDimension(); 1060 ret = ret * 31 + nRows; 1061 ret = ret * 31 + nCols; 1062 for (int row = 0; row < nRows; ++row) { 1063 for (int col = 0; col < nCols; ++col) { 1064 ret = ret * 31 + (11 * (row+1) + 17 * (col+1)) * 1065 MathUtils.hash(getEntry(row, col)); 1066 } 1067 } 1068 return ret; 1069 } 1070 1071 } 1072