/* * 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.math.linear; import java.lang.reflect.Array; import java.util.Arrays; import org.apache.commons.math.Field; import org.apache.commons.math.FieldElement; import org.apache.commons.math.MathRuntimeException; import org.apache.commons.math.linear.MatrixVisitorException; import org.apache.commons.math.exception.util.LocalizedFormats; /** * Basic implementation of {@link FieldMatrix} 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> * * @param <T> the type of the field elements * @version $Revision: 1073158 $ $Date: 2011-02-21 22:46:52 +0100 (lun. 21 févr. 2011) $ * @since 2.0 */ public abstract class AbstractFieldMatrix<T extends FieldElement<T>> implements FieldMatrix<T> { /** Field to which the elements belong. */ private final Field<T> field; /** * Constructor for use with Serializable */ protected AbstractFieldMatrix() { field = null; } /** * Creates a matrix with no data * @param field field to which the elements belong */ protected AbstractFieldMatrix(final Field<T> field) { this.field = field; } /** * Create a new FieldMatrix<T> with the supplied row and column dimensions. * * @param field field to which the elements belong * @param rowDimension the number of rows in the new matrix * @param columnDimension the number of columns in the new matrix * @throws IllegalArgumentException if row or column dimension is not positive */ protected AbstractFieldMatrix(final Field<T> field, final int rowDimension, final int columnDimension) throws IllegalArgumentException { if (rowDimension < 1 ) { throw MathRuntimeException.createIllegalArgumentException( LocalizedFormats.INSUFFICIENT_DIMENSION, rowDimension, 1); } if (columnDimension < 1) { throw MathRuntimeException.createIllegalArgumentException( LocalizedFormats.INSUFFICIENT_DIMENSION, columnDimension, 1); } this.field = field; } /** * Get the elements type from an array. * @param <T> the type of the field elements * @param d data array * @return field to which array elements belong * @exception IllegalArgumentException if array is empty */ protected static <T extends FieldElement<T>> Field<T> extractField(final T[][] d) throws IllegalArgumentException { if (d.length == 0) { throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_ROW); } if (d[0].length == 0) { throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_COLUMN); } return d[0][0].getField(); } /** * Get the elements type from an array. * @param <T> the type of the field elements * @param d data array * @return field to which array elements belong * @exception IllegalArgumentException if array is empty */ protected static <T extends FieldElement<T>> Field<T> extractField(final T[] d) throws IllegalArgumentException { if (d.length == 0) { throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_ROW); } return d[0].getField(); } /** Build an array of elements. * <p> * Complete arrays are filled with field.getZero() * </p> * @param <T> the type of the field elements * @param field field to which array elements belong * @param rows number of rows * @param columns number of columns (may be negative to build partial * arrays in the same way <code>new Field[rows][]</code> works) * @return a new array */ @SuppressWarnings("unchecked") protected static <T extends FieldElement<T>> T[][] buildArray(final Field<T> field, final int rows, final int columns) { if (columns < 0) { T[] dummyRow = (T[]) Array.newInstance(field.getZero().getClass(), 0); return (T[][]) Array.newInstance(dummyRow.getClass(), rows); } T[][] array = (T[][]) Array.newInstance(field.getZero().getClass(), new int[] { rows, columns }); for (int i = 0; i < array.length; ++i) { Arrays.fill(array[i], field.getZero()); } return array; } /** Build an array of elements. * <p> * Arrays are filled with field.getZero() * </p> * @param <T> the type of the field elements * @param field field to which array elements belong * @param length of the array * @return a new array */ protected static <T extends FieldElement<T>> T[] buildArray(final Field<T> field, final int length) { @SuppressWarnings("unchecked") // OK because field must be correct class T[] array = (T[]) Array.newInstance(field.getZero().getClass(), length); Arrays.fill(array, field.getZero()); return array; } /** {@inheritDoc} */ public Field<T> getField() { return field; } /** {@inheritDoc} */ public abstract FieldMatrix<T> createMatrix(final int rowDimension, final int columnDimension) throws IllegalArgumentException; /** {@inheritDoc} */ public abstract FieldMatrix<T> copy(); /** {@inheritDoc} */ public FieldMatrix<T> add(FieldMatrix<T> m) throws IllegalArgumentException { // safety check checkAdditionCompatible(m); final int rowCount = getRowDimension(); final int columnCount = getColumnDimension(); final FieldMatrix<T> 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).add(m.getEntry(row, col))); } } return out; } /** {@inheritDoc} */ public FieldMatrix<T> subtract(final FieldMatrix<T> m) throws IllegalArgumentException { // safety check checkSubtractionCompatible(m); final int rowCount = getRowDimension(); final int columnCount = getColumnDimension(); final FieldMatrix<T> 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).subtract(m.getEntry(row, col))); } } return out; } /** {@inheritDoc} */ public FieldMatrix<T> scalarAdd(final T d) { final int rowCount = getRowDimension(); final int columnCount = getColumnDimension(); final FieldMatrix<T> 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).add(d)); } } return out; } /** {@inheritDoc} */ public FieldMatrix<T> scalarMultiply(final T d) { final int rowCount = getRowDimension(); final int columnCount = getColumnDimension(); final FieldMatrix<T> 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).multiply(d)); } } return out; } /** {@inheritDoc} */ public FieldMatrix<T> multiply(final FieldMatrix<T> m) throws IllegalArgumentException { // safety check checkMultiplicationCompatible(m); final int nRows = getRowDimension(); final int nCols = m.getColumnDimension(); final int nSum = getColumnDimension(); final FieldMatrix<T> out = createMatrix(nRows, nCols); for (int row = 0; row < nRows; ++row) { for (int col = 0; col < nCols; ++col) { T sum = field.getZero(); for (int i = 0; i < nSum; ++i) { sum = sum.add(getEntry(row, i).multiply(m.getEntry(i, col))); } out.setEntry(row, col, sum); } } return out; } /** {@inheritDoc} */ public FieldMatrix<T> preMultiply(final FieldMatrix<T> m) throws IllegalArgumentException { return m.multiply(this); } /** {@inheritDoc} */ public T[][] getData() { final T[][] data = buildArray(field, getRowDimension(), getColumnDimension()); for (int i = 0; i < data.length; ++i) { final T[] dataI = data[i]; for (int j = 0; j < dataI.length; ++j) { dataI[j] = getEntry(i, j); } } return data; } /** {@inheritDoc} */ public FieldMatrix<T> getSubMatrix(final int startRow, final int endRow, final int startColumn, final int endColumn) throws MatrixIndexException { checkSubMatrixIndex(startRow, endRow, startColumn, endColumn); final FieldMatrix<T> 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} */ public FieldMatrix<T> getSubMatrix(final int[] selectedRows, final int[] selectedColumns) throws MatrixIndexException { // safety checks checkSubMatrixIndex(selectedRows, selectedColumns); // copy entries final FieldMatrix<T> subMatrix = createMatrix(selectedRows.length, selectedColumns.length); subMatrix.walkInOptimizedOrder(new DefaultFieldMatrixChangingVisitor<T>(field.getZero()) { /** {@inheritDoc} */ @Override public T visit(final int row, final int column, final T value) { return getEntry(selectedRows[row], selectedColumns[column]); } }); return subMatrix; } /** {@inheritDoc} */ public void copySubMatrix(final int startRow, final int endRow, final int startColumn, final int endColumn, final T[][] destination) throws MatrixIndexException, IllegalArgumentException { // safety checks checkSubMatrixIndex(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 MathRuntimeException.createIllegalArgumentException( LocalizedFormats.DIMENSIONS_MISMATCH_2x2, destination.length, destination[0].length, rowsCount, columnsCount); } // copy entries walkInOptimizedOrder(new DefaultFieldMatrixPreservingVisitor<T>(field.getZero()) { /** 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 T value) { destination[row - startRow][column - startColumn] = value; } }, startRow, endRow, startColumn, endColumn); } /** {@inheritDoc} */ public void copySubMatrix(int[] selectedRows, int[] selectedColumns, T[][] destination) throws MatrixIndexException, IllegalArgumentException { // safety checks checkSubMatrixIndex(selectedRows, selectedColumns); if ((destination.length < selectedRows.length) || (destination[0].length < selectedColumns.length)) { throw MathRuntimeException.createIllegalArgumentException( LocalizedFormats.DIMENSIONS_MISMATCH_2x2, destination.length, destination[0].length, selectedRows.length, selectedColumns.length); } // copy entries for (int i = 0; i < selectedRows.length; i++) { final T[] destinationI = destination[i]; for (int j = 0; j < selectedColumns.length; j++) { destinationI[j] = getEntry(selectedRows[i], selectedColumns[j]); } } } /** {@inheritDoc} */ public void setSubMatrix(final T[][] subMatrix, final int row, final int column) throws MatrixIndexException { final int nRows = subMatrix.length; if (nRows == 0) { throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_ROW); } final int nCols = subMatrix[0].length; if (nCols == 0) { throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_COLUMN); } for (int r = 1; r < nRows; ++r) { if (subMatrix[r].length != nCols) { throw MathRuntimeException.createIllegalArgumentException( LocalizedFormats.DIFFERENT_ROWS_LENGTHS, nCols, subMatrix[r].length); } } checkRowIndex(row); checkColumnIndex(column); checkRowIndex(nRows + row - 1); checkColumnIndex(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} */ public FieldMatrix<T> getRowMatrix(final int row) throws MatrixIndexException { checkRowIndex(row); final int nCols = getColumnDimension(); final FieldMatrix<T> out = createMatrix(1, nCols); for (int i = 0; i < nCols; ++i) { out.setEntry(0, i, getEntry(row, i)); } return out; } /** {@inheritDoc} */ public void setRowMatrix(final int row, final FieldMatrix<T> matrix) throws MatrixIndexException, InvalidMatrixException { checkRowIndex(row); final int nCols = getColumnDimension(); if ((matrix.getRowDimension() != 1) || (matrix.getColumnDimension() != nCols)) { throw new InvalidMatrixException( LocalizedFormats.DIMENSIONS_MISMATCH_2x2, matrix.getRowDimension(), matrix.getColumnDimension(), 1, nCols); } for (int i = 0; i < nCols; ++i) { setEntry(row, i, matrix.getEntry(0, i)); } } /** {@inheritDoc} */ public FieldMatrix<T> getColumnMatrix(final int column) throws MatrixIndexException { checkColumnIndex(column); final int nRows = getRowDimension(); final FieldMatrix<T> out = createMatrix(nRows, 1); for (int i = 0; i < nRows; ++i) { out.setEntry(i, 0, getEntry(i, column)); } return out; } /** {@inheritDoc} */ public void setColumnMatrix(final int column, final FieldMatrix<T> matrix) throws MatrixIndexException, InvalidMatrixException { checkColumnIndex(column); final int nRows = getRowDimension(); if ((matrix.getRowDimension() != nRows) || (matrix.getColumnDimension() != 1)) { throw new InvalidMatrixException( LocalizedFormats.DIMENSIONS_MISMATCH_2x2, matrix.getRowDimension(), matrix.getColumnDimension(), nRows, 1); } for (int i = 0; i < nRows; ++i) { setEntry(i, column, matrix.getEntry(i, 0)); } } /** {@inheritDoc} */ public FieldVector<T> getRowVector(final int row) throws MatrixIndexException { return new ArrayFieldVector<T>(getRow(row), false); } /** {@inheritDoc} */ public void setRowVector(final int row, final FieldVector<T> vector) throws MatrixIndexException, InvalidMatrixException { checkRowIndex(row); final int nCols = getColumnDimension(); if (vector.getDimension() != nCols) { throw new InvalidMatrixException( LocalizedFormats.DIMENSIONS_MISMATCH_2x2, 1, vector.getDimension(), 1, nCols); } for (int i = 0; i < nCols; ++i) { setEntry(row, i, vector.getEntry(i)); } } /** {@inheritDoc} */ public FieldVector<T> getColumnVector(final int column) throws MatrixIndexException { return new ArrayFieldVector<T>(getColumn(column), false); } /** {@inheritDoc} */ public void setColumnVector(final int column, final FieldVector<T> vector) throws MatrixIndexException, InvalidMatrixException { checkColumnIndex(column); final int nRows = getRowDimension(); if (vector.getDimension() != nRows) { throw new InvalidMatrixException( LocalizedFormats.DIMENSIONS_MISMATCH_2x2, vector.getDimension(), 1, nRows, 1); } for (int i = 0; i < nRows; ++i) { setEntry(i, column, vector.getEntry(i)); } } /** {@inheritDoc} */ public T[] getRow(final int row) throws MatrixIndexException { checkRowIndex(row); final int nCols = getColumnDimension(); final T[] out = buildArray(field, nCols); for (int i = 0; i < nCols; ++i) { out[i] = getEntry(row, i); } return out; } /** {@inheritDoc} */ public void setRow(final int row, final T[] array) throws MatrixIndexException, InvalidMatrixException { checkRowIndex(row); final int nCols = getColumnDimension(); if (array.length != nCols) { throw new InvalidMatrixException( LocalizedFormats.DIMENSIONS_MISMATCH_2x2, 1, array.length, 1, nCols); } for (int i = 0; i < nCols; ++i) { setEntry(row, i, array[i]); } } /** {@inheritDoc} */ public T[] getColumn(final int column) throws MatrixIndexException { checkColumnIndex(column); final int nRows = getRowDimension(); final T[] out = buildArray(field, nRows); for (int i = 0; i < nRows; ++i) { out[i] = getEntry(i, column); } return out; } /** {@inheritDoc} */ public void setColumn(final int column, final T[] array) throws MatrixIndexException, InvalidMatrixException { checkColumnIndex(column); final int nRows = getRowDimension(); if (array.length != nRows) { throw new InvalidMatrixException( LocalizedFormats.DIMENSIONS_MISMATCH_2x2, array.length, 1, nRows, 1); } for (int i = 0; i < nRows; ++i) { setEntry(i, column, array[i]); } } /** {@inheritDoc} */ public abstract T getEntry(int row, int column) throws MatrixIndexException; /** {@inheritDoc} */ public abstract void setEntry(int row, int column, T value) throws MatrixIndexException; /** {@inheritDoc} */ public abstract void addToEntry(int row, int column, T increment) throws MatrixIndexException; /** {@inheritDoc} */ public abstract void multiplyEntry(int row, int column, T factor) throws MatrixIndexException; /** {@inheritDoc} */ public FieldMatrix<T> transpose() { final int nRows = getRowDimension(); final int nCols = getColumnDimension(); final FieldMatrix<T> out = createMatrix(nCols, nRows); walkInOptimizedOrder(new DefaultFieldMatrixPreservingVisitor<T>(field.getZero()) { /** {@inheritDoc} */ @Override public void visit(final int row, final int column, final T value) { out.setEntry(column, row, value); } }); return out; } /** {@inheritDoc} */ public boolean isSquare() { return getColumnDimension() == getRowDimension(); } /** {@inheritDoc} */ public abstract int getRowDimension(); /** {@inheritDoc} */ public abstract int getColumnDimension(); /** {@inheritDoc} */ public T getTrace() throws NonSquareMatrixException { final int nRows = getRowDimension(); final int nCols = getColumnDimension(); if (nRows != nCols) { throw new NonSquareMatrixException(nRows, nCols); } T trace = field.getZero(); for (int i = 0; i < nRows; ++i) { trace = trace.add(getEntry(i, i)); } return trace; } /** {@inheritDoc} */ public T[] operate(final T[] v) throws IllegalArgumentException { final int nRows = getRowDimension(); final int nCols = getColumnDimension(); if (v.length != nCols) { throw MathRuntimeException.createIllegalArgumentException( LocalizedFormats.VECTOR_LENGTH_MISMATCH, v.length, nCols); } final T[] out = buildArray(field, nRows); for (int row = 0; row < nRows; ++row) { T sum = field.getZero(); for (int i = 0; i < nCols; ++i) { sum = sum.add(getEntry(row, i).multiply(v[i])); } out[row] = sum; } return out; } /** {@inheritDoc} */ public FieldVector<T> operate(final FieldVector<T> v) throws IllegalArgumentException { try { return new ArrayFieldVector<T>(operate(((ArrayFieldVector<T>) v).getDataRef()), false); } catch (ClassCastException cce) { final int nRows = getRowDimension(); final int nCols = getColumnDimension(); if (v.getDimension() != nCols) { throw MathRuntimeException.createIllegalArgumentException( LocalizedFormats.VECTOR_LENGTH_MISMATCH, v.getDimension(), nCols); } final T[] out = buildArray(field, nRows); for (int row = 0; row < nRows; ++row) { T sum = field.getZero(); for (int i = 0; i < nCols; ++i) { sum = sum.add(getEntry(row, i).multiply(v.getEntry(i))); } out[row] = sum; } return new ArrayFieldVector<T>(out, false); } } /** {@inheritDoc} */ public T[] preMultiply(final T[] v) throws IllegalArgumentException { final int nRows = getRowDimension(); final int nCols = getColumnDimension(); if (v.length != nRows) { throw MathRuntimeException.createIllegalArgumentException( LocalizedFormats.VECTOR_LENGTH_MISMATCH, v.length, nRows); } final T[] out = buildArray(field, nCols); for (int col = 0; col < nCols; ++col) { T sum = field.getZero(); for (int i = 0; i < nRows; ++i) { sum = sum.add(getEntry(i, col).multiply(v[i])); } out[col] = sum; } return out; } /** {@inheritDoc} */ public FieldVector<T> preMultiply(final FieldVector<T> v) throws IllegalArgumentException { try { return new ArrayFieldVector<T>(preMultiply(((ArrayFieldVector<T>) v).getDataRef()), false); } catch (ClassCastException cce) { final int nRows = getRowDimension(); final int nCols = getColumnDimension(); if (v.getDimension() != nRows) { throw MathRuntimeException.createIllegalArgumentException( LocalizedFormats.VECTOR_LENGTH_MISMATCH, v.getDimension(), nRows); } final T[] out = buildArray(field, nCols); for (int col = 0; col < nCols; ++col) { T sum = field.getZero(); for (int i = 0; i < nRows; ++i) { sum = sum.add(getEntry(i, col).multiply(v.getEntry(i))); } out[col] = sum; } return new ArrayFieldVector<T>(out); } } /** {@inheritDoc} */ public T walkInRowOrder(final FieldMatrixChangingVisitor<T> visitor) throws MatrixVisitorException { 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 T oldValue = getEntry(row, column); final T newValue = visitor.visit(row, column, oldValue); setEntry(row, column, newValue); } } return visitor.end(); } /** {@inheritDoc} */ public T walkInRowOrder(final FieldMatrixPreservingVisitor<T> visitor) throws MatrixVisitorException { 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} */ public T walkInRowOrder(final FieldMatrixChangingVisitor<T> visitor, final int startRow, final int endRow, final int startColumn, final int endColumn) throws MatrixIndexException, MatrixVisitorException { checkSubMatrixIndex(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 T oldValue = getEntry(row, column); final T newValue = visitor.visit(row, column, oldValue); setEntry(row, column, newValue); } } return visitor.end(); } /** {@inheritDoc} */ public T walkInRowOrder(final FieldMatrixPreservingVisitor<T> visitor, final int startRow, final int endRow, final int startColumn, final int endColumn) throws MatrixIndexException, MatrixVisitorException { checkSubMatrixIndex(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} */ public T walkInColumnOrder(final FieldMatrixChangingVisitor<T> visitor) throws MatrixVisitorException { 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 T oldValue = getEntry(row, column); final T newValue = visitor.visit(row, column, oldValue); setEntry(row, column, newValue); } } return visitor.end(); } /** {@inheritDoc} */ public T walkInColumnOrder(final FieldMatrixPreservingVisitor<T> visitor) throws MatrixVisitorException { 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} */ public T walkInColumnOrder(final FieldMatrixChangingVisitor<T> visitor, final int startRow, final int endRow, final int startColumn, final int endColumn) throws MatrixIndexException, MatrixVisitorException { checkSubMatrixIndex(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 T oldValue = getEntry(row, column); final T newValue = visitor.visit(row, column, oldValue); setEntry(row, column, newValue); } } return visitor.end(); } /** {@inheritDoc} */ public T walkInColumnOrder(final FieldMatrixPreservingVisitor<T> visitor, final int startRow, final int endRow, final int startColumn, final int endColumn) throws MatrixIndexException, MatrixVisitorException { checkSubMatrixIndex(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} */ public T walkInOptimizedOrder(final FieldMatrixChangingVisitor<T> visitor) throws MatrixVisitorException { return walkInRowOrder(visitor); } /** {@inheritDoc} */ public T walkInOptimizedOrder(final FieldMatrixPreservingVisitor<T> visitor) throws MatrixVisitorException { return walkInRowOrder(visitor); } /** {@inheritDoc} */ public T walkInOptimizedOrder(final FieldMatrixChangingVisitor<T> visitor, final int startRow, final int endRow, final int startColumn, final int endColumn) throws MatrixIndexException, MatrixVisitorException { return walkInRowOrder(visitor, startRow, endRow, startColumn, endColumn); } /** {@inheritDoc} */ public T walkInOptimizedOrder(final FieldMatrixPreservingVisitor<T> visitor, final int startRow, final int endRow, final int startColumn, final int endColumn) throws MatrixIndexException, MatrixVisitorException { 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 int nRows = getRowDimension(); final int nCols = getColumnDimension(); final StringBuilder res = new StringBuilder(); String fullClassName = getClass().getName(); String shortClassName = fullClassName.substring(fullClassName.lastIndexOf('.') + 1); res.append(shortClassName).append("{"); for (int i = 0; i < nRows; ++i) { if (i > 0) { res.append(","); } res.append("{"); for (int j = 0; j < nCols; ++j) { if (j > 0) { res.append(","); } res.append(getEntry(i, j)); } res.append("}"); } res.append("}"); return res.toString(); } /** * Returns true iff <code>object</code> is a * <code>FieldMatrix</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 FieldMatrix<?> == false) { return false; } FieldMatrix<?> m = (FieldMatrix<?>) 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).equals(m.getEntry(row, col))) { return false; } } } return true; } /** * Computes a hashcode for the matrix. * * @return hashcode for matrix */ @Override public int hashCode() { int ret = 322562; 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)) * getEntry(row, col).hashCode(); } } return ret; } /** * Check if a row index is valid. * @param row row index to check * @exception MatrixIndexException if index is not valid */ protected void checkRowIndex(final int row) { if (row < 0 || row >= getRowDimension()) { throw new MatrixIndexException(LocalizedFormats.ROW_INDEX_OUT_OF_RANGE, row, 0, getRowDimension() - 1); } } /** * Check if a column index is valid. * @param column column index to check * @exception MatrixIndexException if index is not valid */ protected void checkColumnIndex(final int column) throws MatrixIndexException { if (column < 0 || column >= getColumnDimension()) { throw new MatrixIndexException(LocalizedFormats.COLUMN_INDEX_OUT_OF_RANGE, column, 0, getColumnDimension() - 1); } } /** * Check if submatrix ranges indices are valid. * Rows and columns are indicated counting from 0 to n-1. * * @param startRow Initial row index * @param endRow Final row index * @param startColumn Initial column index * @param endColumn Final column index * @exception MatrixIndexException if the indices are not valid */ protected void checkSubMatrixIndex(final int startRow, final int endRow, final int startColumn, final int endColumn) { checkRowIndex(startRow); checkRowIndex(endRow); if (startRow > endRow) { throw new MatrixIndexException(LocalizedFormats.INITIAL_ROW_AFTER_FINAL_ROW, startRow, endRow); } checkColumnIndex(startColumn); checkColumnIndex(endColumn); if (startColumn > endColumn) { throw new MatrixIndexException(LocalizedFormats.INITIAL_COLUMN_AFTER_FINAL_COLUMN, startColumn, endColumn); } } /** * Check if submatrix ranges indices are valid. * Rows and columns are indicated counting from 0 to n-1. * * @param selectedRows Array of row indices. * @param selectedColumns Array of column indices. * @exception MatrixIndexException if row or column selections are not valid */ protected void checkSubMatrixIndex(final int[] selectedRows, final int[] selectedColumns) { if (selectedRows.length * selectedColumns.length == 0) { if (selectedRows.length == 0) { throw new MatrixIndexException(LocalizedFormats.EMPTY_SELECTED_ROW_INDEX_ARRAY); } throw new MatrixIndexException(LocalizedFormats.EMPTY_SELECTED_COLUMN_INDEX_ARRAY); } for (final int row : selectedRows) { checkRowIndex(row); } for (final int column : selectedColumns) { checkColumnIndex(column); } } /** * Check if a matrix is addition compatible with the instance * @param m matrix to check * @exception IllegalArgumentException if matrix is not addition compatible with instance */ protected void checkAdditionCompatible(final FieldMatrix<T> m) { if ((getRowDimension() != m.getRowDimension()) || (getColumnDimension() != m.getColumnDimension())) { throw MathRuntimeException.createIllegalArgumentException( LocalizedFormats.NOT_ADDITION_COMPATIBLE_MATRICES, getRowDimension(), getColumnDimension(), m.getRowDimension(), m.getColumnDimension()); } } /** * Check if a matrix is subtraction compatible with the instance * @param m matrix to check * @exception IllegalArgumentException if matrix is not subtraction compatible with instance */ protected void checkSubtractionCompatible(final FieldMatrix<T> m) { if ((getRowDimension() != m.getRowDimension()) || (getColumnDimension() != m.getColumnDimension())) { throw MathRuntimeException.createIllegalArgumentException( LocalizedFormats.NOT_SUBTRACTION_COMPATIBLE_MATRICES, getRowDimension(), getColumnDimension(), m.getRowDimension(), m.getColumnDimension()); } } /** * Check if a matrix is multiplication compatible with the instance * @param m matrix to check * @exception IllegalArgumentException if matrix is not multiplication compatible with instance */ protected void checkMultiplicationCompatible(final FieldMatrix<T> m) { if (getColumnDimension() != m.getRowDimension()) { throw MathRuntimeException.createIllegalArgumentException( LocalizedFormats.NOT_MULTIPLICATION_COMPATIBLE_MATRICES, getRowDimension(), getColumnDimension(), m.getRowDimension(), m.getColumnDimension()); } } }