Home | History | Annotate | Download | only in linear
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 package org.apache.commons.math.linear;
     19 
     20 import java.lang.reflect.Array;
     21 import java.util.Arrays;
     22 
     23 import org.apache.commons.math.Field;
     24 import org.apache.commons.math.FieldElement;
     25 import org.apache.commons.math.MathRuntimeException;
     26 import org.apache.commons.math.linear.MatrixVisitorException;
     27 import org.apache.commons.math.exception.util.LocalizedFormats;
     28 
     29 /**
     30  * Basic implementation of {@link FieldMatrix} methods regardless of the underlying storage.
     31  * <p>All the methods implemented here use {@link #getEntry(int, int)} to access
     32  * matrix elements. Derived class can provide faster implementations. </p>
     33  *
     34  * @param <T> the type of the field elements
     35  * @version $Revision: 1073158 $ $Date: 2011-02-21 22:46:52 +0100 (lun. 21 fvr. 2011) $
     36  * @since 2.0
     37  */
     38 public abstract class AbstractFieldMatrix<T extends FieldElement<T>> implements FieldMatrix<T> {
     39 
     40     /** Field to which the elements belong. */
     41     private final Field<T> field;
     42 
     43     /**
     44      * Constructor for use with Serializable
     45      */
     46     protected AbstractFieldMatrix() {
     47         field = null;
     48     }
     49 
     50     /**
     51      * Creates a matrix with no data
     52      * @param field field to which the elements belong
     53      */
     54     protected AbstractFieldMatrix(final Field<T> field) {
     55         this.field = field;
     56     }
     57 
     58     /**
     59      * Create a new FieldMatrix<T> with the supplied row and column dimensions.
     60      *
     61      * @param field field to which the elements belong
     62      * @param rowDimension  the number of rows in the new matrix
     63      * @param columnDimension  the number of columns in the new matrix
     64      * @throws IllegalArgumentException if row or column dimension is not positive
     65      */
     66     protected AbstractFieldMatrix(final Field<T> field,
     67                                   final int rowDimension, final int columnDimension)
     68         throws IllegalArgumentException {
     69         if (rowDimension < 1 ) {
     70             throw MathRuntimeException.createIllegalArgumentException(
     71                     LocalizedFormats.INSUFFICIENT_DIMENSION, rowDimension, 1);
     72         }
     73         if (columnDimension < 1) {
     74             throw MathRuntimeException.createIllegalArgumentException(
     75                     LocalizedFormats.INSUFFICIENT_DIMENSION, columnDimension, 1);
     76         }
     77         this.field = field;
     78     }
     79 
     80     /**
     81      * Get the elements type from an array.
     82      * @param <T> the type of the field elements
     83      * @param d data array
     84      * @return field to which array elements belong
     85      * @exception IllegalArgumentException if array is empty
     86      */
     87     protected static <T extends FieldElement<T>> Field<T> extractField(final T[][] d)
     88         throws IllegalArgumentException {
     89         if (d.length == 0) {
     90             throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_ROW);
     91         }
     92         if (d[0].length == 0) {
     93             throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_COLUMN);
     94         }
     95         return d[0][0].getField();
     96     }
     97 
     98     /**
     99      * Get the elements type from an array.
    100      * @param <T> the type of the field elements
    101      * @param d data array
    102      * @return field to which array elements belong
    103      * @exception IllegalArgumentException if array is empty
    104      */
    105     protected static <T extends FieldElement<T>> Field<T> extractField(final T[] d)
    106         throws IllegalArgumentException {
    107         if (d.length == 0) {
    108             throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_ROW);
    109         }
    110         return d[0].getField();
    111     }
    112 
    113     /** Build an array of elements.
    114      * <p>
    115      * Complete arrays are filled with field.getZero()
    116      * </p>
    117      * @param <T> the type of the field elements
    118      * @param field field to which array elements belong
    119      * @param rows number of rows
    120      * @param columns number of columns (may be negative to build partial
    121      * arrays in the same way <code>new Field[rows][]</code> works)
    122      * @return a new array
    123      */
    124     @SuppressWarnings("unchecked")
    125     protected static <T extends FieldElement<T>> T[][] buildArray(final Field<T> field,
    126                                                                   final int rows,
    127                                                                   final int columns) {
    128         if (columns < 0) {
    129             T[] dummyRow = (T[]) Array.newInstance(field.getZero().getClass(), 0);
    130             return (T[][]) Array.newInstance(dummyRow.getClass(), rows);
    131         }
    132         T[][] array =
    133             (T[][]) Array.newInstance(field.getZero().getClass(), new int[] { rows, columns });
    134         for (int i = 0; i < array.length; ++i) {
    135             Arrays.fill(array[i], field.getZero());
    136         }
    137         return array;
    138     }
    139 
    140     /** Build an array of elements.
    141      * <p>
    142      * Arrays are filled with field.getZero()
    143      * </p>
    144      * @param <T> the type of the field elements
    145      * @param field field to which array elements belong
    146      * @param length of the array
    147      * @return a new array
    148      */
    149     protected static <T extends FieldElement<T>> T[] buildArray(final Field<T> field,
    150                                                                 final int length) {
    151         @SuppressWarnings("unchecked") // OK because field must be correct class
    152         T[] array = (T[]) Array.newInstance(field.getZero().getClass(), length);
    153         Arrays.fill(array, field.getZero());
    154         return array;
    155     }
    156 
    157     /** {@inheritDoc} */
    158     public Field<T> getField() {
    159         return field;
    160     }
    161 
    162     /** {@inheritDoc} */
    163     public abstract FieldMatrix<T> createMatrix(final int rowDimension, final int columnDimension)
    164         throws IllegalArgumentException;
    165 
    166     /** {@inheritDoc} */
    167     public abstract FieldMatrix<T> copy();
    168 
    169     /** {@inheritDoc} */
    170     public FieldMatrix<T> add(FieldMatrix<T> m) throws IllegalArgumentException {
    171 
    172         // safety check
    173         checkAdditionCompatible(m);
    174 
    175         final int rowCount    = getRowDimension();
    176         final int columnCount = getColumnDimension();
    177         final FieldMatrix<T> out = createMatrix(rowCount, columnCount);
    178         for (int row = 0; row < rowCount; ++row) {
    179             for (int col = 0; col < columnCount; ++col) {
    180                 out.setEntry(row, col, getEntry(row, col).add(m.getEntry(row, col)));
    181             }
    182         }
    183 
    184         return out;
    185 
    186     }
    187 
    188     /** {@inheritDoc} */
    189     public FieldMatrix<T> subtract(final FieldMatrix<T> m) throws IllegalArgumentException {
    190 
    191         // safety check
    192         checkSubtractionCompatible(m);
    193 
    194         final int rowCount    = getRowDimension();
    195         final int columnCount = getColumnDimension();
    196         final FieldMatrix<T> out = createMatrix(rowCount, columnCount);
    197         for (int row = 0; row < rowCount; ++row) {
    198             for (int col = 0; col < columnCount; ++col) {
    199                 out.setEntry(row, col, getEntry(row, col).subtract(m.getEntry(row, col)));
    200             }
    201         }
    202 
    203         return out;
    204 
    205     }
    206 
    207     /** {@inheritDoc} */
    208     public FieldMatrix<T> scalarAdd(final T d) {
    209 
    210         final int rowCount    = getRowDimension();
    211         final int columnCount = getColumnDimension();
    212         final FieldMatrix<T> out = createMatrix(rowCount, columnCount);
    213         for (int row = 0; row < rowCount; ++row) {
    214             for (int col = 0; col < columnCount; ++col) {
    215                 out.setEntry(row, col, getEntry(row, col).add(d));
    216             }
    217         }
    218 
    219         return out;
    220 
    221     }
    222 
    223     /** {@inheritDoc} */
    224     public FieldMatrix<T> scalarMultiply(final T d) {
    225 
    226         final int rowCount    = getRowDimension();
    227         final int columnCount = getColumnDimension();
    228         final FieldMatrix<T> out = createMatrix(rowCount, columnCount);
    229         for (int row = 0; row < rowCount; ++row) {
    230             for (int col = 0; col < columnCount; ++col) {
    231                 out.setEntry(row, col, getEntry(row, col).multiply(d));
    232             }
    233         }
    234 
    235         return out;
    236 
    237     }
    238 
    239     /** {@inheritDoc} */
    240     public FieldMatrix<T> multiply(final FieldMatrix<T> m)
    241         throws IllegalArgumentException {
    242 
    243         // safety check
    244         checkMultiplicationCompatible(m);
    245 
    246         final int nRows = getRowDimension();
    247         final int nCols = m.getColumnDimension();
    248         final int nSum  = getColumnDimension();
    249         final FieldMatrix<T> out = createMatrix(nRows, nCols);
    250         for (int row = 0; row < nRows; ++row) {
    251             for (int col = 0; col < nCols; ++col) {
    252                 T sum = field.getZero();
    253                 for (int i = 0; i < nSum; ++i) {
    254                     sum = sum.add(getEntry(row, i).multiply(m.getEntry(i, col)));
    255                 }
    256                 out.setEntry(row, col, sum);
    257             }
    258         }
    259 
    260         return out;
    261 
    262     }
    263 
    264     /** {@inheritDoc} */
    265     public FieldMatrix<T> preMultiply(final FieldMatrix<T> m)
    266         throws IllegalArgumentException {
    267         return m.multiply(this);
    268     }
    269 
    270     /** {@inheritDoc} */
    271     public T[][] getData() {
    272 
    273         final T[][] data = buildArray(field, getRowDimension(), getColumnDimension());
    274 
    275         for (int i = 0; i < data.length; ++i) {
    276             final T[] dataI = data[i];
    277             for (int j = 0; j < dataI.length; ++j) {
    278                 dataI[j] = getEntry(i, j);
    279             }
    280         }
    281 
    282         return data;
    283 
    284     }
    285 
    286     /** {@inheritDoc} */
    287     public FieldMatrix<T> getSubMatrix(final int startRow, final int endRow,
    288                                    final int startColumn, final int endColumn)
    289         throws MatrixIndexException {
    290 
    291         checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
    292 
    293         final FieldMatrix<T> subMatrix =
    294             createMatrix(endRow - startRow + 1, endColumn - startColumn + 1);
    295         for (int i = startRow; i <= endRow; ++i) {
    296             for (int j = startColumn; j <= endColumn; ++j) {
    297                 subMatrix.setEntry(i - startRow, j - startColumn, getEntry(i, j));
    298             }
    299         }
    300 
    301         return subMatrix;
    302 
    303     }
    304 
    305     /** {@inheritDoc} */
    306     public FieldMatrix<T> getSubMatrix(final int[] selectedRows, final int[] selectedColumns)
    307         throws MatrixIndexException {
    308 
    309         // safety checks
    310         checkSubMatrixIndex(selectedRows, selectedColumns);
    311 
    312         // copy entries
    313         final FieldMatrix<T> subMatrix =
    314             createMatrix(selectedRows.length, selectedColumns.length);
    315         subMatrix.walkInOptimizedOrder(new DefaultFieldMatrixChangingVisitor<T>(field.getZero()) {
    316 
    317             /** {@inheritDoc} */
    318             @Override
    319             public T visit(final int row, final int column, final T value) {
    320                 return getEntry(selectedRows[row], selectedColumns[column]);
    321             }
    322 
    323         });
    324 
    325         return subMatrix;
    326 
    327     }
    328 
    329     /** {@inheritDoc} */
    330     public void copySubMatrix(final int startRow, final int endRow,
    331                               final int startColumn, final int endColumn,
    332                               final T[][] destination)
    333         throws MatrixIndexException, IllegalArgumentException {
    334 
    335         // safety checks
    336         checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
    337         final int rowsCount    = endRow + 1 - startRow;
    338         final int columnsCount = endColumn + 1 - startColumn;
    339         if ((destination.length < rowsCount) || (destination[0].length < columnsCount)) {
    340             throw MathRuntimeException.createIllegalArgumentException(
    341                     LocalizedFormats.DIMENSIONS_MISMATCH_2x2,
    342                     destination.length, destination[0].length,
    343                     rowsCount, columnsCount);
    344         }
    345 
    346         // copy entries
    347         walkInOptimizedOrder(new DefaultFieldMatrixPreservingVisitor<T>(field.getZero()) {
    348 
    349             /** Initial row index. */
    350             private int startRow;
    351 
    352             /** Initial column index. */
    353             private int startColumn;
    354 
    355             /** {@inheritDoc} */
    356             @Override
    357             public void start(final int rows, final int columns,
    358                               final int startRow, final int endRow,
    359                               final int startColumn, final int endColumn) {
    360                 this.startRow    = startRow;
    361                 this.startColumn = startColumn;
    362             }
    363 
    364             /** {@inheritDoc} */
    365             @Override
    366             public void visit(final int row, final int column, final T value) {
    367                 destination[row - startRow][column - startColumn] = value;
    368             }
    369 
    370         }, startRow, endRow, startColumn, endColumn);
    371 
    372     }
    373 
    374     /** {@inheritDoc} */
    375     public void copySubMatrix(int[] selectedRows, int[] selectedColumns, T[][] destination)
    376         throws MatrixIndexException, IllegalArgumentException {
    377 
    378         // safety checks
    379         checkSubMatrixIndex(selectedRows, selectedColumns);
    380         if ((destination.length < selectedRows.length) ||
    381             (destination[0].length < selectedColumns.length)) {
    382             throw MathRuntimeException.createIllegalArgumentException(
    383                     LocalizedFormats.DIMENSIONS_MISMATCH_2x2,
    384                     destination.length, destination[0].length,
    385                     selectedRows.length, selectedColumns.length);
    386         }
    387 
    388         // copy entries
    389         for (int i = 0; i < selectedRows.length; i++) {
    390             final T[] destinationI = destination[i];
    391             for (int j = 0; j < selectedColumns.length; j++) {
    392                 destinationI[j] = getEntry(selectedRows[i], selectedColumns[j]);
    393             }
    394         }
    395 
    396     }
    397 
    398     /** {@inheritDoc} */
    399     public void setSubMatrix(final T[][] subMatrix, final int row, final int column)
    400         throws MatrixIndexException {
    401 
    402         final int nRows = subMatrix.length;
    403         if (nRows == 0) {
    404             throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_ROW);
    405         }
    406 
    407         final int nCols = subMatrix[0].length;
    408         if (nCols == 0) {
    409             throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_COLUMN);
    410         }
    411 
    412         for (int r = 1; r < nRows; ++r) {
    413             if (subMatrix[r].length != nCols) {
    414                 throw MathRuntimeException.createIllegalArgumentException(
    415                         LocalizedFormats.DIFFERENT_ROWS_LENGTHS,
    416                         nCols, subMatrix[r].length);
    417             }
    418         }
    419 
    420         checkRowIndex(row);
    421         checkColumnIndex(column);
    422         checkRowIndex(nRows + row - 1);
    423         checkColumnIndex(nCols + column - 1);
    424 
    425         for (int i = 0; i < nRows; ++i) {
    426             for (int j = 0; j < nCols; ++j) {
    427                 setEntry(row + i, column + j, subMatrix[i][j]);
    428             }
    429         }
    430 
    431     }
    432 
    433     /** {@inheritDoc} */
    434     public FieldMatrix<T> getRowMatrix(final int row)
    435         throws MatrixIndexException {
    436 
    437         checkRowIndex(row);
    438         final int nCols = getColumnDimension();
    439         final FieldMatrix<T> out = createMatrix(1, nCols);
    440         for (int i = 0; i < nCols; ++i) {
    441             out.setEntry(0, i, getEntry(row, i));
    442         }
    443 
    444         return out;
    445 
    446     }
    447 
    448     /** {@inheritDoc} */
    449     public void setRowMatrix(final int row, final FieldMatrix<T> matrix)
    450         throws MatrixIndexException, InvalidMatrixException {
    451 
    452         checkRowIndex(row);
    453         final int nCols = getColumnDimension();
    454         if ((matrix.getRowDimension() != 1) ||
    455             (matrix.getColumnDimension() != nCols)) {
    456             throw new InvalidMatrixException(
    457                     LocalizedFormats.DIMENSIONS_MISMATCH_2x2,
    458                     matrix.getRowDimension(), matrix.getColumnDimension(), 1, nCols);
    459         }
    460         for (int i = 0; i < nCols; ++i) {
    461             setEntry(row, i, matrix.getEntry(0, i));
    462         }
    463 
    464     }
    465 
    466     /** {@inheritDoc} */
    467     public FieldMatrix<T> getColumnMatrix(final int column)
    468         throws MatrixIndexException {
    469 
    470         checkColumnIndex(column);
    471         final int nRows = getRowDimension();
    472         final FieldMatrix<T> out = createMatrix(nRows, 1);
    473         for (int i = 0; i < nRows; ++i) {
    474             out.setEntry(i, 0, getEntry(i, column));
    475         }
    476 
    477         return out;
    478 
    479     }
    480 
    481     /** {@inheritDoc} */
    482     public void setColumnMatrix(final int column, final FieldMatrix<T> matrix)
    483         throws MatrixIndexException, InvalidMatrixException {
    484 
    485         checkColumnIndex(column);
    486         final int nRows = getRowDimension();
    487         if ((matrix.getRowDimension() != nRows) ||
    488             (matrix.getColumnDimension() != 1)) {
    489             throw new InvalidMatrixException(
    490                     LocalizedFormats.DIMENSIONS_MISMATCH_2x2,
    491                     matrix.getRowDimension(), matrix.getColumnDimension(), nRows, 1);
    492         }
    493         for (int i = 0; i < nRows; ++i) {
    494             setEntry(i, column, matrix.getEntry(i, 0));
    495         }
    496 
    497     }
    498 
    499     /** {@inheritDoc} */
    500     public FieldVector<T> getRowVector(final int row)
    501         throws MatrixIndexException {
    502         return new ArrayFieldVector<T>(getRow(row), false);
    503     }
    504 
    505     /** {@inheritDoc} */
    506     public void setRowVector(final int row, final FieldVector<T> vector)
    507         throws MatrixIndexException, InvalidMatrixException {
    508 
    509         checkRowIndex(row);
    510         final int nCols = getColumnDimension();
    511         if (vector.getDimension() != nCols) {
    512             throw new InvalidMatrixException(
    513                     LocalizedFormats.DIMENSIONS_MISMATCH_2x2,
    514                     1, vector.getDimension(), 1, nCols);
    515         }
    516         for (int i = 0; i < nCols; ++i) {
    517             setEntry(row, i, vector.getEntry(i));
    518         }
    519 
    520     }
    521 
    522     /** {@inheritDoc} */
    523     public FieldVector<T> getColumnVector(final int column)
    524         throws MatrixIndexException {
    525         return new ArrayFieldVector<T>(getColumn(column), false);
    526     }
    527 
    528     /** {@inheritDoc} */
    529     public void setColumnVector(final int column, final FieldVector<T> vector)
    530         throws MatrixIndexException, InvalidMatrixException {
    531 
    532         checkColumnIndex(column);
    533         final int nRows = getRowDimension();
    534         if (vector.getDimension() != nRows) {
    535             throw new InvalidMatrixException(
    536                     LocalizedFormats.DIMENSIONS_MISMATCH_2x2,
    537                     vector.getDimension(), 1, nRows, 1);
    538         }
    539         for (int i = 0; i < nRows; ++i) {
    540             setEntry(i, column, vector.getEntry(i));
    541         }
    542 
    543     }
    544 
    545     /** {@inheritDoc} */
    546     public T[] getRow(final int row)
    547         throws MatrixIndexException {
    548 
    549         checkRowIndex(row);
    550         final int nCols = getColumnDimension();
    551         final T[] out = buildArray(field, nCols);
    552         for (int i = 0; i < nCols; ++i) {
    553             out[i] = getEntry(row, i);
    554         }
    555 
    556         return out;
    557 
    558     }
    559 
    560     /** {@inheritDoc} */
    561     public void setRow(final int row, final T[] array)
    562         throws MatrixIndexException, InvalidMatrixException {
    563 
    564         checkRowIndex(row);
    565         final int nCols = getColumnDimension();
    566         if (array.length != nCols) {
    567             throw new InvalidMatrixException(
    568                     LocalizedFormats.DIMENSIONS_MISMATCH_2x2,
    569                     1, array.length, 1, nCols);
    570         }
    571         for (int i = 0; i < nCols; ++i) {
    572             setEntry(row, i, array[i]);
    573         }
    574 
    575     }
    576 
    577     /** {@inheritDoc} */
    578     public T[] getColumn(final int column)
    579         throws MatrixIndexException {
    580 
    581         checkColumnIndex(column);
    582         final int nRows = getRowDimension();
    583         final T[] out = buildArray(field, nRows);
    584         for (int i = 0; i < nRows; ++i) {
    585             out[i] = getEntry(i, column);
    586         }
    587 
    588         return out;
    589 
    590     }
    591 
    592     /** {@inheritDoc} */
    593     public void setColumn(final int column, final T[] array)
    594         throws MatrixIndexException, InvalidMatrixException {
    595 
    596         checkColumnIndex(column);
    597         final int nRows = getRowDimension();
    598         if (array.length != nRows) {
    599             throw new InvalidMatrixException(
    600                     LocalizedFormats.DIMENSIONS_MISMATCH_2x2,
    601                     array.length, 1, nRows, 1);
    602         }
    603         for (int i = 0; i < nRows; ++i) {
    604             setEntry(i, column, array[i]);
    605         }
    606 
    607     }
    608 
    609     /** {@inheritDoc} */
    610     public abstract T getEntry(int row, int column)
    611         throws MatrixIndexException;
    612 
    613     /** {@inheritDoc} */
    614     public abstract void setEntry(int row, int column, T value)
    615         throws MatrixIndexException;
    616 
    617     /** {@inheritDoc} */
    618     public abstract void addToEntry(int row, int column, T increment)
    619         throws MatrixIndexException;
    620 
    621     /** {@inheritDoc} */
    622     public abstract void multiplyEntry(int row, int column, T factor)
    623         throws MatrixIndexException;
    624 
    625     /** {@inheritDoc} */
    626     public FieldMatrix<T> transpose() {
    627 
    628         final int nRows = getRowDimension();
    629         final int nCols = getColumnDimension();
    630         final FieldMatrix<T> out = createMatrix(nCols, nRows);
    631         walkInOptimizedOrder(new DefaultFieldMatrixPreservingVisitor<T>(field.getZero()) {
    632 
    633             /** {@inheritDoc} */
    634             @Override
    635             public void visit(final int row, final int column, final T value) {
    636                 out.setEntry(column, row, value);
    637             }
    638 
    639         });
    640 
    641         return out;
    642 
    643     }
    644 
    645     /** {@inheritDoc} */
    646     public boolean isSquare() {
    647         return getColumnDimension() == getRowDimension();
    648     }
    649 
    650     /** {@inheritDoc} */
    651     public abstract int getRowDimension();
    652 
    653     /** {@inheritDoc} */
    654     public abstract int getColumnDimension();
    655 
    656     /** {@inheritDoc} */
    657     public T getTrace()
    658         throws NonSquareMatrixException {
    659         final int nRows = getRowDimension();
    660         final int nCols = getColumnDimension();
    661         if (nRows != nCols) {
    662             throw new NonSquareMatrixException(nRows, nCols);
    663        }
    664         T trace = field.getZero();
    665         for (int i = 0; i < nRows; ++i) {
    666             trace = trace.add(getEntry(i, i));
    667         }
    668         return trace;
    669     }
    670 
    671     /** {@inheritDoc} */
    672     public T[] operate(final T[] v)
    673         throws IllegalArgumentException {
    674 
    675         final int nRows = getRowDimension();
    676         final int nCols = getColumnDimension();
    677         if (v.length != nCols) {
    678             throw MathRuntimeException.createIllegalArgumentException(
    679                     LocalizedFormats.VECTOR_LENGTH_MISMATCH,
    680                     v.length, nCols);
    681         }
    682 
    683         final T[] out = buildArray(field, nRows);
    684         for (int row = 0; row < nRows; ++row) {
    685             T sum = field.getZero();
    686             for (int i = 0; i < nCols; ++i) {
    687                 sum = sum.add(getEntry(row, i).multiply(v[i]));
    688             }
    689             out[row] = sum;
    690         }
    691 
    692         return out;
    693 
    694     }
    695 
    696     /** {@inheritDoc} */
    697     public FieldVector<T> operate(final FieldVector<T> v)
    698         throws IllegalArgumentException {
    699         try {
    700             return new ArrayFieldVector<T>(operate(((ArrayFieldVector<T>) v).getDataRef()), false);
    701         } catch (ClassCastException cce) {
    702             final int nRows = getRowDimension();
    703             final int nCols = getColumnDimension();
    704             if (v.getDimension() != nCols) {
    705                 throw MathRuntimeException.createIllegalArgumentException(
    706                         LocalizedFormats.VECTOR_LENGTH_MISMATCH,
    707                         v.getDimension(), nCols);
    708             }
    709 
    710             final T[] out = buildArray(field, nRows);
    711             for (int row = 0; row < nRows; ++row) {
    712                 T sum = field.getZero();
    713                 for (int i = 0; i < nCols; ++i) {
    714                     sum = sum.add(getEntry(row, i).multiply(v.getEntry(i)));
    715                 }
    716                 out[row] = sum;
    717             }
    718 
    719             return new ArrayFieldVector<T>(out, false);
    720         }
    721     }
    722 
    723     /** {@inheritDoc} */
    724     public T[] preMultiply(final T[] v)
    725         throws IllegalArgumentException {
    726 
    727         final int nRows = getRowDimension();
    728         final int nCols = getColumnDimension();
    729         if (v.length != nRows) {
    730             throw MathRuntimeException.createIllegalArgumentException(
    731                     LocalizedFormats.VECTOR_LENGTH_MISMATCH,
    732                     v.length, nRows);
    733         }
    734 
    735         final T[] out = buildArray(field, nCols);
    736         for (int col = 0; col < nCols; ++col) {
    737             T sum = field.getZero();
    738             for (int i = 0; i < nRows; ++i) {
    739                 sum = sum.add(getEntry(i, col).multiply(v[i]));
    740             }
    741             out[col] = sum;
    742         }
    743 
    744         return out;
    745 
    746     }
    747 
    748     /** {@inheritDoc} */
    749     public FieldVector<T> preMultiply(final FieldVector<T> v)
    750         throws IllegalArgumentException {
    751         try {
    752             return new ArrayFieldVector<T>(preMultiply(((ArrayFieldVector<T>) v).getDataRef()), false);
    753         } catch (ClassCastException cce) {
    754 
    755             final int nRows = getRowDimension();
    756             final int nCols = getColumnDimension();
    757             if (v.getDimension() != nRows) {
    758                 throw MathRuntimeException.createIllegalArgumentException(
    759                         LocalizedFormats.VECTOR_LENGTH_MISMATCH,
    760                         v.getDimension(), nRows);
    761             }
    762 
    763             final T[] out = buildArray(field, nCols);
    764             for (int col = 0; col < nCols; ++col) {
    765                 T sum = field.getZero();
    766                 for (int i = 0; i < nRows; ++i) {
    767                     sum = sum.add(getEntry(i, col).multiply(v.getEntry(i)));
    768                 }
    769                 out[col] = sum;
    770             }
    771 
    772             return new ArrayFieldVector<T>(out);
    773 
    774         }
    775     }
    776 
    777     /** {@inheritDoc} */
    778     public T walkInRowOrder(final FieldMatrixChangingVisitor<T> visitor)
    779         throws MatrixVisitorException {
    780         final int rows    = getRowDimension();
    781         final int columns = getColumnDimension();
    782         visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
    783         for (int row = 0; row < rows; ++row) {
    784             for (int column = 0; column < columns; ++column) {
    785                 final T oldValue = getEntry(row, column);
    786                 final T newValue = visitor.visit(row, column, oldValue);
    787                 setEntry(row, column, newValue);
    788             }
    789         }
    790         return visitor.end();
    791     }
    792 
    793     /** {@inheritDoc} */
    794     public T walkInRowOrder(final FieldMatrixPreservingVisitor<T> visitor)
    795         throws MatrixVisitorException {
    796         final int rows    = getRowDimension();
    797         final int columns = getColumnDimension();
    798         visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
    799         for (int row = 0; row < rows; ++row) {
    800             for (int column = 0; column < columns; ++column) {
    801                 visitor.visit(row, column, getEntry(row, column));
    802             }
    803         }
    804         return visitor.end();
    805     }
    806 
    807     /** {@inheritDoc} */
    808     public T walkInRowOrder(final FieldMatrixChangingVisitor<T> visitor,
    809                             final int startRow, final int endRow,
    810                             final int startColumn, final int endColumn)
    811         throws MatrixIndexException, MatrixVisitorException {
    812         checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
    813         visitor.start(getRowDimension(), getColumnDimension(),
    814                       startRow, endRow, startColumn, endColumn);
    815         for (int row = startRow; row <= endRow; ++row) {
    816             for (int column = startColumn; column <= endColumn; ++column) {
    817                 final T oldValue = getEntry(row, column);
    818                 final T newValue = visitor.visit(row, column, oldValue);
    819                 setEntry(row, column, newValue);
    820             }
    821         }
    822         return visitor.end();
    823     }
    824 
    825     /** {@inheritDoc} */
    826     public T walkInRowOrder(final FieldMatrixPreservingVisitor<T> visitor,
    827                                  final int startRow, final int endRow,
    828                                  final int startColumn, final int endColumn)
    829         throws MatrixIndexException, MatrixVisitorException {
    830         checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
    831         visitor.start(getRowDimension(), getColumnDimension(),
    832                       startRow, endRow, startColumn, endColumn);
    833         for (int row = startRow; row <= endRow; ++row) {
    834             for (int column = startColumn; column <= endColumn; ++column) {
    835                 visitor.visit(row, column, getEntry(row, column));
    836             }
    837         }
    838         return visitor.end();
    839     }
    840 
    841     /** {@inheritDoc} */
    842     public T walkInColumnOrder(final FieldMatrixChangingVisitor<T> visitor)
    843         throws MatrixVisitorException {
    844         final int rows    = getRowDimension();
    845         final int columns = getColumnDimension();
    846         visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
    847         for (int column = 0; column < columns; ++column) {
    848             for (int row = 0; row < rows; ++row) {
    849                 final T oldValue = getEntry(row, column);
    850                 final T newValue = visitor.visit(row, column, oldValue);
    851                 setEntry(row, column, newValue);
    852             }
    853         }
    854         return visitor.end();
    855     }
    856 
    857     /** {@inheritDoc} */
    858     public T walkInColumnOrder(final FieldMatrixPreservingVisitor<T> visitor)
    859         throws MatrixVisitorException {
    860         final int rows    = getRowDimension();
    861         final int columns = getColumnDimension();
    862         visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
    863         for (int column = 0; column < columns; ++column) {
    864             for (int row = 0; row < rows; ++row) {
    865                 visitor.visit(row, column, getEntry(row, column));
    866             }
    867         }
    868         return visitor.end();
    869     }
    870 
    871     /** {@inheritDoc} */
    872     public T walkInColumnOrder(final FieldMatrixChangingVisitor<T> visitor,
    873                                final int startRow, final int endRow,
    874                                final int startColumn, final int endColumn)
    875     throws MatrixIndexException, MatrixVisitorException {
    876         checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
    877         visitor.start(getRowDimension(), getColumnDimension(),
    878                       startRow, endRow, startColumn, endColumn);
    879         for (int column = startColumn; column <= endColumn; ++column) {
    880             for (int row = startRow; row <= endRow; ++row) {
    881                 final T oldValue = getEntry(row, column);
    882                 final T newValue = visitor.visit(row, column, oldValue);
    883                 setEntry(row, column, newValue);
    884             }
    885         }
    886         return visitor.end();
    887     }
    888 
    889     /** {@inheritDoc} */
    890     public T walkInColumnOrder(final FieldMatrixPreservingVisitor<T> visitor,
    891                                final int startRow, final int endRow,
    892                                final int startColumn, final int endColumn)
    893     throws MatrixIndexException, MatrixVisitorException {
    894         checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
    895         visitor.start(getRowDimension(), getColumnDimension(),
    896                       startRow, endRow, startColumn, endColumn);
    897         for (int column = startColumn; column <= endColumn; ++column) {
    898             for (int row = startRow; row <= endRow; ++row) {
    899                 visitor.visit(row, column, getEntry(row, column));
    900             }
    901         }
    902         return visitor.end();
    903     }
    904 
    905     /** {@inheritDoc} */
    906     public T walkInOptimizedOrder(final FieldMatrixChangingVisitor<T> visitor)
    907         throws MatrixVisitorException {
    908         return walkInRowOrder(visitor);
    909     }
    910 
    911     /** {@inheritDoc} */
    912     public T walkInOptimizedOrder(final FieldMatrixPreservingVisitor<T> visitor)
    913         throws MatrixVisitorException {
    914         return walkInRowOrder(visitor);
    915     }
    916 
    917     /** {@inheritDoc} */
    918     public T walkInOptimizedOrder(final FieldMatrixChangingVisitor<T> visitor,
    919                                        final int startRow, final int endRow,
    920                                        final int startColumn, final int endColumn)
    921         throws MatrixIndexException, MatrixVisitorException {
    922         return walkInRowOrder(visitor, startRow, endRow, startColumn, endColumn);
    923     }
    924 
    925     /** {@inheritDoc} */
    926     public T walkInOptimizedOrder(final FieldMatrixPreservingVisitor<T> visitor,
    927                                        final int startRow, final int endRow,
    928                                        final int startColumn, final int endColumn)
    929         throws MatrixIndexException, MatrixVisitorException {
    930         return walkInRowOrder(visitor, startRow, endRow, startColumn, endColumn);
    931     }
    932 
    933     /**
    934      * Get a string representation for this matrix.
    935      * @return a string representation for this matrix
    936      */
    937     @Override
    938     public String toString() {
    939         final int nRows = getRowDimension();
    940         final int nCols = getColumnDimension();
    941         final StringBuilder res = new StringBuilder();
    942         String fullClassName = getClass().getName();
    943         String shortClassName = fullClassName.substring(fullClassName.lastIndexOf('.') + 1);
    944         res.append(shortClassName).append("{");
    945 
    946         for (int i = 0; i < nRows; ++i) {
    947             if (i > 0) {
    948                 res.append(",");
    949             }
    950             res.append("{");
    951             for (int j = 0; j < nCols; ++j) {
    952                 if (j > 0) {
    953                     res.append(",");
    954                 }
    955                 res.append(getEntry(i, j));
    956             }
    957             res.append("}");
    958         }
    959 
    960         res.append("}");
    961         return res.toString();
    962 
    963     }
    964 
    965     /**
    966      * Returns true iff <code>object</code> is a
    967      * <code>FieldMatrix</code> instance with the same dimensions as this
    968      * and all corresponding matrix entries are equal.
    969      *
    970      * @param object the object to test equality against.
    971      * @return true if object equals this
    972      */
    973     @Override
    974     public boolean equals(final Object object) {
    975         if (object == this ) {
    976             return true;
    977         }
    978         if (object instanceof FieldMatrix<?> == false) {
    979             return false;
    980         }
    981         FieldMatrix<?> m = (FieldMatrix<?>) object;
    982         final int nRows = getRowDimension();
    983         final int nCols = getColumnDimension();
    984         if (m.getColumnDimension() != nCols || m.getRowDimension() != nRows) {
    985             return false;
    986         }
    987         for (int row = 0; row < nRows; ++row) {
    988             for (int col = 0; col < nCols; ++col) {
    989                 if (!getEntry(row, col).equals(m.getEntry(row, col))) {
    990                     return false;
    991                 }
    992             }
    993         }
    994         return true;
    995     }
    996 
    997     /**
    998      * Computes a hashcode for the matrix.
    999      *
   1000      * @return hashcode for matrix
   1001      */
   1002     @Override
   1003     public int hashCode() {
   1004         int ret = 322562;
   1005         final int nRows = getRowDimension();
   1006         final int nCols = getColumnDimension();
   1007         ret = ret * 31 + nRows;
   1008         ret = ret * 31 + nCols;
   1009         for (int row = 0; row < nRows; ++row) {
   1010             for (int col = 0; col < nCols; ++col) {
   1011                ret = ret * 31 + (11 * (row+1) + 17 * (col+1)) * getEntry(row, col).hashCode();
   1012            }
   1013         }
   1014         return ret;
   1015     }
   1016 
   1017     /**
   1018      * Check if a row index is valid.
   1019      * @param row row index to check
   1020      * @exception MatrixIndexException if index is not valid
   1021      */
   1022     protected void checkRowIndex(final int row) {
   1023         if (row < 0 || row >= getRowDimension()) {
   1024             throw new MatrixIndexException(LocalizedFormats.ROW_INDEX_OUT_OF_RANGE,
   1025                                            row, 0, getRowDimension() - 1);
   1026         }
   1027     }
   1028 
   1029     /**
   1030      * Check if a column index is valid.
   1031      * @param column column index to check
   1032      * @exception MatrixIndexException if index is not valid
   1033      */
   1034     protected void checkColumnIndex(final int column)
   1035         throws MatrixIndexException {
   1036         if (column < 0 || column >= getColumnDimension()) {
   1037             throw new MatrixIndexException(LocalizedFormats.COLUMN_INDEX_OUT_OF_RANGE,
   1038                                            column, 0, getColumnDimension() - 1);
   1039         }
   1040     }
   1041 
   1042     /**
   1043      * Check if submatrix ranges indices are valid.
   1044      * Rows and columns are indicated counting from 0 to n-1.
   1045      *
   1046      * @param startRow Initial row index
   1047      * @param endRow Final row index
   1048      * @param startColumn Initial column index
   1049      * @param endColumn Final column index
   1050      * @exception MatrixIndexException  if the indices are not valid
   1051      */
   1052     protected void checkSubMatrixIndex(final int startRow, final int endRow,
   1053                                        final int startColumn, final int endColumn) {
   1054         checkRowIndex(startRow);
   1055         checkRowIndex(endRow);
   1056         if (startRow > endRow) {
   1057             throw new MatrixIndexException(LocalizedFormats.INITIAL_ROW_AFTER_FINAL_ROW,
   1058                                            startRow, endRow);
   1059         }
   1060 
   1061         checkColumnIndex(startColumn);
   1062         checkColumnIndex(endColumn);
   1063         if (startColumn > endColumn) {
   1064             throw new MatrixIndexException(LocalizedFormats.INITIAL_COLUMN_AFTER_FINAL_COLUMN,
   1065                                            startColumn, endColumn);
   1066         }
   1067 
   1068 
   1069     }
   1070 
   1071     /**
   1072      * Check if submatrix ranges indices are valid.
   1073      * Rows and columns are indicated counting from 0 to n-1.
   1074      *
   1075      * @param selectedRows Array of row indices.
   1076      * @param selectedColumns Array of column indices.
   1077      * @exception MatrixIndexException if row or column selections are not valid
   1078      */
   1079     protected void checkSubMatrixIndex(final int[] selectedRows, final int[] selectedColumns) {
   1080         if (selectedRows.length * selectedColumns.length == 0) {
   1081             if (selectedRows.length == 0) {
   1082                 throw new MatrixIndexException(LocalizedFormats.EMPTY_SELECTED_ROW_INDEX_ARRAY);
   1083             }
   1084             throw new MatrixIndexException(LocalizedFormats.EMPTY_SELECTED_COLUMN_INDEX_ARRAY);
   1085         }
   1086 
   1087         for (final int row : selectedRows) {
   1088             checkRowIndex(row);
   1089         }
   1090         for (final int column : selectedColumns) {
   1091             checkColumnIndex(column);
   1092         }
   1093     }
   1094 
   1095     /**
   1096      * Check if a matrix is addition compatible with the instance
   1097      * @param m matrix to check
   1098      * @exception IllegalArgumentException if matrix is not addition compatible with instance
   1099      */
   1100     protected void checkAdditionCompatible(final FieldMatrix<T> m) {
   1101         if ((getRowDimension()    != m.getRowDimension()) ||
   1102             (getColumnDimension() != m.getColumnDimension())) {
   1103             throw MathRuntimeException.createIllegalArgumentException(
   1104                     LocalizedFormats.NOT_ADDITION_COMPATIBLE_MATRICES,
   1105                     getRowDimension(), getColumnDimension(),
   1106                     m.getRowDimension(), m.getColumnDimension());
   1107         }
   1108     }
   1109 
   1110     /**
   1111      * Check if a matrix is subtraction compatible with the instance
   1112      * @param m matrix to check
   1113      * @exception IllegalArgumentException if matrix is not subtraction compatible with instance
   1114      */
   1115     protected void checkSubtractionCompatible(final FieldMatrix<T> m) {
   1116         if ((getRowDimension()    != m.getRowDimension()) ||
   1117             (getColumnDimension() != m.getColumnDimension())) {
   1118             throw MathRuntimeException.createIllegalArgumentException(
   1119                     LocalizedFormats.NOT_SUBTRACTION_COMPATIBLE_MATRICES,
   1120                     getRowDimension(), getColumnDimension(),
   1121                     m.getRowDimension(), m.getColumnDimension());
   1122         }
   1123     }
   1124 
   1125     /**
   1126      * Check if a matrix is multiplication compatible with the instance
   1127      * @param m matrix to check
   1128      * @exception IllegalArgumentException if matrix is not multiplication compatible with instance
   1129      */
   1130     protected void checkMultiplicationCompatible(final FieldMatrix<T> m) {
   1131         if (getColumnDimension() != m.getRowDimension()) {
   1132             throw MathRuntimeException.createIllegalArgumentException(
   1133                     LocalizedFormats.NOT_MULTIPLICATION_COMPATIBLE_MATRICES,
   1134                     getRowDimension(), getColumnDimension(),
   1135                     m.getRowDimension(), m.getColumnDimension());
   1136         }
   1137     }
   1138 
   1139 }
   1140