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