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