blob: 4917b89638847db81bf5843d57a397951755976d [file] [log] [blame]
Raymonddee08492015-04-02 10:43:13 -07001/*
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
18package org.apache.commons.math.linear;
19
20import java.io.IOException;
21import java.io.ObjectInputStream;
22import java.io.ObjectOutputStream;
23import java.lang.reflect.Array;
24import java.math.BigDecimal;
25import java.util.Arrays;
26
27import org.apache.commons.math.Field;
28import org.apache.commons.math.FieldElement;
29import org.apache.commons.math.MathRuntimeException;
30import org.apache.commons.math.exception.util.LocalizedFormats;
31import org.apache.commons.math.fraction.BigFraction;
32import 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 */
39public class MatrixUtils {
40
41 /**
42 * Private constructor.
43 */
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 */
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 */
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 */
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 */
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 */
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>
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
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 */
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>
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
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
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
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
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 */
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 */
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 */
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>
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
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
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
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 */
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>
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
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
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
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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. */
677 public FractionMatrixConverter() {
678 super(Fraction.ZERO);
679 }
680
681 /** {@inheritDoc} */
682 @Override
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
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 */
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 */
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. */
721 public BigFractionMatrixConverter() {
722 super(BigFraction.ZERO);
723 }
724
725 /** {@inheritDoc} */
726 @Override
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
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 */
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 */
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 */
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 */
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 */
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}