• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 févr. 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      */
AbstractFieldMatrix()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      */
AbstractFieldMatrix(final Field<T> field)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      */
AbstractFieldMatrix(final Field<T> field, final int rowDimension, final int columnDimension)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      */
extractField(final T[][] d)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      */
extractField(final T[] d)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")
buildArray(final Field<T> field, final int rows, final int columns)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      */
buildArray(final Field<T> field, final int length)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} */
getField()158     public Field<T> getField() {
159         return field;
160     }
161 
162     /** {@inheritDoc} */
createMatrix(final int rowDimension, final int columnDimension)163     public abstract FieldMatrix<T> createMatrix(final int rowDimension, final int columnDimension)
164         throws IllegalArgumentException;
165 
166     /** {@inheritDoc} */
copy()167     public abstract FieldMatrix<T> copy();
168 
169     /** {@inheritDoc} */
add(FieldMatrix<T> m)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} */
subtract(final FieldMatrix<T> m)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} */
scalarAdd(final T d)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} */
scalarMultiply(final T d)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} */
multiply(final FieldMatrix<T> m)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} */
preMultiply(final FieldMatrix<T> m)265     public FieldMatrix<T> preMultiply(final FieldMatrix<T> m)
266         throws IllegalArgumentException {
267         return m.multiply(this);
268     }
269 
270     /** {@inheritDoc} */
getData()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} */
getSubMatrix(final int startRow, final int endRow, final int startColumn, final int endColumn)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} */
getSubMatrix(final int[] selectedRows, final int[] selectedColumns)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} */
copySubMatrix(final int startRow, final int endRow, final int startColumn, final int endColumn, final T[][] destination)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} */
copySubMatrix(int[] selectedRows, int[] selectedColumns, T[][] destination)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} */
setSubMatrix(final T[][] subMatrix, final int row, final int column)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} */
getRowMatrix(final int row)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} */
setRowMatrix(final int row, final FieldMatrix<T> matrix)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} */
getColumnMatrix(final int column)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} */
setColumnMatrix(final int column, final FieldMatrix<T> matrix)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} */
getRowVector(final int row)500     public FieldVector<T> getRowVector(final int row)
501         throws MatrixIndexException {
502         return new ArrayFieldVector<T>(getRow(row), false);
503     }
504 
505     /** {@inheritDoc} */
setRowVector(final int row, final FieldVector<T> vector)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} */
getColumnVector(final int column)523     public FieldVector<T> getColumnVector(final int column)
524         throws MatrixIndexException {
525         return new ArrayFieldVector<T>(getColumn(column), false);
526     }
527 
528     /** {@inheritDoc} */
setColumnVector(final int column, final FieldVector<T> vector)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} */
getRow(final int row)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} */
setRow(final int row, final T[] array)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} */
getColumn(final int column)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} */
setColumn(final int column, final T[] array)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} */
getEntry(int row, int column)610     public abstract T getEntry(int row, int column)
611         throws MatrixIndexException;
612 
613     /** {@inheritDoc} */
setEntry(int row, int column, T value)614     public abstract void setEntry(int row, int column, T value)
615         throws MatrixIndexException;
616 
617     /** {@inheritDoc} */
addToEntry(int row, int column, T increment)618     public abstract void addToEntry(int row, int column, T increment)
619         throws MatrixIndexException;
620 
621     /** {@inheritDoc} */
multiplyEntry(int row, int column, T factor)622     public abstract void multiplyEntry(int row, int column, T factor)
623         throws MatrixIndexException;
624 
625     /** {@inheritDoc} */
transpose()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} */
isSquare()646     public boolean isSquare() {
647         return getColumnDimension() == getRowDimension();
648     }
649 
650     /** {@inheritDoc} */
getRowDimension()651     public abstract int getRowDimension();
652 
653     /** {@inheritDoc} */
getColumnDimension()654     public abstract int getColumnDimension();
655 
656     /** {@inheritDoc} */
getTrace()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} */
operate(final T[] v)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} */
operate(final FieldVector<T> v)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} */
preMultiply(final T[] v)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} */
preMultiply(final FieldVector<T> v)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} */
walkInRowOrder(final FieldMatrixChangingVisitor<T> visitor)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} */
walkInRowOrder(final FieldMatrixPreservingVisitor<T> visitor)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} */
walkInRowOrder(final FieldMatrixChangingVisitor<T> visitor, final int startRow, final int endRow, final int startColumn, final int endColumn)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} */
walkInRowOrder(final FieldMatrixPreservingVisitor<T> visitor, final int startRow, final int endRow, final int startColumn, final int endColumn)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} */
walkInColumnOrder(final FieldMatrixChangingVisitor<T> visitor)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} */
walkInColumnOrder(final FieldMatrixPreservingVisitor<T> visitor)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} */
walkInColumnOrder(final FieldMatrixChangingVisitor<T> visitor, final int startRow, final int endRow, final int startColumn, final int endColumn)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} */
walkInColumnOrder(final FieldMatrixPreservingVisitor<T> visitor, final int startRow, final int endRow, final int startColumn, final int endColumn)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} */
walkInOptimizedOrder(final FieldMatrixChangingVisitor<T> visitor)906     public T walkInOptimizedOrder(final FieldMatrixChangingVisitor<T> visitor)
907         throws MatrixVisitorException {
908         return walkInRowOrder(visitor);
909     }
910 
911     /** {@inheritDoc} */
walkInOptimizedOrder(final FieldMatrixPreservingVisitor<T> visitor)912     public T walkInOptimizedOrder(final FieldMatrixPreservingVisitor<T> visitor)
913         throws MatrixVisitorException {
914         return walkInRowOrder(visitor);
915     }
916 
917     /** {@inheritDoc} */
walkInOptimizedOrder(final FieldMatrixChangingVisitor<T> visitor, final int startRow, final int endRow, final int startColumn, final int endColumn)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} */
walkInOptimizedOrder(final FieldMatrixPreservingVisitor<T> visitor, final int startRow, final int endRow, final int startColumn, final int endColumn)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
toString()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
equals(final Object object)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
hashCode()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      */
checkRowIndex(final int row)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      */
checkColumnIndex(final int column)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      */
checkSubMatrixIndex(final int startRow, final int endRow, final int startColumn, final int endColumn)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      */
checkSubMatrixIndex(final int[] selectedRows, final int[] selectedColumns)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      */
checkAdditionCompatible(final FieldMatrix<T> m)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      */
checkSubtractionCompatible(final FieldMatrix<T> m)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      */
checkMultiplicationCompatible(final FieldMatrix<T> m)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