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