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×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×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×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×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