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 }