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