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