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