• 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.io.IOException;
21 import java.io.ObjectInputStream;
22 import java.io.ObjectOutputStream;
23 import java.lang.reflect.Array;
24 import java.math.BigDecimal;
25 import java.util.Arrays;
26 
27 import org.apache.commons.math.Field;
28 import org.apache.commons.math.FieldElement;
29 import org.apache.commons.math.MathRuntimeException;
30 import org.apache.commons.math.exception.util.LocalizedFormats;
31 import org.apache.commons.math.fraction.BigFraction;
32 import org.apache.commons.math.fraction.Fraction;
33 
34 /**
35  * A collection of static methods that operate on or return matrices.
36  *
37  * @version $Revision: 983921 $ $Date: 2010-08-10 12:46:06 +0200 (mar. 10 août 2010) $
38  */
39 public class MatrixUtils {
40 
41     /**
42      * Private constructor.
43      */
MatrixUtils()44     private MatrixUtils() {
45         super();
46     }
47 
48     /**
49      * Returns a {@link RealMatrix} with specified dimensions.
50      * <p>The type of matrix returned depends on the dimension. Below
51      * 2<sup>12</sup> elements (i.e. 4096 elements or 64&times;64 for a
52      * square matrix) which can be stored in a 32kB array, a {@link
53      * Array2DRowRealMatrix} instance is built. Above this threshold a {@link
54      * BlockRealMatrix} instance is built.</p>
55      * <p>The matrix elements are all set to 0.0.</p>
56      * @param rows number of rows of the matrix
57      * @param columns number of columns of the matrix
58      * @return  RealMatrix with specified dimensions
59      * @see #createRealMatrix(double[][])
60      */
createRealMatrix(final int rows, final int columns)61     public static RealMatrix createRealMatrix(final int rows, final int columns) {
62         return (rows * columns <= 4096) ?
63                 new Array2DRowRealMatrix(rows, columns) : new BlockRealMatrix(rows, columns);
64     }
65 
66     /**
67      * Returns a {@link FieldMatrix} with specified dimensions.
68      * <p>The type of matrix returned depends on the dimension. Below
69      * 2<sup>12</sup> elements (i.e. 4096 elements or 64&times;64 for a
70      * square matrix), a {@link FieldMatrix} instance is built. Above
71      * this threshold a {@link BlockFieldMatrix} instance is built.</p>
72      * <p>The matrix elements are all set to field.getZero().</p>
73      * @param <T> the type of the field elements
74      * @param field field to which the matrix elements belong
75      * @param rows number of rows of the matrix
76      * @param columns number of columns of the matrix
77      * @return  FieldMatrix with specified dimensions
78      * @see #createFieldMatrix(FieldElement[][])
79      * @since 2.0
80      */
createFieldMatrix(final Field<T> field, final int rows, final int columns)81     public static <T extends FieldElement<T>> FieldMatrix<T> createFieldMatrix(final Field<T> field,
82                                                                                final int rows,
83                                                                                final int columns) {
84         return (rows * columns <= 4096) ?
85                 new Array2DRowFieldMatrix<T>(field, rows, columns) : new BlockFieldMatrix<T>(field, rows, columns);
86     }
87 
88     /**
89      * Returns a {@link RealMatrix} whose entries are the the values in the
90      * the input array.
91      * <p>The type of matrix returned depends on the dimension. Below
92      * 2<sup>12</sup> elements (i.e. 4096 elements or 64&times;64 for a
93      * square matrix) which can be stored in a 32kB array, a {@link
94      * Array2DRowRealMatrix} instance is built. Above this threshold a {@link
95      * BlockRealMatrix} instance is built.</p>
96      * <p>The input array is copied, not referenced.</p>
97      *
98      * @param data input array
99      * @return  RealMatrix containing the values of the array
100      * @throws IllegalArgumentException if <code>data</code> is not rectangular
101      *  (not all rows have the same length) or empty
102      * @throws NullPointerException if either <code>data</code> or
103      * <code>data[0]</code> is null
104      * @see #createRealMatrix(int, int)
105      */
createRealMatrix(double[][] data)106     public static RealMatrix createRealMatrix(double[][] data) {
107         return (data.length * data[0].length <= 4096) ?
108                 new Array2DRowRealMatrix(data) : new BlockRealMatrix(data);
109     }
110 
111     /**
112      * Returns a {@link FieldMatrix} whose entries are the the values in the
113      * the input array.
114      * <p>The type of matrix returned depends on the dimension. Below
115      * 2<sup>12</sup> elements (i.e. 4096 elements or 64&times;64 for a
116      * square matrix), a {@link FieldMatrix} instance is built. Above
117      * this threshold a {@link BlockFieldMatrix} instance is built.</p>
118      * <p>The input array is copied, not referenced.</p>
119      * @param <T> the type of the field elements
120      * @param data input array
121      * @return  RealMatrix containing the values of the array
122      * @throws IllegalArgumentException if <code>data</code> is not rectangular
123      *  (not all rows have the same length) or empty
124      * @throws NullPointerException if either <code>data</code> or
125      * <code>data[0]</code> is null
126      * @see #createFieldMatrix(Field, int, int)
127      * @since 2.0
128      */
createFieldMatrix(T[][] data)129     public static <T extends FieldElement<T>> FieldMatrix<T> createFieldMatrix(T[][] data) {
130         return (data.length * data[0].length <= 4096) ?
131                 new Array2DRowFieldMatrix<T>(data) : new BlockFieldMatrix<T>(data);
132     }
133 
134     /**
135      * Returns <code>dimension x dimension</code> identity matrix.
136      *
137      * @param dimension dimension of identity matrix to generate
138      * @return identity matrix
139      * @throws IllegalArgumentException if dimension is not positive
140      * @since 1.1
141      */
createRealIdentityMatrix(int dimension)142     public static RealMatrix createRealIdentityMatrix(int dimension) {
143         final RealMatrix m = createRealMatrix(dimension, dimension);
144         for (int i = 0; i < dimension; ++i) {
145             m.setEntry(i, i, 1.0);
146         }
147         return m;
148     }
149 
150     /**
151      * Returns <code>dimension x dimension</code> identity matrix.
152      *
153      * @param <T> the type of the field elements
154      * @param field field to which the elements belong
155      * @param dimension dimension of identity matrix to generate
156      * @return identity matrix
157      * @throws IllegalArgumentException if dimension is not positive
158      * @since 2.0
159      */
160     public static <T extends FieldElement<T>> FieldMatrix<T>
createFieldIdentityMatrix(final Field<T> field, final int dimension)161         createFieldIdentityMatrix(final Field<T> field, final int dimension) {
162         final T zero = field.getZero();
163         final T one  = field.getOne();
164         @SuppressWarnings("unchecked") // zero is type T
165         final T[][] d = (T[][]) Array.newInstance(zero.getClass(), new int[] { dimension, dimension });
166         for (int row = 0; row < dimension; row++) {
167             final T[] dRow = d[row];
168             Arrays.fill(dRow, zero);
169             dRow[row] = one;
170         }
171         return new Array2DRowFieldMatrix<T>(d, false);
172     }
173 
174     /**
175      * Returns <code>dimension x dimension</code> identity matrix.
176      *
177      * @param dimension dimension of identity matrix to generate
178      * @return identity matrix
179      * @throws IllegalArgumentException if dimension is not positive
180      * @since 1.1
181      * @deprecated since 2.0, replaced by {@link #createFieldIdentityMatrix(Field, int)}
182      */
183     @Deprecated
createBigIdentityMatrix(int dimension)184     public static BigMatrix createBigIdentityMatrix(int dimension) {
185         final BigDecimal[][] d = new BigDecimal[dimension][dimension];
186         for (int row = 0; row < dimension; row++) {
187             final BigDecimal[] dRow = d[row];
188             Arrays.fill(dRow, BigMatrixImpl.ZERO);
189             dRow[row] = BigMatrixImpl.ONE;
190         }
191         return new BigMatrixImpl(d, false);
192     }
193 
194     /**
195      * Returns a diagonal matrix with specified elements.
196      *
197      * @param diagonal diagonal elements of the matrix (the array elements
198      * will be copied)
199      * @return diagonal matrix
200      * @since 2.0
201      */
createRealDiagonalMatrix(final double[] diagonal)202     public static RealMatrix createRealDiagonalMatrix(final double[] diagonal) {
203         final RealMatrix m = createRealMatrix(diagonal.length, diagonal.length);
204         for (int i = 0; i < diagonal.length; ++i) {
205             m.setEntry(i, i, diagonal[i]);
206         }
207         return m;
208     }
209 
210     /**
211      * Returns a diagonal matrix with specified elements.
212      *
213      * @param <T> the type of the field elements
214      * @param diagonal diagonal elements of the matrix (the array elements
215      * will be copied)
216      * @return diagonal matrix
217      * @since 2.0
218      */
219     public static <T extends FieldElement<T>> FieldMatrix<T>
createFieldDiagonalMatrix(final T[] diagonal)220         createFieldDiagonalMatrix(final T[] diagonal) {
221         final FieldMatrix<T> m =
222             createFieldMatrix(diagonal[0].getField(), diagonal.length, diagonal.length);
223         for (int i = 0; i < diagonal.length; ++i) {
224             m.setEntry(i, i, diagonal[i]);
225         }
226         return m;
227     }
228 
229     /**
230      * Returns a {@link BigMatrix} whose entries are the the values in the
231      * the input array.  The input array is copied, not referenced.
232      *
233      * @param data input array
234      * @return  RealMatrix containing the values of the array
235      * @throws IllegalArgumentException if <code>data</code> is not rectangular
236      *  (not all rows have the same length) or empty
237      * @throws NullPointerException if data is null
238      * @deprecated since 2.0 replaced by {@link #createFieldMatrix(FieldElement[][])}
239      */
240     @Deprecated
createBigMatrix(double[][] data)241     public static BigMatrix createBigMatrix(double[][] data) {
242         return new BigMatrixImpl(data);
243     }
244 
245     /**
246      * Returns a {@link BigMatrix} whose entries are the the values in the
247      * the input array.  The input array is copied, not referenced.
248      *
249      * @param data input array
250      * @return  RealMatrix containing the values of the array
251      * @throws IllegalArgumentException if <code>data</code> is not rectangular
252      *  (not all rows have the same length) or empty
253      * @throws NullPointerException if data is null
254      * @deprecated since 2.0 replaced by {@link #createFieldMatrix(FieldElement[][])}
255      */
256     @Deprecated
createBigMatrix(BigDecimal[][] data)257     public static BigMatrix createBigMatrix(BigDecimal[][] data) {
258         return new BigMatrixImpl(data);
259     }
260 
261     /**
262      * Returns a {@link BigMatrix} whose entries are the the values in the
263      * the input array.
264      * <p>If an array is built specially in order to be embedded in a
265      * BigMatrix and not used directly, the <code>copyArray</code> may be
266      * set to <code>false</code. This will prevent the copying and improve
267      * performance as no new array will be built and no data will be copied.</p>
268      * @param data data for new matrix
269      * @param copyArray if true, the input array will be copied, otherwise
270      * it will be referenced
271      * @return  BigMatrix containing the values of the array
272      * @throws IllegalArgumentException if <code>data</code> is not rectangular
273      *  (not all rows have the same length) or empty
274      * @throws NullPointerException if <code>data</code> is null
275      * @see #createRealMatrix(double[][])
276      * @deprecated since 2.0 replaced by {@link #createFieldMatrix(FieldElement[][])}
277      */
278     @Deprecated
createBigMatrix(BigDecimal[][] data, boolean copyArray)279     public static BigMatrix createBigMatrix(BigDecimal[][] data, boolean copyArray) {
280         return new BigMatrixImpl(data, copyArray);
281     }
282 
283     /**
284      * Returns a {@link BigMatrix} whose entries are the the values in the
285      * the input array.  The input array is copied, not referenced.
286      *
287      * @param data input array
288      * @return  RealMatrix containing the values of the array
289      * @throws IllegalArgumentException if <code>data</code> is not rectangular
290      *  (not all rows have the same length) or empty
291      * @throws NullPointerException if data is null
292      * @deprecated since 2.0 replaced by {@link #createFieldMatrix(FieldElement[][])}
293      */
294     @Deprecated
createBigMatrix(String[][] data)295     public static BigMatrix createBigMatrix(String[][] data) {
296         return new BigMatrixImpl(data);
297     }
298 
299     /**
300      * Creates a {@link RealVector} using the data from the input array.
301      *
302      * @param data the input data
303      * @return a data.length RealVector
304      * @throws IllegalArgumentException if <code>data</code> is empty
305      * @throws NullPointerException if <code>data</code>is null
306      */
createRealVector(double[] data)307     public static RealVector createRealVector(double[] data) {
308         return new ArrayRealVector(data, true);
309     }
310 
311     /**
312      * Creates a {@link FieldVector} using the data from the input array.
313      *
314      * @param <T> the type of the field elements
315      * @param data the input data
316      * @return a data.length FieldVector
317      * @throws IllegalArgumentException if <code>data</code> is empty
318      * @throws NullPointerException if <code>data</code>is null
319      */
createFieldVector(final T[] data)320     public static <T extends FieldElement<T>> FieldVector<T> createFieldVector(final T[] data) {
321         return new ArrayFieldVector<T>(data, true);
322     }
323 
324     /**
325      * Creates a row {@link RealMatrix} using the data from the input
326      * array.
327      *
328      * @param rowData the input row data
329      * @return a 1 x rowData.length RealMatrix
330      * @throws IllegalArgumentException if <code>rowData</code> is empty
331      * @throws NullPointerException if <code>rowData</code>is null
332      */
createRowRealMatrix(double[] rowData)333     public static RealMatrix createRowRealMatrix(double[] rowData) {
334         final int nCols = rowData.length;
335         final RealMatrix m = createRealMatrix(1, nCols);
336         for (int i = 0; i < nCols; ++i) {
337             m.setEntry(0, i, rowData[i]);
338         }
339         return m;
340     }
341 
342     /**
343      * Creates a row {@link FieldMatrix} using the data from the input
344      * array.
345      *
346      * @param <T> the type of the field elements
347      * @param rowData the input row data
348      * @return a 1 x rowData.length FieldMatrix
349      * @throws IllegalArgumentException if <code>rowData</code> is empty
350      * @throws NullPointerException if <code>rowData</code>is null
351      */
352     public static <T extends FieldElement<T>> FieldMatrix<T>
createRowFieldMatrix(final T[] rowData)353         createRowFieldMatrix(final T[] rowData) {
354         final int nCols = rowData.length;
355         if (nCols == 0) {
356             throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_COLUMN);
357         }
358         final FieldMatrix<T> m = createFieldMatrix(rowData[0].getField(), 1, nCols);
359         for (int i = 0; i < nCols; ++i) {
360             m.setEntry(0, i, rowData[i]);
361         }
362         return m;
363     }
364 
365     /**
366      * Creates a row {@link BigMatrix} using the data from the input
367      * array.
368      *
369      * @param rowData the input row data
370      * @return a 1 x rowData.length BigMatrix
371      * @throws IllegalArgumentException if <code>rowData</code> is empty
372      * @throws NullPointerException if <code>rowData</code>is null
373      * @deprecated since 2.0 replaced by {@link #createRowFieldMatrix(FieldElement[])}
374      */
375     @Deprecated
createRowBigMatrix(double[] rowData)376     public static BigMatrix createRowBigMatrix(double[] rowData) {
377         final int nCols = rowData.length;
378         final BigDecimal[][] data = new BigDecimal[1][nCols];
379         for (int i = 0; i < nCols; ++i) {
380             data[0][i] = new BigDecimal(rowData[i]);
381         }
382         return new BigMatrixImpl(data, false);
383     }
384 
385     /**
386      * Creates a row {@link BigMatrix} using the data from the input
387      * array.
388      *
389      * @param rowData the input row data
390      * @return a 1 x rowData.length BigMatrix
391      * @throws IllegalArgumentException if <code>rowData</code> is empty
392      * @throws NullPointerException if <code>rowData</code>is null
393      * @deprecated since 2.0 replaced by {@link #createRowFieldMatrix(FieldElement[])}
394      */
395     @Deprecated
createRowBigMatrix(BigDecimal[] rowData)396     public static BigMatrix createRowBigMatrix(BigDecimal[] rowData) {
397         final int nCols = rowData.length;
398         final BigDecimal[][] data = new BigDecimal[1][nCols];
399         System.arraycopy(rowData, 0, data[0], 0, nCols);
400         return new BigMatrixImpl(data, false);
401     }
402 
403     /**
404      * Creates a row {@link BigMatrix} using the data from the input
405      * array.
406      *
407      * @param rowData the input row data
408      * @return a 1 x rowData.length BigMatrix
409      * @throws IllegalArgumentException if <code>rowData</code> is empty
410      * @throws NullPointerException if <code>rowData</code>is null
411      * @deprecated since 2.0 replaced by {@link #createRowFieldMatrix(FieldElement[])}
412      */
413     @Deprecated
createRowBigMatrix(String[] rowData)414     public static BigMatrix createRowBigMatrix(String[] rowData) {
415         final int nCols = rowData.length;
416         final BigDecimal[][] data = new BigDecimal[1][nCols];
417         for (int i = 0; i < nCols; ++i) {
418             data[0][i] = new BigDecimal(rowData[i]);
419         }
420         return new BigMatrixImpl(data, false);
421     }
422 
423     /**
424      * Creates a column {@link RealMatrix} using the data from the input
425      * array.
426      *
427      * @param columnData  the input column data
428      * @return a columnData x 1 RealMatrix
429      * @throws IllegalArgumentException if <code>columnData</code> is empty
430      * @throws NullPointerException if <code>columnData</code>is null
431      */
createColumnRealMatrix(double[] columnData)432     public static RealMatrix createColumnRealMatrix(double[] columnData) {
433         final int nRows = columnData.length;
434         final RealMatrix m = createRealMatrix(nRows, 1);
435         for (int i = 0; i < nRows; ++i) {
436             m.setEntry(i, 0, columnData[i]);
437         }
438         return m;
439     }
440 
441     /**
442      * Creates a column {@link FieldMatrix} using the data from the input
443      * array.
444      *
445      * @param <T> the type of the field elements
446      * @param columnData  the input column data
447      * @return a columnData x 1 FieldMatrix
448      * @throws IllegalArgumentException if <code>columnData</code> is empty
449      * @throws NullPointerException if <code>columnData</code>is null
450      */
451     public static <T extends FieldElement<T>> FieldMatrix<T>
createColumnFieldMatrix(final T[] columnData)452         createColumnFieldMatrix(final T[] columnData) {
453         final int nRows = columnData.length;
454         if (nRows == 0) {
455             throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_ROW);
456         }
457         final FieldMatrix<T> m = createFieldMatrix(columnData[0].getField(), nRows, 1);
458         for (int i = 0; i < nRows; ++i) {
459             m.setEntry(i, 0, columnData[i]);
460         }
461         return m;
462     }
463 
464     /**
465      * Creates a column {@link BigMatrix} using the data from the input
466      * array.
467      *
468      * @param columnData  the input column data
469      * @return a columnData x 1 BigMatrix
470      * @throws IllegalArgumentException if <code>columnData</code> is empty
471      * @throws NullPointerException if <code>columnData</code>is null
472      * @deprecated since 2.0 replaced by {@link #createColumnFieldMatrix(FieldElement[])}
473      */
474     @Deprecated
createColumnBigMatrix(double[] columnData)475     public static BigMatrix createColumnBigMatrix(double[] columnData) {
476         final int nRows = columnData.length;
477         final BigDecimal[][] data = new BigDecimal[nRows][1];
478         for (int row = 0; row < nRows; row++) {
479             data[row][0] = new BigDecimal(columnData[row]);
480         }
481         return new BigMatrixImpl(data, false);
482     }
483 
484     /**
485      * Creates a column {@link BigMatrix} using the data from the input
486      * array.
487      *
488      * @param columnData  the input column data
489      * @return a columnData x 1 BigMatrix
490      * @throws IllegalArgumentException if <code>columnData</code> is empty
491      * @throws NullPointerException if <code>columnData</code>is null
492      * @deprecated since 2.0 replaced by {@link #createColumnFieldMatrix(FieldElement[])}
493      */
494     @Deprecated
createColumnBigMatrix(BigDecimal[] columnData)495     public static BigMatrix createColumnBigMatrix(BigDecimal[] columnData) {
496         final int nRows = columnData.length;
497         final BigDecimal[][] data = new BigDecimal[nRows][1];
498         for (int row = 0; row < nRows; row++) {
499             data[row][0] = columnData[row];
500         }
501         return new BigMatrixImpl(data, false);
502     }
503 
504     /**
505      * Creates a column {@link BigMatrix} using the data from the input
506      * array.
507      *
508      * @param columnData  the input column data
509      * @return a columnData x 1 BigMatrix
510      * @throws IllegalArgumentException if <code>columnData</code> is empty
511      * @throws NullPointerException if <code>columnData</code>is null
512      * @deprecated since 2.0 replaced by {@link #createColumnFieldMatrix(FieldElement[])}
513      */
514     @Deprecated
createColumnBigMatrix(String[] columnData)515     public static BigMatrix createColumnBigMatrix(String[] columnData) {
516         int nRows = columnData.length;
517         final BigDecimal[][] data = new BigDecimal[nRows][1];
518         for (int row = 0; row < nRows; row++) {
519             data[row][0] = new BigDecimal(columnData[row]);
520         }
521         return new BigMatrixImpl(data, false);
522     }
523 
524     /**
525      * Check if a row index is valid.
526      * @param m matrix containing the submatrix
527      * @param row row index to check
528      * @exception MatrixIndexException if index is not valid
529      */
checkRowIndex(final AnyMatrix m, final int row)530     public static void checkRowIndex(final AnyMatrix m, final int row) {
531         if (row < 0 || row >= m.getRowDimension()) {
532             throw new MatrixIndexException(LocalizedFormats.ROW_INDEX_OUT_OF_RANGE,
533                                            row, 0, m.getRowDimension() - 1);
534         }
535     }
536 
537     /**
538      * Check if a column index is valid.
539      * @param m matrix containing the submatrix
540      * @param column column index to check
541      * @exception MatrixIndexException if index is not valid
542      */
checkColumnIndex(final AnyMatrix m, final int column)543     public static void checkColumnIndex(final AnyMatrix m, final int column)
544         throws MatrixIndexException {
545         if (column < 0 || column >= m.getColumnDimension()) {
546             throw new MatrixIndexException(LocalizedFormats.COLUMN_INDEX_OUT_OF_RANGE,
547                                            column, 0, m.getColumnDimension() - 1);
548         }
549     }
550 
551     /**
552      * Check if submatrix ranges indices are valid.
553      * Rows and columns are indicated counting from 0 to n-1.
554      *
555      * @param m matrix containing the submatrix
556      * @param startRow Initial row index
557      * @param endRow Final row index
558      * @param startColumn Initial column index
559      * @param endColumn Final column index
560      * @exception MatrixIndexException  if the indices are not valid
561      */
checkSubMatrixIndex(final AnyMatrix m, final int startRow, final int endRow, final int startColumn, final int endColumn)562     public static void checkSubMatrixIndex(final AnyMatrix m,
563                                            final int startRow, final int endRow,
564                                            final int startColumn, final int endColumn) {
565         checkRowIndex(m, startRow);
566         checkRowIndex(m, endRow);
567         if (startRow > endRow) {
568             throw new MatrixIndexException(LocalizedFormats.INITIAL_ROW_AFTER_FINAL_ROW,
569                                            startRow, endRow);
570         }
571 
572         checkColumnIndex(m, startColumn);
573         checkColumnIndex(m, endColumn);
574         if (startColumn > endColumn) {
575             throw new MatrixIndexException(LocalizedFormats.INITIAL_COLUMN_AFTER_FINAL_COLUMN,
576                                            startColumn, endColumn);
577         }
578 
579 
580     }
581 
582     /**
583      * Check if submatrix ranges indices are valid.
584      * Rows and columns are indicated counting from 0 to n-1.
585      *
586      * @param m matrix containing the submatrix
587      * @param selectedRows Array of row indices.
588      * @param selectedColumns Array of column indices.
589      * @exception MatrixIndexException if row or column selections are not valid
590      */
checkSubMatrixIndex(final AnyMatrix m, final int[] selectedRows, final int[] selectedColumns)591     public static void checkSubMatrixIndex(final AnyMatrix m,
592                                            final int[] selectedRows, final int[] selectedColumns)
593         throws MatrixIndexException {
594         if (selectedRows.length * selectedColumns.length == 0) {
595             if (selectedRows.length == 0) {
596                 throw new MatrixIndexException(LocalizedFormats.EMPTY_SELECTED_ROW_INDEX_ARRAY);
597             }
598             throw new MatrixIndexException(LocalizedFormats.EMPTY_SELECTED_COLUMN_INDEX_ARRAY);
599         }
600 
601         for (final int row : selectedRows) {
602             checkRowIndex(m, row);
603         }
604         for (final int column : selectedColumns) {
605             checkColumnIndex(m, column);
606         }
607     }
608 
609     /**
610      * Check if matrices are addition compatible
611      * @param left left hand side matrix
612      * @param right right hand side matrix
613      * @exception IllegalArgumentException if matrices are not addition compatible
614      */
checkAdditionCompatible(final AnyMatrix left, final AnyMatrix right)615     public static void checkAdditionCompatible(final AnyMatrix left, final AnyMatrix right)
616         throws IllegalArgumentException {
617         if ((left.getRowDimension()    != right.getRowDimension()) ||
618             (left.getColumnDimension() != right.getColumnDimension())) {
619             throw MathRuntimeException.createIllegalArgumentException(
620                     LocalizedFormats.NOT_ADDITION_COMPATIBLE_MATRICES,
621                     left.getRowDimension(), left.getColumnDimension(),
622                     right.getRowDimension(), right.getColumnDimension());
623         }
624     }
625 
626     /**
627      * Check if matrices are subtraction compatible
628      * @param left left hand side matrix
629      * @param right right hand side matrix
630      * @exception IllegalArgumentException if matrices are not subtraction compatible
631      */
checkSubtractionCompatible(final AnyMatrix left, final AnyMatrix right)632     public static void checkSubtractionCompatible(final AnyMatrix left, final AnyMatrix right)
633         throws IllegalArgumentException {
634         if ((left.getRowDimension()    != right.getRowDimension()) ||
635             (left.getColumnDimension() != right.getColumnDimension())) {
636             throw MathRuntimeException.createIllegalArgumentException(
637                     LocalizedFormats.NOT_SUBTRACTION_COMPATIBLE_MATRICES,
638                     left.getRowDimension(), left.getColumnDimension(),
639                     right.getRowDimension(), right.getColumnDimension());
640         }
641     }
642 
643     /**
644      * Check if matrices are multiplication compatible
645      * @param left left hand side matrix
646      * @param right right hand side matrix
647      * @exception IllegalArgumentException if matrices are not multiplication compatible
648      */
checkMultiplicationCompatible(final AnyMatrix left, final AnyMatrix right)649     public static void checkMultiplicationCompatible(final AnyMatrix left, final AnyMatrix right)
650         throws IllegalArgumentException {
651         if (left.getColumnDimension() != right.getRowDimension()) {
652             throw MathRuntimeException.createIllegalArgumentException(
653                     LocalizedFormats.NOT_MULTIPLICATION_COMPATIBLE_MATRICES,
654                     left.getRowDimension(), left.getColumnDimension(),
655                     right.getRowDimension(), right.getColumnDimension());
656         }
657     }
658 
659     /**
660      * Convert a {@link FieldMatrix}/{@link Fraction} matrix to a {@link RealMatrix}.
661      * @param m matrix to convert
662      * @return converted matrix
663      */
fractionMatrixToRealMatrix(final FieldMatrix<Fraction> m)664     public static Array2DRowRealMatrix fractionMatrixToRealMatrix(final FieldMatrix<Fraction> m) {
665         final FractionMatrixConverter converter = new FractionMatrixConverter();
666         m.walkInOptimizedOrder(converter);
667         return converter.getConvertedMatrix();
668     }
669 
670     /** Converter for {@link FieldMatrix}/{@link Fraction}. */
671     private static class FractionMatrixConverter extends DefaultFieldMatrixPreservingVisitor<Fraction> {
672 
673         /** Converted array. */
674         private double[][] data;
675 
676         /** Simple constructor. */
FractionMatrixConverter()677         public FractionMatrixConverter() {
678             super(Fraction.ZERO);
679         }
680 
681         /** {@inheritDoc} */
682         @Override
start(int rows, int columns, int startRow, int endRow, int startColumn, int endColumn)683         public void start(int rows, int columns,
684                           int startRow, int endRow, int startColumn, int endColumn) {
685             data = new double[rows][columns];
686         }
687 
688         /** {@inheritDoc} */
689         @Override
visit(int row, int column, Fraction value)690         public void visit(int row, int column, Fraction value) {
691             data[row][column] = value.doubleValue();
692         }
693 
694         /** Get the converted matrix.
695          * @return converted matrix
696          */
getConvertedMatrix()697         Array2DRowRealMatrix getConvertedMatrix() {
698             return new Array2DRowRealMatrix(data, false);
699         }
700 
701     }
702 
703     /**
704      * Convert a {@link FieldMatrix}/{@link BigFraction} matrix to a {@link RealMatrix}.
705      * @param m matrix to convert
706      * @return converted matrix
707      */
bigFractionMatrixToRealMatrix(final FieldMatrix<BigFraction> m)708     public static Array2DRowRealMatrix bigFractionMatrixToRealMatrix(final FieldMatrix<BigFraction> m) {
709         final BigFractionMatrixConverter converter = new BigFractionMatrixConverter();
710         m.walkInOptimizedOrder(converter);
711         return converter.getConvertedMatrix();
712     }
713 
714     /** Converter for {@link FieldMatrix}/{@link BigFraction}. */
715     private static class BigFractionMatrixConverter extends DefaultFieldMatrixPreservingVisitor<BigFraction> {
716 
717         /** Converted array. */
718         private double[][] data;
719 
720         /** Simple constructor. */
BigFractionMatrixConverter()721         public BigFractionMatrixConverter() {
722             super(BigFraction.ZERO);
723         }
724 
725         /** {@inheritDoc} */
726         @Override
start(int rows, int columns, int startRow, int endRow, int startColumn, int endColumn)727         public void start(int rows, int columns,
728                           int startRow, int endRow, int startColumn, int endColumn) {
729             data = new double[rows][columns];
730         }
731 
732         /** {@inheritDoc} */
733         @Override
visit(int row, int column, BigFraction value)734         public void visit(int row, int column, BigFraction value) {
735             data[row][column] = value.doubleValue();
736         }
737 
738         /** Get the converted matrix.
739          * @return converted matrix
740          */
getConvertedMatrix()741         Array2DRowRealMatrix getConvertedMatrix() {
742             return new Array2DRowRealMatrix(data, false);
743         }
744 
745     }
746 
747     /** Serialize a {@link RealVector}.
748      * <p>
749      * This method is intended to be called from within a private
750      * <code>writeObject</code> method (after a call to
751      * <code>oos.defaultWriteObject()</code>) in a class that has a
752      * {@link RealVector} field, which should be declared <code>transient</code>.
753      * This way, the default handling does not serialize the vector (the {@link
754      * RealVector} interface is not serializable by default) but this method does
755      * serialize it specifically.
756      * </p>
757      * <p>
758      * The following example shows how a simple class with a name and a real vector
759      * should be written:
760      * <pre><code>
761      * public class NamedVector implements Serializable {
762      *
763      *     private final String name;
764      *     private final transient RealVector coefficients;
765      *
766      *     // omitted constructors, getters ...
767      *
768      *     private void writeObject(ObjectOutputStream oos) throws IOException {
769      *         oos.defaultWriteObject();  // takes care of name field
770      *         MatrixUtils.serializeRealVector(coefficients, oos);
771      *     }
772      *
773      *     private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
774      *         ois.defaultReadObject();  // takes care of name field
775      *         MatrixUtils.deserializeRealVector(this, "coefficients", ois);
776      *     }
777      *
778      * }
779      * </code></pre>
780      * </p>
781      *
782      * @param vector real vector to serialize
783      * @param oos stream where the real vector should be written
784      * @exception IOException if object cannot be written to stream
785      * @see #deserializeRealVector(Object, String, ObjectInputStream)
786      */
serializeRealVector(final RealVector vector, final ObjectOutputStream oos)787     public static void serializeRealVector(final RealVector vector,
788                                            final ObjectOutputStream oos)
789         throws IOException {
790         final int n = vector.getDimension();
791         oos.writeInt(n);
792         for (int i = 0; i < n; ++i) {
793             oos.writeDouble(vector.getEntry(i));
794         }
795     }
796 
797     /** Deserialize  a {@link RealVector} field in a class.
798      * <p>
799      * This method is intended to be called from within a private
800      * <code>readObject</code> method (after a call to
801      * <code>ois.defaultReadObject()</code>) in a class that has a
802      * {@link RealVector} field, which should be declared <code>transient</code>.
803      * This way, the default handling does not deserialize the vector (the {@link
804      * RealVector} interface is not serializable by default) but this method does
805      * deserialize it specifically.
806      * </p>
807      * @param instance instance in which the field must be set up
808      * @param fieldName name of the field within the class (may be private and final)
809      * @param ois stream from which the real vector should be read
810      * @exception ClassNotFoundException if a class in the stream cannot be found
811      * @exception IOException if object cannot be read from the stream
812      * @see #serializeRealVector(RealVector, ObjectOutputStream)
813      */
deserializeRealVector(final Object instance, final String fieldName, final ObjectInputStream ois)814     public static void deserializeRealVector(final Object instance,
815                                              final String fieldName,
816                                              final ObjectInputStream ois)
817       throws ClassNotFoundException, IOException {
818         try {
819 
820             // read the vector data
821             final int n = ois.readInt();
822             final double[] data = new double[n];
823             for (int i = 0; i < n; ++i) {
824                 data[i] = ois.readDouble();
825             }
826 
827             // create the instance
828             final RealVector vector = new ArrayRealVector(data, false);
829 
830             // set up the field
831             final java.lang.reflect.Field f =
832                 instance.getClass().getDeclaredField(fieldName);
833             f.setAccessible(true);
834             f.set(instance, vector);
835 
836         } catch (NoSuchFieldException nsfe) {
837             IOException ioe = new IOException();
838             ioe.initCause(nsfe);
839             throw ioe;
840         } catch (IllegalAccessException iae) {
841             IOException ioe = new IOException();
842             ioe.initCause(iae);
843             throw ioe;
844         }
845 
846     }
847 
848     /** Serialize a {@link RealMatrix}.
849      * <p>
850      * This method is intended to be called from within a private
851      * <code>writeObject</code> method (after a call to
852      * <code>oos.defaultWriteObject()</code>) in a class that has a
853      * {@link RealMatrix} field, which should be declared <code>transient</code>.
854      * This way, the default handling does not serialize the matrix (the {@link
855      * RealMatrix} interface is not serializable by default) but this method does
856      * serialize it specifically.
857      * </p>
858      * <p>
859      * The following example shows how a simple class with a name and a real matrix
860      * should be written:
861      * <pre><code>
862      * public class NamedMatrix implements Serializable {
863      *
864      *     private final String name;
865      *     private final transient RealMatrix coefficients;
866      *
867      *     // omitted constructors, getters ...
868      *
869      *     private void writeObject(ObjectOutputStream oos) throws IOException {
870      *         oos.defaultWriteObject();  // takes care of name field
871      *         MatrixUtils.serializeRealMatrix(coefficients, oos);
872      *     }
873      *
874      *     private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
875      *         ois.defaultReadObject();  // takes care of name field
876      *         MatrixUtils.deserializeRealMatrix(this, "coefficients", ois);
877      *     }
878      *
879      * }
880      * </code></pre>
881      * </p>
882      *
883      * @param matrix real matrix to serialize
884      * @param oos stream where the real matrix should be written
885      * @exception IOException if object cannot be written to stream
886      * @see #deserializeRealMatrix(Object, String, ObjectInputStream)
887      */
serializeRealMatrix(final RealMatrix matrix, final ObjectOutputStream oos)888     public static void serializeRealMatrix(final RealMatrix matrix,
889                                            final ObjectOutputStream oos)
890         throws IOException {
891         final int n = matrix.getRowDimension();
892         final int m = matrix.getColumnDimension();
893         oos.writeInt(n);
894         oos.writeInt(m);
895         for (int i = 0; i < n; ++i) {
896             for (int j = 0; j < m; ++j) {
897                 oos.writeDouble(matrix.getEntry(i, j));
898             }
899         }
900     }
901 
902     /** Deserialize  a {@link RealMatrix} field in a class.
903      * <p>
904      * This method is intended to be called from within a private
905      * <code>readObject</code> method (after a call to
906      * <code>ois.defaultReadObject()</code>) in a class that has a
907      * {@link RealMatrix} field, which should be declared <code>transient</code>.
908      * This way, the default handling does not deserialize the matrix (the {@link
909      * RealMatrix} interface is not serializable by default) but this method does
910      * deserialize it specifically.
911      * </p>
912      * @param instance instance in which the field must be set up
913      * @param fieldName name of the field within the class (may be private and final)
914      * @param ois stream from which the real matrix should be read
915      * @exception ClassNotFoundException if a class in the stream cannot be found
916      * @exception IOException if object cannot be read from the stream
917      * @see #serializeRealMatrix(RealMatrix, ObjectOutputStream)
918      */
deserializeRealMatrix(final Object instance, final String fieldName, final ObjectInputStream ois)919     public static void deserializeRealMatrix(final Object instance,
920                                              final String fieldName,
921                                              final ObjectInputStream ois)
922       throws ClassNotFoundException, IOException {
923         try {
924 
925             // read the matrix data
926             final int n = ois.readInt();
927             final int m = ois.readInt();
928             final double[][] data = new double[n][m];
929             for (int i = 0; i < n; ++i) {
930                 final double[] dataI = data[i];
931                 for (int j = 0; j < m; ++j) {
932                     dataI[j] = ois.readDouble();
933                 }
934             }
935 
936             // create the instance
937             final RealMatrix matrix = new Array2DRowRealMatrix(data, false);
938 
939             // set up the field
940             final java.lang.reflect.Field f =
941                 instance.getClass().getDeclaredField(fieldName);
942             f.setAccessible(true);
943             f.set(instance, matrix);
944 
945         } catch (NoSuchFieldException nsfe) {
946             IOException ioe = new IOException();
947             ioe.initCause(nsfe);
948             throw ioe;
949         } catch (IllegalAccessException iae) {
950             IOException ioe = new IOException();
951             ioe.initCause(iae);
952             throw ioe;
953         }
954 
955     }
956 
957 }
958