View Javadoc
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    *      https://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  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  
23  package org.hipparchus.linear;
24  
25  
26  import java.util.function.Function;
27  
28  import org.hipparchus.Field;
29  import org.hipparchus.FieldElement;
30  import org.hipparchus.analysis.polynomials.SmoothStepFactory;
31  import org.hipparchus.exception.MathIllegalArgumentException;
32  import org.hipparchus.exception.NullArgumentException;
33  import org.hipparchus.util.FieldBlendable;
34  
35  /**
36   * Interface defining field-valued matrix with basic algebraic operations.
37   * <p>
38   * Matrix element indexing is 0-based -- e.g., <code>getEntry(0, 0)</code>
39   * returns the element in the first row, first column of the matrix.</p>
40   *
41   * @param <T> the type of the field elements
42   */
43  public interface FieldMatrix<T extends FieldElement<T>> extends AnyMatrix, FieldBlendable<FieldMatrix<T>, T> {
44      /**
45       * Get the type of field elements of the matrix.
46       *
47       * @return the type of field elements of the matrix.
48       */
49      Field<T> getField();
50  
51      /**
52       * Create a new {@link FieldMatrix} of the same type as the instance with
53       * the supplied row and column dimensions.
54       *
55       * @param rowDimension  the number of rows in the new matrix
56       * @param columnDimension  the number of columns in the new matrix
57       * @return a new matrix of the same type as the instance
58       * @throws MathIllegalArgumentException if row or column dimension is not
59       * positive.
60       */
61      FieldMatrix<T> createMatrix(int rowDimension, int columnDimension)
62      throws MathIllegalArgumentException;
63  
64      /**
65       * Make a (deep) copy of this.
66       *
67       * @return a copy of this matrix.
68       */
69      FieldMatrix<T> copy();
70  
71      /**
72       * Compute the sum of this and m.
73       *
74       * @param m Matrix to be added.
75       * @return {@code this} + {@code m}.
76       * @throws MathIllegalArgumentException if {@code m} is not the same
77       * size as {@code this} matrix.
78       */
79      FieldMatrix<T> add(FieldMatrix<T> m) throws MathIllegalArgumentException;
80  
81      /**
82       * Subtract {@code m} from this matrix.
83       *
84       * @param m Matrix to be subtracted.
85       * @return {@code this} - {@code m}.
86       * @throws MathIllegalArgumentException if {@code m} is not the same
87       * size as {@code this} matrix.
88       */
89      FieldMatrix<T> subtract(FieldMatrix<T> m) throws MathIllegalArgumentException;
90  
91       /**
92       * Increment each entry of this matrix.
93       *
94       * @param d Value to be added to each entry.
95       * @return {@code d} + {@code this}.
96       */
97      FieldMatrix<T> scalarAdd(T d);
98  
99      /**
100      * Multiply each entry by {@code d}.
101      *
102      * @param d Value to multiply all entries by.
103      * @return {@code d} * {@code this}.
104      */
105     FieldMatrix<T> scalarMultiply(T d);
106 
107     /**
108      * Postmultiply this matrix by {@code m}.
109      *
110      * @param m  Matrix to postmultiply by.
111      * @return {@code this} * {@code m}.
112      * @throws MathIllegalArgumentException if the number of columns of
113      * {@code this} matrix is not equal to the number of rows of matrix
114      * {@code m}.
115      */
116     FieldMatrix<T> multiply(FieldMatrix<T> m) throws MathIllegalArgumentException;
117 
118     /**
119      * Returns the result of postmultiplying {@code this} by {@code m^T}.
120      * <p>
121      * This is equivalent to call {@link #multiply(FieldMatrix) multiply}(m.{@link #transpose()}),
122      * but some implementations may avoid building the intermediate transposed matrix.
123      * </p>
124      * @param m matrix to first transpose and second postmultiply by
125      * @return {@code this * m^T}
126      * @throws MathIllegalArgumentException if
127      * {@code columnDimension(this) != columnDimension(m)}
128      * @since 1.3
129      */
130     default FieldMatrix<T> multiplyTransposed(final FieldMatrix<T> m)
131         throws MathIllegalArgumentException {
132         return multiply(m.transpose());
133     }
134 
135     /**
136      * Returns the result of postmultiplying {@code this^T} by {@code m}.
137      * <p>
138      * This is equivalent to call {@link #transpose()}.{@link #multiply(FieldMatrix) multiply(m)},
139      * but some implementations may avoid building the intermediate transposed matrix.
140      * </p>
141      * @param m matrix to postmultiply by
142      * @return {@code this^T * m}
143      * @throws MathIllegalArgumentException if
144      * {@code columnDimension(this) != columnDimension(m)}
145      * @since 1.3
146      */
147     default FieldMatrix<T> transposeMultiply(final FieldMatrix<T> m)
148         throws MathIllegalArgumentException {
149         return transpose().multiply(m);
150     }
151 
152     /**
153      * Premultiply this matrix by {@code m}.
154      *
155      * @param m Matrix to premultiply by.
156      * @return {@code m} * {@code this}.
157      * @throws MathIllegalArgumentException if the number of columns of {@code m}
158      * differs from the number of rows of {@code this} matrix.
159      */
160     FieldMatrix<T> preMultiply(FieldMatrix<T> m) throws MathIllegalArgumentException;
161 
162     /**
163      * Returns the result multiplying this with itself <code>p</code> times.
164      * Depending on the type of the field elements, T, instability for high
165      * powers might occur.
166      *
167      * @param p raise this to power p
168      * @return this^p
169      * @throws MathIllegalArgumentException if {@code p < 0}
170      * @throws MathIllegalArgumentException if {@code this matrix} is not square
171      */
172     FieldMatrix<T> power(int p) throws MathIllegalArgumentException;
173 
174     /** {@inheritDoc} */
175     @Override
176     default FieldMatrix<T> blendArithmeticallyWith(final FieldMatrix<T> other, final T blendingValue) {
177         SmoothStepFactory.checkBetweenZeroAndOneIncluded(blendingValue.getReal());
178         return this.scalarMultiply(getField().getOne().subtract(blendingValue))
179                    .add(other.scalarMultiply(blendingValue));
180     }
181 
182     /**
183      * Returns matrix entries as a two-dimensional array.
184      *
185      * @return a 2-dimensional array of entries.
186      */
187     T[][] getData();
188 
189     /**
190      * Get a submatrix. Rows and columns are indicated
191      * counting from 0 to n - 1.
192      *
193      * @param startRow Initial row index
194      * @param endRow Final row index (inclusive)
195      * @param startColumn Initial column index
196      * @param endColumn Final column index (inclusive)
197      * @return the matrix containing the data of the specified rows and columns.
198      * @throws MathIllegalArgumentException is {@code endRow < startRow} of
199      * {@code endColumn < startColumn}.
200      * @throws MathIllegalArgumentException if the indices are not valid.
201      */
202    FieldMatrix<T> getSubMatrix(int startRow, int endRow, int startColumn, int endColumn)
203    throws MathIllegalArgumentException;
204 
205    /**
206     * Get a submatrix. Rows and columns are indicated
207     * counting from 0 to n - 1.
208     *
209     * @param selectedRows Array of row indices.
210     * @param selectedColumns Array of column indices.
211     * @return the matrix containing the data in the
212     * specified rows and columns.
213     * @throws MathIllegalArgumentException if {@code selectedRows} or
214     * {@code selectedColumns} is empty
215     * @throws NullArgumentException if {@code selectedRows} or
216     * {@code selectedColumns} is {@code null}.
217     * @throws MathIllegalArgumentException if row or column selections are not valid.
218     */
219    FieldMatrix<T> getSubMatrix(int[] selectedRows, int[] selectedColumns)
220    throws MathIllegalArgumentException, NullArgumentException;
221 
222    /**
223     * Copy a submatrix. Rows and columns are 0-based. The designated submatrix
224     * is copied into the top left portion of the destination array.
225     *
226     * @param startRow Initial row index.
227     * @param endRow Final row index (inclusive).
228     * @param startColumn Initial column index.
229     * @param endColumn Final column index (inclusive).
230     * @param destination The array where the submatrix data should be copied
231     * (if larger than rows/columns counts, only the upper-left part will be modified).
232     * @throws MathIllegalArgumentException if the dimensions of
233     * {@code destination} are not large enough to hold the submatrix.
234     * @throws MathIllegalArgumentException if {@code endRow < startRow} or
235     * {@code endColumn < startColumn}.
236     * @throws MathIllegalArgumentException if the indices are not valid.
237     */
238     void copySubMatrix(int startRow, int endRow, int startColumn, int endColumn,
239                        T[][] destination)
240     throws MathIllegalArgumentException;
241 
242   /**
243    * Copy a submatrix. Rows and columns are indicated
244    * counting from 0 to n - 1.
245    *
246    * @param selectedRows Array of row indices.
247    * @param selectedColumns Array of column indices.
248    * @param destination Arrays where the submatrix data should be copied
249    * (if larger than rows/columns counts, only the upper-left part will be used)
250    * @throws MathIllegalArgumentException if the dimensions of
251    * {@code destination} do not match those of {@code this}.
252    * @throws MathIllegalArgumentException if {@code selectedRows} or
253    * {@code selectedColumns} is empty
254    * @throws NullArgumentException if {@code selectedRows} or
255    * {@code selectedColumns} is {@code null}.
256    * @throws MathIllegalArgumentException if the indices are not valid.
257    */
258   void copySubMatrix(int[] selectedRows, int[] selectedColumns, T[][] destination)
259   throws MathIllegalArgumentException, NullArgumentException;
260 
261     /**
262      * Replace the submatrix starting at {@code (row, column)} using data in the
263      * input {@code subMatrix} array. Indexes are 0-based.
264      * <p>
265      * Example:<br>
266      * Starting with
267      * </p>
268      *
269      * <pre>
270      * 1  2  3  4
271      * 5  6  7  8
272      * 9  0  1  2
273      * </pre>
274      *
275      * <p>and {@code subMatrix = {{3, 4} {5,6}}}, invoking
276      * {@code setSubMatrix(subMatrix,1,1))} will result in</p>
277      *
278      * <pre>
279      * 1  2  3  4
280      * 5  3  4  8
281      * 9  5  6  2
282      * </pre>
283      *
284      * @param subMatrix Array containing the submatrix replacement data.
285      * @param row Row coordinate of the top-left element to be replaced.
286      * @param column Column coordinate of the top-left element to be replaced.
287      * @throws MathIllegalArgumentException if {@code subMatrix} does not fit into this
288      * matrix from element in {@code (row, column)}.
289      * @throws MathIllegalArgumentException if a row or column of {@code subMatrix} is empty.
290      * @throws MathIllegalArgumentException if {@code subMatrix} is not
291      * rectangular (not all rows have the same length).
292      * @throws NullArgumentException if {@code subMatrix} is {@code null}.
293      */
294     void setSubMatrix(T[][] subMatrix, int row, int column)
295         throws MathIllegalArgumentException, NullArgumentException;
296 
297    /**
298     * Get the entries in row number {@code row}
299     * as a row matrix.
300     *
301     * @param row Row to be fetched.
302     * @return a row matrix.
303     * @throws MathIllegalArgumentException if the specified row index is invalid.
304     */
305    FieldMatrix<T> getRowMatrix(int row) throws MathIllegalArgumentException;
306 
307    /**
308     * Set the entries in row number {@code row}
309     * as a row matrix.
310     *
311     * @param row Row to be set.
312     * @param matrix Row matrix (must have one row and the same number
313     * of columns as the instance).
314     * @throws MathIllegalArgumentException if the specified row index is invalid.
315     * @throws MathIllegalArgumentException
316     * if the matrix dimensions do not match one instance row.
317     */
318    void setRowMatrix(int row, FieldMatrix<T> matrix)
319    throws MathIllegalArgumentException;
320 
321    /**
322     * Get the entries in column number {@code column}
323     * as a column matrix.
324     *
325     * @param column Column to be fetched.
326     * @return a column matrix.
327     * @throws MathIllegalArgumentException if the specified column index is invalid.
328     */
329    FieldMatrix<T> getColumnMatrix(int column) throws MathIllegalArgumentException;
330 
331    /**
332     * Set the entries in column number {@code column}
333     * as a column matrix.
334     *
335     * @param column Column to be set.
336     * @param matrix column matrix (must have one column and the same
337     * number of rows as the instance).
338     * @throws MathIllegalArgumentException if the specified column index is invalid.
339     * @throws MathIllegalArgumentException if the matrix dimensions do
340     * not match one instance column.
341     */
342    void setColumnMatrix(int column, FieldMatrix<T> matrix)
343    throws MathIllegalArgumentException;
344 
345    /**
346     * Get the entries in row number {@code row}
347     * as a vector.
348     *
349     * @param row Row to be fetched
350     * @return a row vector.
351     * @throws MathIllegalArgumentException if the specified row index is invalid.
352     */
353    FieldVector<T> getRowVector(int row) throws MathIllegalArgumentException;
354 
355    /**
356     * Set the entries in row number {@code row}
357     * as a vector.
358     *
359     * @param row Row to be set.
360     * @param vector row vector (must have the same number of columns
361     * as the instance).
362     * @throws MathIllegalArgumentException if the specified row index is invalid.
363     * @throws MathIllegalArgumentException if the vector dimension does not
364     * match one instance row.
365     */
366    void setRowVector(int row, FieldVector<T> vector)
367    throws MathIllegalArgumentException;
368 
369    /**
370     * Returns the entries in column number {@code column}
371     * as a vector.
372     *
373     * @param column Column to be fetched.
374     * @return a column vector.
375     * @throws MathIllegalArgumentException if the specified column index is invalid.
376     */
377    FieldVector<T> getColumnVector(int column) throws MathIllegalArgumentException;
378 
379    /**
380     * Set the entries in column number {@code column}
381     * as a vector.
382     *
383     * @param column Column to be set.
384     * @param vector Column vector (must have the same number of rows
385     * as the instance).
386     * @throws MathIllegalArgumentException if the specified column index is invalid.
387     * @throws MathIllegalArgumentException if the vector dimension does not
388     * match one instance column.
389     */
390    void setColumnVector(int column, FieldVector<T> vector)
391    throws MathIllegalArgumentException;
392 
393     /**
394      * Get the entries in row number {@code row} as an array.
395      *
396      * @param row Row to be fetched.
397      * @return array of entries in the row.
398      * @throws MathIllegalArgumentException if the specified row index is not valid.
399      */
400     T[] getRow(int row) throws MathIllegalArgumentException;
401 
402     /**
403      * Set the entries in row number {@code row}
404      * as a row matrix.
405      *
406      * @param row Row to be set.
407      * @param array Row matrix (must have the same number of columns as
408      * the instance).
409      * @throws MathIllegalArgumentException if the specified row index is invalid.
410      * @throws MathIllegalArgumentException if the array size does not match
411      * one instance row.
412      */
413     void setRow(int row, T[] array) throws MathIllegalArgumentException;
414 
415     /**
416      * Get the entries in column number {@code col} as an array.
417      *
418      * @param column the column to be fetched
419      * @return array of entries in the column
420      * @throws MathIllegalArgumentException if the specified column index is not valid.
421      */
422     T[] getColumn(int column) throws MathIllegalArgumentException;
423 
424     /**
425      * Set the entries in column number {@code column}
426      * as a column matrix.
427      *
428      * @param column the column to be set
429      * @param array column array (must have the same number of rows as the instance)
430      * @throws MathIllegalArgumentException if the specified column index is invalid.
431      * @throws MathIllegalArgumentException if the array size does not match
432      * one instance column.
433      */
434     void setColumn(int column, T[] array) throws MathIllegalArgumentException;
435 
436     /**
437      * Returns the entry in the specified row and column.
438      *
439      * @param row  row location of entry to be fetched
440      * @param column  column location of entry to be fetched
441      * @return matrix entry in row,column
442      * @throws MathIllegalArgumentException if the row or column index is not valid.
443      */
444     T getEntry(int row, int column) throws MathIllegalArgumentException;
445 
446     /**
447      * Set the entry in the specified row and column.
448      *
449      * @param row  row location of entry to be set
450      * @param column  column location of entry to be set
451      * @param value matrix entry to be set in row,column
452      * @throws MathIllegalArgumentException if the row or column index is not valid.
453      */
454     void setEntry(int row, int column, T value) throws MathIllegalArgumentException;
455 
456     /**
457      * Change an entry in the specified row and column.
458      *
459      * @param row Row location of entry to be set.
460      * @param column Column location of entry to be set.
461      * @param increment Value to add to the current matrix entry in
462      * {@code (row, column)}.
463      * @throws MathIllegalArgumentException if the row or column index is not valid.
464      */
465     void addToEntry(int row, int column, T increment) throws MathIllegalArgumentException;
466 
467     /**
468      * Change an entry in the specified row and column.
469      *
470      * @param row Row location of entry to be set.
471      * @param column Column location of entry to be set.
472      * @param factor Multiplication factor for the current matrix entry
473      * in {@code (row,column)}
474      * @throws MathIllegalArgumentException if the row or column index is not valid.
475      */
476     void multiplyEntry(int row, int column, T factor) throws MathIllegalArgumentException;
477 
478     /**
479      * Returns the transpose of this matrix.
480      *
481      * @return transpose matrix
482      */
483     FieldMatrix<T> transpose();
484 
485     /**
486      * Returns the <a href="http://mathworld.wolfram.com/MatrixTrace.html">
487      * trace</a> of the matrix (the sum of the elements on the main diagonal).
488      *
489      * @return trace
490      * @throws MathIllegalArgumentException if the matrix is not square.
491      */
492     T getTrace() throws MathIllegalArgumentException;
493 
494     /**
495      * Returns the result of multiplying this by the vector {@code v}.
496      *
497      * @param v the vector to operate on
498      * @return {@code this * v}
499      * @throws MathIllegalArgumentException if the number of columns of
500      * {@code this} matrix is not equal to the size of the vector {@code v}.
501      */
502     T[] operate(T[] v) throws MathIllegalArgumentException;
503 
504     /**
505      * Returns the result of multiplying this by the vector {@code v}.
506      *
507      * @param v the vector to operate on
508      * @return {@code this * v}
509      * @throws MathIllegalArgumentException if the number of columns of
510      * {@code this} matrix is not equal to the size of the vector {@code v}.
511      */
512     FieldVector<T> operate(FieldVector<T> v) throws MathIllegalArgumentException;
513 
514     /**
515      * Returns the (row) vector result of premultiplying this by the vector
516      * {@code v}.
517      *
518      * @param v the row vector to premultiply by
519      * @return {@code v * this}
520      * @throws MathIllegalArgumentException if the number of rows of {@code this}
521      * matrix is not equal to the size of the vector {@code v}
522      */
523     T[] preMultiply(T[] v) throws MathIllegalArgumentException;
524 
525     /**
526      * Returns the (row) vector result of premultiplying this by the vector
527      * {@code v}.
528      *
529      * @param v the row vector to premultiply by
530      * @return {@code v * this}
531      * @throws MathIllegalArgumentException if the number of rows of {@code this}
532      * matrix is not equal to the size of the vector {@code v}
533      */
534     FieldVector<T> preMultiply(FieldVector<T> v) throws MathIllegalArgumentException;
535 
536     /**
537      * Visit (and possibly change) all matrix entries in row order.
538      * <p>Row order starts at upper left and iterating through all elements
539      * of a row from left to right before going to the leftmost element
540      * of the next row.</p>
541      * @param visitor visitor used to process all matrix entries
542      * @see #walkInRowOrder(FieldMatrixPreservingVisitor)
543      * @see #walkInRowOrder(FieldMatrixChangingVisitor, int, int, int, int)
544      * @see #walkInRowOrder(FieldMatrixPreservingVisitor, int, int, int, int)
545      * @see #walkInColumnOrder(FieldMatrixChangingVisitor)
546      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor)
547      * @see #walkInColumnOrder(FieldMatrixChangingVisitor, int, int, int, int)
548      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor, int, int, int, int)
549      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor)
550      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor)
551      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor, int, int, int, int)
552      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor, int, int, int, int)
553      * @return the value returned by {@link FieldMatrixChangingVisitor#end()} at the end
554      * of the walk
555      */
556     T walkInRowOrder(FieldMatrixChangingVisitor<T> visitor);
557 
558     /**
559      * Visit (but don't change) all matrix entries in row order.
560      * <p>Row order starts at upper left and iterating through all elements
561      * of a row from left to right before going to the leftmost element
562      * of the next row.</p>
563      * @param visitor visitor used to process all matrix entries
564      * @see #walkInRowOrder(FieldMatrixChangingVisitor)
565      * @see #walkInRowOrder(FieldMatrixChangingVisitor, int, int, int, int)
566      * @see #walkInRowOrder(FieldMatrixPreservingVisitor, int, int, int, int)
567      * @see #walkInColumnOrder(FieldMatrixChangingVisitor)
568      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor)
569      * @see #walkInColumnOrder(FieldMatrixChangingVisitor, int, int, int, int)
570      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor, int, int, int, int)
571      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor)
572      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor)
573      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor, int, int, int, int)
574      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor, int, int, int, int)
575      * @return the value returned by {@link FieldMatrixPreservingVisitor#end()} at the end
576      * of the walk
577      */
578     T walkInRowOrder(FieldMatrixPreservingVisitor<T> visitor);
579 
580     /**
581      * Visit (and possibly change) some matrix entries in row order.
582      * <p>Row order starts at upper left and iterating through all elements
583      * of a row from left to right before going to the leftmost element
584      * of the next row.</p>
585      * @param visitor visitor used to process all matrix entries
586      * @param startRow Initial row index
587      * @param endRow Final row index (inclusive)
588      * @param startColumn Initial column index
589      * @param endColumn Final column index
590      * @throws MathIllegalArgumentException if the indices are not valid.
591      * @throws MathIllegalArgumentException if {@code endRow < startRow} or
592      * {@code endColumn < startColumn}.
593      * @see #walkInRowOrder(FieldMatrixChangingVisitor)
594      * @see #walkInRowOrder(FieldMatrixPreservingVisitor)
595      * @see #walkInRowOrder(FieldMatrixPreservingVisitor, int, int, int, int)
596      * @see #walkInColumnOrder(FieldMatrixChangingVisitor)
597      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor)
598      * @see #walkInColumnOrder(FieldMatrixChangingVisitor, int, int, int, int)
599      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor, int, int, int, int)
600      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor)
601      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor)
602      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor, int, int, int, int)
603      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor, int, int, int, int)
604      * @return the value returned by {@link FieldMatrixChangingVisitor#end()} at the end
605      * of the walk
606      */
607     T walkInRowOrder(FieldMatrixChangingVisitor<T> visitor,
608                      int startRow, int endRow, int startColumn, int endColumn)
609     throws MathIllegalArgumentException;
610 
611     /**
612      * Visit (but don't change) some matrix entries in row order.
613      * <p>Row order starts at upper left and iterating through all elements
614      * of a row from left to right before going to the leftmost element
615      * of the next row.</p>
616      * @param visitor visitor used to process all matrix entries
617      * @param startRow Initial row index
618      * @param endRow Final row index (inclusive)
619      * @param startColumn Initial column index
620      * @param endColumn Final column index
621      * @throws MathIllegalArgumentException if the indices are not valid.
622      * @throws MathIllegalArgumentException if {@code endRow < startRow} or
623      * {@code endColumn < startColumn}.
624      * @see #walkInRowOrder(FieldMatrixChangingVisitor)
625      * @see #walkInRowOrder(FieldMatrixPreservingVisitor)
626      * @see #walkInRowOrder(FieldMatrixChangingVisitor, int, int, int, int)
627      * @see #walkInColumnOrder(FieldMatrixChangingVisitor)
628      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor)
629      * @see #walkInColumnOrder(FieldMatrixChangingVisitor, int, int, int, int)
630      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor, int, int, int, int)
631      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor)
632      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor)
633      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor, int, int, int, int)
634      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor, int, int, int, int)
635      * @return the value returned by {@link FieldMatrixPreservingVisitor#end()} at the end
636      * of the walk
637      */
638     T walkInRowOrder(FieldMatrixPreservingVisitor<T> visitor,
639                      int startRow, int endRow, int startColumn, int endColumn)
640     throws MathIllegalArgumentException;
641 
642     /**
643      * Visit (and possibly change) all matrix entries in column order.
644      * <p>Column order starts at upper left and iterating through all elements
645      * of a column from top to bottom before going to the topmost element
646      * of the next column.</p>
647      * @param visitor visitor used to process all matrix entries
648      * @see #walkInRowOrder(FieldMatrixChangingVisitor)
649      * @see #walkInRowOrder(FieldMatrixPreservingVisitor)
650      * @see #walkInRowOrder(FieldMatrixChangingVisitor, int, int, int, int)
651      * @see #walkInRowOrder(FieldMatrixPreservingVisitor, int, int, int, int)
652      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor)
653      * @see #walkInColumnOrder(FieldMatrixChangingVisitor, int, int, int, int)
654      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor, int, int, int, int)
655      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor)
656      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor)
657      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor, int, int, int, int)
658      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor, int, int, int, int)
659      * @return the value returned by {@link FieldMatrixChangingVisitor#end()} at the end
660      * of the walk
661      */
662     T walkInColumnOrder(FieldMatrixChangingVisitor<T> visitor);
663 
664     /**
665      * Visit (but don't change) all matrix entries in column order.
666      * <p>Column order starts at upper left and iterating through all elements
667      * of a column from top to bottom before going to the topmost element
668      * of the next column.</p>
669      * @param visitor visitor used to process all matrix entries
670      * @see #walkInRowOrder(FieldMatrixChangingVisitor)
671      * @see #walkInRowOrder(FieldMatrixPreservingVisitor)
672      * @see #walkInRowOrder(FieldMatrixChangingVisitor, int, int, int, int)
673      * @see #walkInRowOrder(FieldMatrixPreservingVisitor, int, int, int, int)
674      * @see #walkInColumnOrder(FieldMatrixChangingVisitor)
675      * @see #walkInColumnOrder(FieldMatrixChangingVisitor, int, int, int, int)
676      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor, int, int, int, int)
677      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor)
678      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor)
679      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor, int, int, int, int)
680      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor, int, int, int, int)
681      * @return the value returned by {@link FieldMatrixPreservingVisitor#end()} at the end
682      * of the walk
683      */
684     T walkInColumnOrder(FieldMatrixPreservingVisitor<T> visitor);
685 
686     /**
687      * Visit (and possibly change) some matrix entries in column order.
688      * <p>Column order starts at upper left and iterating through all elements
689      * of a column from top to bottom before going to the topmost element
690      * of the next column.</p>
691      * @param visitor visitor used to process all matrix entries
692      * @param startRow Initial row index
693      * @param endRow Final row index (inclusive)
694      * @param startColumn Initial column index
695      * @param endColumn Final column index
696      * @throws MathIllegalArgumentException if {@code endRow < startRow} or
697      * {@code endColumn < startColumn}.
698      * @throws MathIllegalArgumentException if the indices are not valid.
699      * @see #walkInRowOrder(FieldMatrixChangingVisitor)
700      * @see #walkInRowOrder(FieldMatrixPreservingVisitor)
701      * @see #walkInRowOrder(FieldMatrixChangingVisitor, int, int, int, int)
702      * @see #walkInRowOrder(FieldMatrixPreservingVisitor, int, int, int, int)
703      * @see #walkInColumnOrder(FieldMatrixChangingVisitor)
704      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor)
705      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor, int, int, int, int)
706      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor)
707      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor)
708      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor, int, int, int, int)
709      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor, int, int, int, int)
710      * @return the value returned by {@link FieldMatrixChangingVisitor#end()} at the end
711      * of the walk
712      */
713     T walkInColumnOrder(FieldMatrixChangingVisitor<T> visitor,
714                         int startRow, int endRow, int startColumn, int endColumn)
715     throws MathIllegalArgumentException;
716 
717     /**
718      * Visit (but don't change) some matrix entries in column order.
719      * <p>Column order starts at upper left and iterating through all elements
720      * of a column from top to bottom before going to the topmost element
721      * of the next column.</p>
722      * @param visitor visitor used to process all matrix entries
723      * @param startRow Initial row index
724      * @param endRow Final row index (inclusive)
725      * @param startColumn Initial column index
726      * @param endColumn Final column index
727      * @throws MathIllegalArgumentException if {@code endRow < startRow} or
728      * {@code endColumn < startColumn}.
729      * @throws MathIllegalArgumentException if the indices are not valid.
730      * @see #walkInRowOrder(FieldMatrixChangingVisitor)
731      * @see #walkInRowOrder(FieldMatrixPreservingVisitor)
732      * @see #walkInRowOrder(FieldMatrixChangingVisitor, int, int, int, int)
733      * @see #walkInRowOrder(FieldMatrixPreservingVisitor, int, int, int, int)
734      * @see #walkInColumnOrder(FieldMatrixChangingVisitor)
735      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor)
736      * @see #walkInColumnOrder(FieldMatrixChangingVisitor, int, int, int, int)
737      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor)
738      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor)
739      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor, int, int, int, int)
740      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor, int, int, int, int)
741      * @return the value returned by {@link FieldMatrixPreservingVisitor#end()} at the end
742      * of the walk
743      */
744     T walkInColumnOrder(FieldMatrixPreservingVisitor<T> visitor,
745                         int startRow, int endRow, int startColumn, int endColumn)
746     throws MathIllegalArgumentException;
747 
748     /**
749      * Visit (and possibly change) all matrix entries using the fastest possible order.
750      * <p>The fastest walking order depends on the exact matrix class. It may be
751      * different from traditional row or column orders.</p>
752      * @param visitor visitor used to process all matrix entries
753      * @see #walkInRowOrder(FieldMatrixChangingVisitor)
754      * @see #walkInRowOrder(FieldMatrixPreservingVisitor)
755      * @see #walkInRowOrder(FieldMatrixChangingVisitor, int, int, int, int)
756      * @see #walkInRowOrder(FieldMatrixPreservingVisitor, int, int, int, int)
757      * @see #walkInColumnOrder(FieldMatrixChangingVisitor)
758      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor)
759      * @see #walkInColumnOrder(FieldMatrixChangingVisitor, int, int, int, int)
760      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor, int, int, int, int)
761      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor)
762      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor, int, int, int, int)
763      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor, int, int, int, int)
764      * @return the value returned by {@link FieldMatrixChangingVisitor#end()} at the end
765      * of the walk
766      */
767     T walkInOptimizedOrder(FieldMatrixChangingVisitor<T> visitor);
768 
769     /**
770      * Visit (but don't change) all matrix entries using the fastest possible order.
771      * <p>The fastest walking order depends on the exact matrix class. It may be
772      * different from traditional row or column orders.</p>
773      * @param visitor visitor used to process all matrix entries
774      * @see #walkInRowOrder(FieldMatrixChangingVisitor)
775      * @see #walkInRowOrder(FieldMatrixPreservingVisitor)
776      * @see #walkInRowOrder(FieldMatrixChangingVisitor, int, int, int, int)
777      * @see #walkInRowOrder(FieldMatrixPreservingVisitor, int, int, int, int)
778      * @see #walkInColumnOrder(FieldMatrixChangingVisitor)
779      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor)
780      * @see #walkInColumnOrder(FieldMatrixChangingVisitor, int, int, int, int)
781      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor, int, int, int, int)
782      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor)
783      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor, int, int, int, int)
784      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor, int, int, int, int)
785      * @return the value returned by {@link FieldMatrixPreservingVisitor#end()} at the end
786      * of the walk
787      */
788     T walkInOptimizedOrder(FieldMatrixPreservingVisitor<T> visitor);
789 
790     /**
791      * Visit (and possibly change) some matrix entries using the fastest possible order.
792      * <p>The fastest walking order depends on the exact matrix class. It may be
793      * different from traditional row or column orders.</p>
794      * @param visitor visitor used to process all matrix entries
795      * @param startRow Initial row index
796      * @param endRow Final row index (inclusive)
797      * @param startColumn Initial column index
798      * @param endColumn Final column index (inclusive)
799      * @throws MathIllegalArgumentException if {@code endRow < startRow} or
800      * {@code endColumn < startColumn}.
801      * @throws MathIllegalArgumentException if the indices are not valid.
802      * @see #walkInRowOrder(FieldMatrixChangingVisitor)
803      * @see #walkInRowOrder(FieldMatrixPreservingVisitor)
804      * @see #walkInRowOrder(FieldMatrixChangingVisitor, int, int, int, int)
805      * @see #walkInRowOrder(FieldMatrixPreservingVisitor, int, int, int, int)
806      * @see #walkInColumnOrder(FieldMatrixChangingVisitor)
807      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor)
808      * @see #walkInColumnOrder(FieldMatrixChangingVisitor, int, int, int, int)
809      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor, int, int, int, int)
810      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor)
811      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor)
812      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor, int, int, int, int)
813      * @return the value returned by {@link FieldMatrixChangingVisitor#end()} at the end
814      * of the walk
815      */
816     T walkInOptimizedOrder(FieldMatrixChangingVisitor<T> visitor,
817                            int startRow, int endRow, int startColumn, int endColumn)
818     throws MathIllegalArgumentException;
819 
820     /**
821      * Visit (but don't change) some matrix entries using the fastest possible order.
822      * <p>The fastest walking order depends on the exact matrix class. It may be
823      * different from traditional row or column orders.</p>
824      * @param visitor visitor used to process all matrix entries
825      * @param startRow Initial row index
826      * @param endRow Final row index (inclusive)
827      * @param startColumn Initial column index
828      * @param endColumn Final column index (inclusive)
829      * @throws MathIllegalArgumentException if {@code endRow < startRow} or
830      * {@code endColumn < startColumn}.
831      * @throws MathIllegalArgumentException if the indices are not valid.
832      * @see #walkInRowOrder(FieldMatrixChangingVisitor)
833      * @see #walkInRowOrder(FieldMatrixPreservingVisitor)
834      * @see #walkInRowOrder(FieldMatrixChangingVisitor, int, int, int, int)
835      * @see #walkInRowOrder(FieldMatrixPreservingVisitor, int, int, int, int)
836      * @see #walkInColumnOrder(FieldMatrixChangingVisitor)
837      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor)
838      * @see #walkInColumnOrder(FieldMatrixChangingVisitor, int, int, int, int)
839      * @see #walkInColumnOrder(FieldMatrixPreservingVisitor, int, int, int, int)
840      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor)
841      * @see #walkInOptimizedOrder(FieldMatrixPreservingVisitor)
842      * @see #walkInOptimizedOrder(FieldMatrixChangingVisitor, int, int, int, int)
843      * @return the value returned by {@link FieldMatrixPreservingVisitor#end()} at the end
844      * of the walk
845      */
846     T walkInOptimizedOrder(FieldMatrixPreservingVisitor<T> visitor,
847                            int startRow, int endRow, int startColumn, int endColumn)
848     throws MathIllegalArgumentException;
849 
850     /**
851      * Acts as if implemented as:
852      * <pre>
853      *  return copy().mapToSelf(function);
854      * </pre>
855      * Returns a new matrix. Does not change instance data.
856      *
857      * @param function Function to apply to each entry.
858      * @return a new matrix.
859      * @since 1.7
860      */
861     default FieldMatrix<T> map(Function<T, T> function) {
862         return copy().mapToSelf(function);
863     }
864 
865     /**
866      * Replace each entry by the result of applying the function to it.
867      *
868      * @param function Function to apply to each entry.
869      * @return a reference to this matrix.
870      * @since 1.7
871      */
872     default FieldMatrix<T> mapToSelf(final Function<T,T> function) {
873         walkInOptimizedOrder(new FieldMatrixChangingVisitor<T>() {
874 
875             /** {@inheritDoc} */
876             @Override
877             public T visit(int row, int column, T value) {
878                 // apply the function to the current entry
879                 return function.apply(value);
880             }
881 
882             /** {@inheritDoc} */
883             @Override
884             public void start(int rows, int columns, int startRow, int endRow,
885                               int startColumn, int endColumn) {
886             }
887 
888             /** {@inheritDoc} */
889             @Override
890             public T end() {
891                 return getField().getZero();
892             }
893 
894         });
895 
896         return this;
897 
898     }
899 
900 }