blob: 6373041e0ab19804eca351ddad7bec7b49837980 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.legacy.linear;
import java.util.ArrayList;
import java.util.Locale;
import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
import org.apache.commons.math4.legacy.exception.NoDataException;
import org.apache.commons.math4.legacy.exception.NotPositiveException;
import org.apache.commons.math4.legacy.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.legacy.exception.NullArgumentException;
import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
import org.apache.commons.math4.legacy.exception.OutOfRangeException;
import org.apache.commons.math4.legacy.exception.util.LocalizedFormats;
import org.apache.commons.math4.core.jdkmath.JdkMath;
/**
* Basic implementation of RealMatrix methods regardless of the underlying storage.
* <p>All the methods implemented here use {@link #getEntry(int, int)} to access
* matrix elements. Derived class can provide faster implementations.</p>
*
* @since 2.0
*/
public abstract class AbstractRealMatrix
extends RealLinearOperator
implements RealMatrix {
/** Default format. */
private static final RealMatrixFormat DEFAULT_FORMAT = RealMatrixFormat.getInstance(Locale.US);
static {
// set the minimum fraction digits to 1 to keep compatibility
DEFAULT_FORMAT.getFormat().setMinimumFractionDigits(1);
}
/**
* Creates a matrix with no data.
*/
protected AbstractRealMatrix() {}
/**
* Create a new RealMatrix with the supplied row and column dimensions.
*
* @param rowDimension the number of rows in the new matrix
* @param columnDimension the number of columns in the new matrix
* @throws NotStrictlyPositiveException if row or column dimension is not positive
*/
protected AbstractRealMatrix(final int rowDimension,
final int columnDimension)
throws NotStrictlyPositiveException {
if (rowDimension < 1) {
throw new NotStrictlyPositiveException(rowDimension);
}
if (columnDimension < 1) {
throw new NotStrictlyPositiveException(columnDimension);
}
}
/** {@inheritDoc} */
@Override
public RealMatrix add(RealMatrix m)
throws MatrixDimensionMismatchException {
checkAdd(m);
final int rowCount = getRowDimension();
final int columnCount = getColumnDimension();
final RealMatrix out = createMatrix(rowCount, columnCount);
for (int row = 0; row < rowCount; ++row) {
for (int col = 0; col < columnCount; ++col) {
out.setEntry(row, col, getEntry(row, col) + m.getEntry(row, col));
}
}
return out;
}
/** {@inheritDoc} */
@Override
public RealMatrix subtract(final RealMatrix m)
throws MatrixDimensionMismatchException {
checkAdd(m);
final int rowCount = getRowDimension();
final int columnCount = getColumnDimension();
final RealMatrix out = createMatrix(rowCount, columnCount);
for (int row = 0; row < rowCount; ++row) {
for (int col = 0; col < columnCount; ++col) {
out.setEntry(row, col, getEntry(row, col) - m.getEntry(row, col));
}
}
return out;
}
/** {@inheritDoc} */
@Override
public RealMatrix scalarAdd(final double d) {
final int rowCount = getRowDimension();
final int columnCount = getColumnDimension();
final RealMatrix out = createMatrix(rowCount, columnCount);
for (int row = 0; row < rowCount; ++row) {
for (int col = 0; col < columnCount; ++col) {
out.setEntry(row, col, getEntry(row, col) + d);
}
}
return out;
}
/** {@inheritDoc} */
@Override
public RealMatrix scalarMultiply(final double d) {
final int rowCount = getRowDimension();
final int columnCount = getColumnDimension();
final RealMatrix out = createMatrix(rowCount, columnCount);
for (int row = 0; row < rowCount; ++row) {
for (int col = 0; col < columnCount; ++col) {
out.setEntry(row, col, getEntry(row, col) * d);
}
}
return out;
}
/** {@inheritDoc} */
@Override
public RealMatrix multiply(final RealMatrix m)
throws DimensionMismatchException {
checkMultiply(m);
final int nRows = getRowDimension();
final int nCols = m.getColumnDimension();
final int nSum = getColumnDimension();
final RealMatrix out = createMatrix(nRows, nCols);
for (int row = 0; row < nRows; ++row) {
for (int col = 0; col < nCols; ++col) {
double sum = 0;
for (int i = 0; i < nSum; ++i) {
sum += getEntry(row, i) * m.getEntry(i, col);
}
out.setEntry(row, col, sum);
}
}
return out;
}
/** {@inheritDoc} */
@Override
public RealMatrix preMultiply(final RealMatrix m)
throws DimensionMismatchException {
return m.multiply(this);
}
/** {@inheritDoc} */
@Override
public RealMatrix power(final int p)
throws NotPositiveException, NonSquareMatrixException {
if (p < 0) {
throw new NotPositiveException(LocalizedFormats.NOT_POSITIVE_EXPONENT, p);
}
if (!isSquare()) {
throw new NonSquareMatrixException(getRowDimension(), getColumnDimension());
}
if (p == 0) {
return MatrixUtils.createRealIdentityMatrix(this.getRowDimension());
}
if (p == 1) {
return this.copy();
}
final int power = p - 1;
/*
* Only log_2(p) operations is used by doing as follows:
* 5^214 = 5^128 * 5^64 * 5^16 * 5^4 * 5^2
*
* In general, the same approach is used for A^p.
*/
final char[] binaryRepresentation = Integer.toBinaryString(power).toCharArray();
final ArrayList<Integer> nonZeroPositions = new ArrayList<>();
int maxI = -1;
for (int i = 0; i < binaryRepresentation.length; ++i) {
if (binaryRepresentation[i] == '1') {
final int pos = binaryRepresentation.length - i - 1;
nonZeroPositions.add(pos);
// The positions are taken in turn, so maxI is only changed once
if (maxI == -1) {
maxI = pos;
}
}
}
RealMatrix[] results = new RealMatrix[maxI + 1];
results[0] = this.copy();
for (int i = 1; i <= maxI; ++i) {
results[i] = results[i-1].multiply(results[i-1]);
}
RealMatrix result = this.copy();
for (Integer i : nonZeroPositions) {
result = result.multiply(results[i]);
}
return result;
}
/** {@inheritDoc} */
@Override
public double[][] getData() {
final double[][] data = new double[getRowDimension()][getColumnDimension()];
for (int i = 0; i < data.length; ++i) {
final double[] dataI = data[i];
for (int j = 0; j < dataI.length; ++j) {
dataI[j] = getEntry(i, j);
}
}
return data;
}
/** {@inheritDoc} */
@Override
public double getNorm() {
return walkInColumnOrder(new RealMatrixPreservingVisitor() {
/** Last row index. */
private double endRow;
/** Sum of absolute values on one column. */
private double columnSum;
/** Maximal sum across all columns. */
private double maxColSum;
/** {@inheritDoc} */
@Override
public void start(final int rows, final int columns,
final int startRow, final int endRow,
final int startColumn, final int endColumn) {
this.endRow = endRow;
columnSum = 0;
maxColSum = 0;
}
/** {@inheritDoc} */
@Override
public void visit(final int row, final int column, final double value) {
columnSum += JdkMath.abs(value);
if (row == endRow) {
maxColSum = JdkMath.max(maxColSum, columnSum);
columnSum = 0;
}
}
/** {@inheritDoc} */
@Override
public double end() {
return maxColSum;
}
});
}
/** {@inheritDoc} */
@Override
public double getFrobeniusNorm() {
return walkInOptimizedOrder(new RealMatrixPreservingVisitor() {
/** Sum of squared entries. */
private double sum;
/** {@inheritDoc} */
@Override
public void start(final int rows, final int columns,
final int startRow, final int endRow,
final int startColumn, final int endColumn) {
sum = 0;
}
/** {@inheritDoc} */
@Override
public void visit(final int row, final int column, final double value) {
sum += value * value;
}
/** {@inheritDoc} */
@Override
public double end() {
return JdkMath.sqrt(sum);
}
});
}
/** {@inheritDoc} */
@Override
public RealMatrix getSubMatrix(final int startRow, final int endRow,
final int startColumn, final int endColumn)
throws OutOfRangeException, NumberIsTooSmallException {
MatrixUtils.checkSubMatrixIndex(this, startRow, endRow, startColumn, endColumn);
final RealMatrix subMatrix =
createMatrix(endRow - startRow + 1, endColumn - startColumn + 1);
for (int i = startRow; i <= endRow; ++i) {
for (int j = startColumn; j <= endColumn; ++j) {
subMatrix.setEntry(i - startRow, j - startColumn, getEntry(i, j));
}
}
return subMatrix;
}
/** {@inheritDoc} */
@Override
public RealMatrix getSubMatrix(final int[] selectedRows,
final int[] selectedColumns)
throws NullArgumentException, NoDataException, OutOfRangeException {
MatrixUtils.checkSubMatrixIndex(this, selectedRows, selectedColumns);
final RealMatrix subMatrix =
createMatrix(selectedRows.length, selectedColumns.length);
subMatrix.walkInOptimizedOrder(new DefaultRealMatrixChangingVisitor() {
/** {@inheritDoc} */
@Override
public double visit(final int row, final int column, final double value) {
return getEntry(selectedRows[row], selectedColumns[column]);
}
});
return subMatrix;
}
/** {@inheritDoc} */
@Override
public void copySubMatrix(final int startRow, final int endRow,
final int startColumn, final int endColumn,
final double[][] destination)
throws OutOfRangeException, NumberIsTooSmallException,
MatrixDimensionMismatchException {
MatrixUtils.checkSubMatrixIndex(this, startRow, endRow, startColumn, endColumn);
final int rowsCount = endRow + 1 - startRow;
final int columnsCount = endColumn + 1 - startColumn;
if ((destination.length < rowsCount) || (destination[0].length < columnsCount)) {
throw new MatrixDimensionMismatchException(destination.length, destination[0].length,
rowsCount, columnsCount);
}
for (int i = 1; i < rowsCount; i++) {
if (destination[i].length < columnsCount) {
throw new MatrixDimensionMismatchException(destination.length, destination[i].length,
rowsCount, columnsCount);
}
}
walkInOptimizedOrder(new DefaultRealMatrixPreservingVisitor() {
/** Initial row index. */
private int startRow;
/** Initial column index. */
private int startColumn;
/** {@inheritDoc} */
@Override
public void start(final int rows, final int columns,
final int startRow, final int endRow,
final int startColumn, final int endColumn) {
this.startRow = startRow;
this.startColumn = startColumn;
}
/** {@inheritDoc} */
@Override
public void visit(final int row, final int column, final double value) {
destination[row - startRow][column - startColumn] = value;
}
}, startRow, endRow, startColumn, endColumn);
}
/** {@inheritDoc} */
@Override
public void copySubMatrix(int[] selectedRows, int[] selectedColumns,
double[][] destination)
throws OutOfRangeException, NullArgumentException, NoDataException,
MatrixDimensionMismatchException {
MatrixUtils.checkSubMatrixIndex(this, selectedRows, selectedColumns);
final int nCols = selectedColumns.length;
if ((destination.length < selectedRows.length) ||
(destination[0].length < nCols)) {
throw new MatrixDimensionMismatchException(destination.length, destination[0].length,
selectedRows.length, selectedColumns.length);
}
for (int i = 0; i < selectedRows.length; i++) {
final double[] destinationI = destination[i];
if (destinationI.length < nCols) {
throw new MatrixDimensionMismatchException(destination.length, destinationI.length,
selectedRows.length, selectedColumns.length);
}
for (int j = 0; j < selectedColumns.length; j++) {
destinationI[j] = getEntry(selectedRows[i], selectedColumns[j]);
}
}
}
/** {@inheritDoc} */
@Override
public void setSubMatrix(final double[][] subMatrix, final int row, final int column)
throws NoDataException, OutOfRangeException,
DimensionMismatchException, NullArgumentException {
NullArgumentException.check(subMatrix);
final int nRows = subMatrix.length;
if (nRows == 0) {
throw new NoDataException(LocalizedFormats.AT_LEAST_ONE_ROW);
}
final int nCols = subMatrix[0].length;
if (nCols == 0) {
throw new NoDataException(LocalizedFormats.AT_LEAST_ONE_COLUMN);
}
for (int r = 1; r < nRows; ++r) {
if (subMatrix[r].length != nCols) {
throw new DimensionMismatchException(nCols, subMatrix[r].length);
}
}
MatrixUtils.checkRowIndex(this, row);
MatrixUtils.checkColumnIndex(this, column);
MatrixUtils.checkRowIndex(this, nRows + row - 1);
MatrixUtils.checkColumnIndex(this, nCols + column - 1);
for (int i = 0; i < nRows; ++i) {
for (int j = 0; j < nCols; ++j) {
setEntry(row + i, column + j, subMatrix[i][j]);
}
}
}
/** {@inheritDoc} */
@Override
public RealMatrix getRowMatrix(final int row) throws OutOfRangeException {
MatrixUtils.checkRowIndex(this, row);
final int nCols = getColumnDimension();
final RealMatrix out = createMatrix(1, nCols);
for (int i = 0; i < nCols; ++i) {
out.setEntry(0, i, getEntry(row, i));
}
return out;
}
/** {@inheritDoc} */
@Override
public void setRowMatrix(final int row, final RealMatrix matrix)
throws OutOfRangeException, MatrixDimensionMismatchException {
MatrixUtils.checkRowIndex(this, row);
final int nCols = getColumnDimension();
if ((matrix.getRowDimension() != 1) ||
(matrix.getColumnDimension() != nCols)) {
throw new MatrixDimensionMismatchException(matrix.getRowDimension(),
matrix.getColumnDimension(),
1, nCols);
}
for (int i = 0; i < nCols; ++i) {
setEntry(row, i, matrix.getEntry(0, i));
}
}
/** {@inheritDoc} */
@Override
public RealMatrix getColumnMatrix(final int column)
throws OutOfRangeException {
MatrixUtils.checkColumnIndex(this, column);
final int nRows = getRowDimension();
final RealMatrix out = createMatrix(nRows, 1);
for (int i = 0; i < nRows; ++i) {
out.setEntry(i, 0, getEntry(i, column));
}
return out;
}
/** {@inheritDoc} */
@Override
public void setColumnMatrix(final int column, final RealMatrix matrix)
throws OutOfRangeException, MatrixDimensionMismatchException {
MatrixUtils.checkColumnIndex(this, column);
final int nRows = getRowDimension();
if ((matrix.getRowDimension() != nRows) ||
(matrix.getColumnDimension() != 1)) {
throw new MatrixDimensionMismatchException(matrix.getRowDimension(),
matrix.getColumnDimension(),
nRows, 1);
}
for (int i = 0; i < nRows; ++i) {
setEntry(i, column, matrix.getEntry(i, 0));
}
}
/** {@inheritDoc} */
@Override
public RealVector getRowVector(final int row)
throws OutOfRangeException {
return new ArrayRealVector(getRow(row), false);
}
/** {@inheritDoc} */
@Override
public void setRowVector(final int row, final RealVector vector)
throws OutOfRangeException, MatrixDimensionMismatchException {
MatrixUtils.checkRowIndex(this, row);
final int nCols = getColumnDimension();
if (vector.getDimension() != nCols) {
throw new MatrixDimensionMismatchException(1, vector.getDimension(),
1, nCols);
}
for (int i = 0; i < nCols; ++i) {
setEntry(row, i, vector.getEntry(i));
}
}
/** {@inheritDoc} */
@Override
public RealVector getColumnVector(final int column)
throws OutOfRangeException {
return new ArrayRealVector(getColumn(column), false);
}
/** {@inheritDoc} */
@Override
public void setColumnVector(final int column, final RealVector vector)
throws OutOfRangeException, MatrixDimensionMismatchException {
MatrixUtils.checkColumnIndex(this, column);
final int nRows = getRowDimension();
if (vector.getDimension() != nRows) {
throw new MatrixDimensionMismatchException(vector.getDimension(), 1,
nRows, 1);
}
for (int i = 0; i < nRows; ++i) {
setEntry(i, column, vector.getEntry(i));
}
}
/** {@inheritDoc} */
@Override
public double[] getRow(final int row) throws OutOfRangeException {
MatrixUtils.checkRowIndex(this, row);
final int nCols = getColumnDimension();
final double[] out = new double[nCols];
for (int i = 0; i < nCols; ++i) {
out[i] = getEntry(row, i);
}
return out;
}
/** {@inheritDoc} */
@Override
public void setRow(final int row, final double[] array)
throws OutOfRangeException, MatrixDimensionMismatchException {
MatrixUtils.checkRowIndex(this, row);
final int nCols = getColumnDimension();
if (array.length != nCols) {
throw new MatrixDimensionMismatchException(1, array.length, 1, nCols);
}
for (int i = 0; i < nCols; ++i) {
setEntry(row, i, array[i]);
}
}
/** {@inheritDoc} */
@Override
public double[] getColumn(final int column) throws OutOfRangeException {
MatrixUtils.checkColumnIndex(this, column);
final int nRows = getRowDimension();
final double[] out = new double[nRows];
for (int i = 0; i < nRows; ++i) {
out[i] = getEntry(i, column);
}
return out;
}
/** {@inheritDoc} */
@Override
public void setColumn(final int column, final double[] array)
throws OutOfRangeException, MatrixDimensionMismatchException {
MatrixUtils.checkColumnIndex(this, column);
final int nRows = getRowDimension();
if (array.length != nRows) {
throw new MatrixDimensionMismatchException(array.length, 1, nRows, 1);
}
for (int i = 0; i < nRows; ++i) {
setEntry(i, column, array[i]);
}
}
/** {@inheritDoc} */
@Override
public void addToEntry(int row, int column, double increment)
throws OutOfRangeException {
MatrixUtils.checkMatrixIndex(this, row, column);
setEntry(row, column, getEntry(row, column) + increment);
}
/** {@inheritDoc} */
@Override
public void multiplyEntry(int row, int column, double factor)
throws OutOfRangeException {
MatrixUtils.checkMatrixIndex(this, row, column);
setEntry(row, column, getEntry(row, column) * factor);
}
/** {@inheritDoc} */
@Override
public RealMatrix transpose() {
final int nRows = getRowDimension();
final int nCols = getColumnDimension();
final RealMatrix out = createMatrix(nCols, nRows);
walkInOptimizedOrder(new DefaultRealMatrixPreservingVisitor() {
/** {@inheritDoc} */
@Override
public void visit(final int row, final int column, final double value) {
out.setEntry(column, row, value);
}
});
return out;
}
/** {@inheritDoc} */
@Override
public double getTrace() throws NonSquareMatrixException {
final int nRows = getRowDimension();
final int nCols = getColumnDimension();
if (nRows != nCols) {
throw new NonSquareMatrixException(nRows, nCols);
}
double trace = 0;
for (int i = 0; i < nRows; ++i) {
trace += getEntry(i, i);
}
return trace;
}
/** {@inheritDoc} */
@Override
public double[] operate(final double[] v)
throws DimensionMismatchException {
final int nRows = getRowDimension();
final int nCols = getColumnDimension();
if (v.length != nCols) {
throw new DimensionMismatchException(v.length, nCols);
}
final double[] out = new double[nRows];
for (int row = 0; row < nRows; ++row) {
double sum = 0;
for (int i = 0; i < nCols; ++i) {
sum += getEntry(row, i) * v[i];
}
out[row] = sum;
}
return out;
}
/** {@inheritDoc} */
@Override
public RealVector operate(final RealVector v)
throws DimensionMismatchException {
if (v instanceof ArrayRealVector) {
return new ArrayRealVector(operate(((ArrayRealVector) v).getDataRef()), false);
}
final int nRows = getRowDimension();
final int nCols = getColumnDimension();
if (v.getDimension() != nCols) {
throw new DimensionMismatchException(v.getDimension(), nCols);
}
final double[] out = new double[nRows];
for (int row = 0; row < nRows; ++row) {
double sum = 0;
for (int i = 0; i < nCols; ++i) {
sum += getEntry(row, i) * v.getEntry(i);
}
out[row] = sum;
}
return new ArrayRealVector(out, false);
}
/** {@inheritDoc} */
@Override
public double[] preMultiply(final double[] v) throws DimensionMismatchException {
final int nRows = getRowDimension();
final int nCols = getColumnDimension();
if (v.length != nRows) {
throw new DimensionMismatchException(v.length, nRows);
}
final double[] out = new double[nCols];
for (int col = 0; col < nCols; ++col) {
double sum = 0;
for (int i = 0; i < nRows; ++i) {
sum += getEntry(i, col) * v[i];
}
out[col] = sum;
}
return out;
}
/** {@inheritDoc} */
@Override
public RealVector preMultiply(final RealVector v) throws DimensionMismatchException {
if (v instanceof ArrayRealVector) {
return new ArrayRealVector(preMultiply(((ArrayRealVector) v).getDataRef()), false);
}
final int nRows = getRowDimension();
final int nCols = getColumnDimension();
if (v.getDimension() != nRows) {
throw new DimensionMismatchException(v.getDimension(), nRows);
}
final double[] out = new double[nCols];
for (int col = 0; col < nCols; ++col) {
double sum = 0;
for (int i = 0; i < nRows; ++i) {
sum += getEntry(i, col) * v.getEntry(i);
}
out[col] = sum;
}
return new ArrayRealVector(out, false);
}
/** {@inheritDoc} */
@Override
public double walkInRowOrder(final RealMatrixChangingVisitor visitor) {
final int rows = getRowDimension();
final int columns = getColumnDimension();
visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
for (int row = 0; row < rows; ++row) {
for (int column = 0; column < columns; ++column) {
final double oldValue = getEntry(row, column);
final double newValue = visitor.visit(row, column, oldValue);
setEntry(row, column, newValue);
}
}
return visitor.end();
}
/** {@inheritDoc} */
@Override
public double walkInRowOrder(final RealMatrixPreservingVisitor visitor) {
final int rows = getRowDimension();
final int columns = getColumnDimension();
visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
for (int row = 0; row < rows; ++row) {
for (int column = 0; column < columns; ++column) {
visitor.visit(row, column, getEntry(row, column));
}
}
return visitor.end();
}
/** {@inheritDoc} */
@Override
public double walkInRowOrder(final RealMatrixChangingVisitor visitor,
final int startRow, final int endRow,
final int startColumn, final int endColumn)
throws OutOfRangeException, NumberIsTooSmallException {
MatrixUtils.checkSubMatrixIndex(this, startRow, endRow, startColumn, endColumn);
visitor.start(getRowDimension(), getColumnDimension(),
startRow, endRow, startColumn, endColumn);
for (int row = startRow; row <= endRow; ++row) {
for (int column = startColumn; column <= endColumn; ++column) {
final double oldValue = getEntry(row, column);
final double newValue = visitor.visit(row, column, oldValue);
setEntry(row, column, newValue);
}
}
return visitor.end();
}
/** {@inheritDoc} */
@Override
public double walkInRowOrder(final RealMatrixPreservingVisitor visitor,
final int startRow, final int endRow,
final int startColumn, final int endColumn)
throws OutOfRangeException, NumberIsTooSmallException {
MatrixUtils.checkSubMatrixIndex(this, startRow, endRow, startColumn, endColumn);
visitor.start(getRowDimension(), getColumnDimension(),
startRow, endRow, startColumn, endColumn);
for (int row = startRow; row <= endRow; ++row) {
for (int column = startColumn; column <= endColumn; ++column) {
visitor.visit(row, column, getEntry(row, column));
}
}
return visitor.end();
}
/** {@inheritDoc} */
@Override
public double walkInColumnOrder(final RealMatrixChangingVisitor visitor) {
final int rows = getRowDimension();
final int columns = getColumnDimension();
visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
for (int column = 0; column < columns; ++column) {
for (int row = 0; row < rows; ++row) {
final double oldValue = getEntry(row, column);
final double newValue = visitor.visit(row, column, oldValue);
setEntry(row, column, newValue);
}
}
return visitor.end();
}
/** {@inheritDoc} */
@Override
public double walkInColumnOrder(final RealMatrixPreservingVisitor visitor) {
final int rows = getRowDimension();
final int columns = getColumnDimension();
visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
for (int column = 0; column < columns; ++column) {
for (int row = 0; row < rows; ++row) {
visitor.visit(row, column, getEntry(row, column));
}
}
return visitor.end();
}
/** {@inheritDoc} */
@Override
public double walkInColumnOrder(final RealMatrixChangingVisitor visitor,
final int startRow, final int endRow,
final int startColumn, final int endColumn)
throws OutOfRangeException, NumberIsTooSmallException {
MatrixUtils.checkSubMatrixIndex(this, startRow, endRow, startColumn, endColumn);
visitor.start(getRowDimension(), getColumnDimension(),
startRow, endRow, startColumn, endColumn);
for (int column = startColumn; column <= endColumn; ++column) {
for (int row = startRow; row <= endRow; ++row) {
final double oldValue = getEntry(row, column);
final double newValue = visitor.visit(row, column, oldValue);
setEntry(row, column, newValue);
}
}
return visitor.end();
}
/** {@inheritDoc} */
@Override
public double walkInColumnOrder(final RealMatrixPreservingVisitor visitor,
final int startRow, final int endRow,
final int startColumn, final int endColumn)
throws OutOfRangeException, NumberIsTooSmallException {
MatrixUtils.checkSubMatrixIndex(this, startRow, endRow, startColumn, endColumn);
visitor.start(getRowDimension(), getColumnDimension(),
startRow, endRow, startColumn, endColumn);
for (int column = startColumn; column <= endColumn; ++column) {
for (int row = startRow; row <= endRow; ++row) {
visitor.visit(row, column, getEntry(row, column));
}
}
return visitor.end();
}
/** {@inheritDoc} */
@Override
public double walkInOptimizedOrder(final RealMatrixChangingVisitor visitor) {
return walkInRowOrder(visitor);
}
/** {@inheritDoc} */
@Override
public double walkInOptimizedOrder(final RealMatrixPreservingVisitor visitor) {
return walkInRowOrder(visitor);
}
/** {@inheritDoc} */
@Override
public double walkInOptimizedOrder(final RealMatrixChangingVisitor visitor,
final int startRow, final int endRow,
final int startColumn,
final int endColumn)
throws OutOfRangeException, NumberIsTooSmallException {
return walkInRowOrder(visitor, startRow, endRow, startColumn, endColumn);
}
/** {@inheritDoc} */
@Override
public double walkInOptimizedOrder(final RealMatrixPreservingVisitor visitor,
final int startRow, final int endRow,
final int startColumn,
final int endColumn)
throws OutOfRangeException, NumberIsTooSmallException {
return walkInRowOrder(visitor, startRow, endRow, startColumn, endColumn);
}
/**
* Get a string representation for this matrix.
* @return a string representation for this matrix
*/
@Override
public String toString() {
final StringBuilder res = new StringBuilder();
String fullClassName = getClass().getName();
String shortClassName = fullClassName.substring(fullClassName.lastIndexOf('.') + 1);
res.append(shortClassName);
res.append(DEFAULT_FORMAT.format(this));
return res.toString();
}
/**
* Returns true iff <code>object</code> is a
* <code>RealMatrix</code> instance with the same dimensions as this
* and all corresponding matrix entries are equal.
*
* @param object the object to test equality against.
* @return true if object equals this
*/
@Override
public boolean equals(final Object object) {
if (object == this ) {
return true;
}
if (!(object instanceof RealMatrix)) {
return false;
}
RealMatrix m = (RealMatrix) object;
final int nRows = getRowDimension();
final int nCols = getColumnDimension();
if (m.getColumnDimension() != nCols || m.getRowDimension() != nRows) {
return false;
}
for (int row = 0; row < nRows; ++row) {
for (int col = 0; col < nCols; ++col) {
if (getEntry(row, col) != m.getEntry(row, col)) {
return false;
}
}
}
return true;
}
/**
* Computes a hashcode for the matrix.
*
* @return hashcode for matrix
*/
@Override
public int hashCode() {
int ret = 7;
final int nRows = getRowDimension();
final int nCols = getColumnDimension();
ret = ret * 31 + nRows;
ret = ret * 31 + nCols;
for (int row = 0; row < nRows; ++row) {
for (int col = 0; col < nCols; ++col) {
ret = ret * 31 + (11 * (row+1) + 17 * (col+1)) *
Double.hashCode(getEntry(row, col));
}
}
return ret;
}
/*
* Empty implementations of these methods are provided in order to allow for
* the use of the @Override tag with Java 1.5.
*/
/** {@inheritDoc} */
@Override
public abstract RealMatrix createMatrix(int rowDimension, int columnDimension)
throws NotStrictlyPositiveException;
/** {@inheritDoc} */
@Override
public abstract RealMatrix copy();
/** {@inheritDoc} */
@Override
public abstract double getEntry(int row, int column)
throws OutOfRangeException;
/** {@inheritDoc} */
@Override
public abstract void setEntry(int row, int column, double value)
throws OutOfRangeException;
}