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.lang.reflect.Array; 21 import java.util.Arrays; 22 23 import org.apache.commons.math.Field; 24 import org.apache.commons.math.FieldElement; 25 import org.apache.commons.math.MathRuntimeException; 26 import org.apache.commons.math.linear.MatrixVisitorException; 27 import org.apache.commons.math.exception.util.LocalizedFormats; 28 29 /** 30 * Basic implementation of {@link FieldMatrix} methods regardless of the underlying storage. 31 * <p>All the methods implemented here use {@link #getEntry(int, int)} to access 32 * matrix elements. Derived class can provide faster implementations. </p> 33 * 34 * @param <T> the type of the field elements 35 * @version $Revision: 1073158 $ $Date: 2011-02-21 22:46:52 +0100 (lun. 21 févr. 2011) $ 36 * @since 2.0 37 */ 38 public abstract class AbstractFieldMatrix<T extends FieldElement<T>> implements FieldMatrix<T> { 39 40 /** Field to which the elements belong. */ 41 private final Field<T> field; 42 43 /** 44 * Constructor for use with Serializable 45 */ AbstractFieldMatrix()46 protected AbstractFieldMatrix() { 47 field = null; 48 } 49 50 /** 51 * Creates a matrix with no data 52 * @param field field to which the elements belong 53 */ AbstractFieldMatrix(final Field<T> field)54 protected AbstractFieldMatrix(final Field<T> field) { 55 this.field = field; 56 } 57 58 /** 59 * Create a new FieldMatrix<T> with the supplied row and column dimensions. 60 * 61 * @param field field to which the elements belong 62 * @param rowDimension the number of rows in the new matrix 63 * @param columnDimension the number of columns in the new matrix 64 * @throws IllegalArgumentException if row or column dimension is not positive 65 */ AbstractFieldMatrix(final Field<T> field, final int rowDimension, final int columnDimension)66 protected AbstractFieldMatrix(final Field<T> field, 67 final int rowDimension, final int columnDimension) 68 throws IllegalArgumentException { 69 if (rowDimension < 1 ) { 70 throw MathRuntimeException.createIllegalArgumentException( 71 LocalizedFormats.INSUFFICIENT_DIMENSION, rowDimension, 1); 72 } 73 if (columnDimension < 1) { 74 throw MathRuntimeException.createIllegalArgumentException( 75 LocalizedFormats.INSUFFICIENT_DIMENSION, columnDimension, 1); 76 } 77 this.field = field; 78 } 79 80 /** 81 * Get the elements type from an array. 82 * @param <T> the type of the field elements 83 * @param d data array 84 * @return field to which array elements belong 85 * @exception IllegalArgumentException if array is empty 86 */ extractField(final T[][] d)87 protected static <T extends FieldElement<T>> Field<T> extractField(final T[][] d) 88 throws IllegalArgumentException { 89 if (d.length == 0) { 90 throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_ROW); 91 } 92 if (d[0].length == 0) { 93 throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_COLUMN); 94 } 95 return d[0][0].getField(); 96 } 97 98 /** 99 * Get the elements type from an array. 100 * @param <T> the type of the field elements 101 * @param d data array 102 * @return field to which array elements belong 103 * @exception IllegalArgumentException if array is empty 104 */ extractField(final T[] d)105 protected static <T extends FieldElement<T>> Field<T> extractField(final T[] d) 106 throws IllegalArgumentException { 107 if (d.length == 0) { 108 throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_ROW); 109 } 110 return d[0].getField(); 111 } 112 113 /** Build an array of elements. 114 * <p> 115 * Complete arrays are filled with field.getZero() 116 * </p> 117 * @param <T> the type of the field elements 118 * @param field field to which array elements belong 119 * @param rows number of rows 120 * @param columns number of columns (may be negative to build partial 121 * arrays in the same way <code>new Field[rows][]</code> works) 122 * @return a new array 123 */ 124 @SuppressWarnings("unchecked") buildArray(final Field<T> field, final int rows, final int columns)125 protected static <T extends FieldElement<T>> T[][] buildArray(final Field<T> field, 126 final int rows, 127 final int columns) { 128 if (columns < 0) { 129 T[] dummyRow = (T[]) Array.newInstance(field.getZero().getClass(), 0); 130 return (T[][]) Array.newInstance(dummyRow.getClass(), rows); 131 } 132 T[][] array = 133 (T[][]) Array.newInstance(field.getZero().getClass(), new int[] { rows, columns }); 134 for (int i = 0; i < array.length; ++i) { 135 Arrays.fill(array[i], field.getZero()); 136 } 137 return array; 138 } 139 140 /** Build an array of elements. 141 * <p> 142 * Arrays are filled with field.getZero() 143 * </p> 144 * @param <T> the type of the field elements 145 * @param field field to which array elements belong 146 * @param length of the array 147 * @return a new array 148 */ buildArray(final Field<T> field, final int length)149 protected static <T extends FieldElement<T>> T[] buildArray(final Field<T> field, 150 final int length) { 151 @SuppressWarnings("unchecked") // OK because field must be correct class 152 T[] array = (T[]) Array.newInstance(field.getZero().getClass(), length); 153 Arrays.fill(array, field.getZero()); 154 return array; 155 } 156 157 /** {@inheritDoc} */ getField()158 public Field<T> getField() { 159 return field; 160 } 161 162 /** {@inheritDoc} */ createMatrix(final int rowDimension, final int columnDimension)163 public abstract FieldMatrix<T> createMatrix(final int rowDimension, final int columnDimension) 164 throws IllegalArgumentException; 165 166 /** {@inheritDoc} */ copy()167 public abstract FieldMatrix<T> copy(); 168 169 /** {@inheritDoc} */ add(FieldMatrix<T> m)170 public FieldMatrix<T> add(FieldMatrix<T> m) throws IllegalArgumentException { 171 172 // safety check 173 checkAdditionCompatible(m); 174 175 final int rowCount = getRowDimension(); 176 final int columnCount = getColumnDimension(); 177 final FieldMatrix<T> out = createMatrix(rowCount, columnCount); 178 for (int row = 0; row < rowCount; ++row) { 179 for (int col = 0; col < columnCount; ++col) { 180 out.setEntry(row, col, getEntry(row, col).add(m.getEntry(row, col))); 181 } 182 } 183 184 return out; 185 186 } 187 188 /** {@inheritDoc} */ subtract(final FieldMatrix<T> m)189 public FieldMatrix<T> subtract(final FieldMatrix<T> m) throws IllegalArgumentException { 190 191 // safety check 192 checkSubtractionCompatible(m); 193 194 final int rowCount = getRowDimension(); 195 final int columnCount = getColumnDimension(); 196 final FieldMatrix<T> out = createMatrix(rowCount, columnCount); 197 for (int row = 0; row < rowCount; ++row) { 198 for (int col = 0; col < columnCount; ++col) { 199 out.setEntry(row, col, getEntry(row, col).subtract(m.getEntry(row, col))); 200 } 201 } 202 203 return out; 204 205 } 206 207 /** {@inheritDoc} */ scalarAdd(final T d)208 public FieldMatrix<T> scalarAdd(final T d) { 209 210 final int rowCount = getRowDimension(); 211 final int columnCount = getColumnDimension(); 212 final FieldMatrix<T> out = createMatrix(rowCount, columnCount); 213 for (int row = 0; row < rowCount; ++row) { 214 for (int col = 0; col < columnCount; ++col) { 215 out.setEntry(row, col, getEntry(row, col).add(d)); 216 } 217 } 218 219 return out; 220 221 } 222 223 /** {@inheritDoc} */ scalarMultiply(final T d)224 public FieldMatrix<T> scalarMultiply(final T d) { 225 226 final int rowCount = getRowDimension(); 227 final int columnCount = getColumnDimension(); 228 final FieldMatrix<T> out = createMatrix(rowCount, columnCount); 229 for (int row = 0; row < rowCount; ++row) { 230 for (int col = 0; col < columnCount; ++col) { 231 out.setEntry(row, col, getEntry(row, col).multiply(d)); 232 } 233 } 234 235 return out; 236 237 } 238 239 /** {@inheritDoc} */ multiply(final FieldMatrix<T> m)240 public FieldMatrix<T> multiply(final FieldMatrix<T> m) 241 throws IllegalArgumentException { 242 243 // safety check 244 checkMultiplicationCompatible(m); 245 246 final int nRows = getRowDimension(); 247 final int nCols = m.getColumnDimension(); 248 final int nSum = getColumnDimension(); 249 final FieldMatrix<T> out = createMatrix(nRows, nCols); 250 for (int row = 0; row < nRows; ++row) { 251 for (int col = 0; col < nCols; ++col) { 252 T sum = field.getZero(); 253 for (int i = 0; i < nSum; ++i) { 254 sum = sum.add(getEntry(row, i).multiply(m.getEntry(i, col))); 255 } 256 out.setEntry(row, col, sum); 257 } 258 } 259 260 return out; 261 262 } 263 264 /** {@inheritDoc} */ preMultiply(final FieldMatrix<T> m)265 public FieldMatrix<T> preMultiply(final FieldMatrix<T> m) 266 throws IllegalArgumentException { 267 return m.multiply(this); 268 } 269 270 /** {@inheritDoc} */ getData()271 public T[][] getData() { 272 273 final T[][] data = buildArray(field, getRowDimension(), getColumnDimension()); 274 275 for (int i = 0; i < data.length; ++i) { 276 final T[] dataI = data[i]; 277 for (int j = 0; j < dataI.length; ++j) { 278 dataI[j] = getEntry(i, j); 279 } 280 } 281 282 return data; 283 284 } 285 286 /** {@inheritDoc} */ getSubMatrix(final int startRow, final int endRow, final int startColumn, final int endColumn)287 public FieldMatrix<T> getSubMatrix(final int startRow, final int endRow, 288 final int startColumn, final int endColumn) 289 throws MatrixIndexException { 290 291 checkSubMatrixIndex(startRow, endRow, startColumn, endColumn); 292 293 final FieldMatrix<T> subMatrix = 294 createMatrix(endRow - startRow + 1, endColumn - startColumn + 1); 295 for (int i = startRow; i <= endRow; ++i) { 296 for (int j = startColumn; j <= endColumn; ++j) { 297 subMatrix.setEntry(i - startRow, j - startColumn, getEntry(i, j)); 298 } 299 } 300 301 return subMatrix; 302 303 } 304 305 /** {@inheritDoc} */ getSubMatrix(final int[] selectedRows, final int[] selectedColumns)306 public FieldMatrix<T> getSubMatrix(final int[] selectedRows, final int[] selectedColumns) 307 throws MatrixIndexException { 308 309 // safety checks 310 checkSubMatrixIndex(selectedRows, selectedColumns); 311 312 // copy entries 313 final FieldMatrix<T> subMatrix = 314 createMatrix(selectedRows.length, selectedColumns.length); 315 subMatrix.walkInOptimizedOrder(new DefaultFieldMatrixChangingVisitor<T>(field.getZero()) { 316 317 /** {@inheritDoc} */ 318 @Override 319 public T visit(final int row, final int column, final T value) { 320 return getEntry(selectedRows[row], selectedColumns[column]); 321 } 322 323 }); 324 325 return subMatrix; 326 327 } 328 329 /** {@inheritDoc} */ copySubMatrix(final int startRow, final int endRow, final int startColumn, final int endColumn, final T[][] destination)330 public void copySubMatrix(final int startRow, final int endRow, 331 final int startColumn, final int endColumn, 332 final T[][] destination) 333 throws MatrixIndexException, IllegalArgumentException { 334 335 // safety checks 336 checkSubMatrixIndex(startRow, endRow, startColumn, endColumn); 337 final int rowsCount = endRow + 1 - startRow; 338 final int columnsCount = endColumn + 1 - startColumn; 339 if ((destination.length < rowsCount) || (destination[0].length < columnsCount)) { 340 throw MathRuntimeException.createIllegalArgumentException( 341 LocalizedFormats.DIMENSIONS_MISMATCH_2x2, 342 destination.length, destination[0].length, 343 rowsCount, columnsCount); 344 } 345 346 // copy entries 347 walkInOptimizedOrder(new DefaultFieldMatrixPreservingVisitor<T>(field.getZero()) { 348 349 /** Initial row index. */ 350 private int startRow; 351 352 /** Initial column index. */ 353 private int startColumn; 354 355 /** {@inheritDoc} */ 356 @Override 357 public void start(final int rows, final int columns, 358 final int startRow, final int endRow, 359 final int startColumn, final int endColumn) { 360 this.startRow = startRow; 361 this.startColumn = startColumn; 362 } 363 364 /** {@inheritDoc} */ 365 @Override 366 public void visit(final int row, final int column, final T value) { 367 destination[row - startRow][column - startColumn] = value; 368 } 369 370 }, startRow, endRow, startColumn, endColumn); 371 372 } 373 374 /** {@inheritDoc} */ copySubMatrix(int[] selectedRows, int[] selectedColumns, T[][] destination)375 public void copySubMatrix(int[] selectedRows, int[] selectedColumns, T[][] destination) 376 throws MatrixIndexException, IllegalArgumentException { 377 378 // safety checks 379 checkSubMatrixIndex(selectedRows, selectedColumns); 380 if ((destination.length < selectedRows.length) || 381 (destination[0].length < selectedColumns.length)) { 382 throw MathRuntimeException.createIllegalArgumentException( 383 LocalizedFormats.DIMENSIONS_MISMATCH_2x2, 384 destination.length, destination[0].length, 385 selectedRows.length, selectedColumns.length); 386 } 387 388 // copy entries 389 for (int i = 0; i < selectedRows.length; i++) { 390 final T[] destinationI = destination[i]; 391 for (int j = 0; j < selectedColumns.length; j++) { 392 destinationI[j] = getEntry(selectedRows[i], selectedColumns[j]); 393 } 394 } 395 396 } 397 398 /** {@inheritDoc} */ setSubMatrix(final T[][] subMatrix, final int row, final int column)399 public void setSubMatrix(final T[][] subMatrix, final int row, final int column) 400 throws MatrixIndexException { 401 402 final int nRows = subMatrix.length; 403 if (nRows == 0) { 404 throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_ROW); 405 } 406 407 final int nCols = subMatrix[0].length; 408 if (nCols == 0) { 409 throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_COLUMN); 410 } 411 412 for (int r = 1; r < nRows; ++r) { 413 if (subMatrix[r].length != nCols) { 414 throw MathRuntimeException.createIllegalArgumentException( 415 LocalizedFormats.DIFFERENT_ROWS_LENGTHS, 416 nCols, subMatrix[r].length); 417 } 418 } 419 420 checkRowIndex(row); 421 checkColumnIndex(column); 422 checkRowIndex(nRows + row - 1); 423 checkColumnIndex(nCols + column - 1); 424 425 for (int i = 0; i < nRows; ++i) { 426 for (int j = 0; j < nCols; ++j) { 427 setEntry(row + i, column + j, subMatrix[i][j]); 428 } 429 } 430 431 } 432 433 /** {@inheritDoc} */ getRowMatrix(final int row)434 public FieldMatrix<T> getRowMatrix(final int row) 435 throws MatrixIndexException { 436 437 checkRowIndex(row); 438 final int nCols = getColumnDimension(); 439 final FieldMatrix<T> out = createMatrix(1, nCols); 440 for (int i = 0; i < nCols; ++i) { 441 out.setEntry(0, i, getEntry(row, i)); 442 } 443 444 return out; 445 446 } 447 448 /** {@inheritDoc} */ setRowMatrix(final int row, final FieldMatrix<T> matrix)449 public void setRowMatrix(final int row, final FieldMatrix<T> matrix) 450 throws MatrixIndexException, InvalidMatrixException { 451 452 checkRowIndex(row); 453 final int nCols = getColumnDimension(); 454 if ((matrix.getRowDimension() != 1) || 455 (matrix.getColumnDimension() != nCols)) { 456 throw new InvalidMatrixException( 457 LocalizedFormats.DIMENSIONS_MISMATCH_2x2, 458 matrix.getRowDimension(), matrix.getColumnDimension(), 1, nCols); 459 } 460 for (int i = 0; i < nCols; ++i) { 461 setEntry(row, i, matrix.getEntry(0, i)); 462 } 463 464 } 465 466 /** {@inheritDoc} */ getColumnMatrix(final int column)467 public FieldMatrix<T> getColumnMatrix(final int column) 468 throws MatrixIndexException { 469 470 checkColumnIndex(column); 471 final int nRows = getRowDimension(); 472 final FieldMatrix<T> out = createMatrix(nRows, 1); 473 for (int i = 0; i < nRows; ++i) { 474 out.setEntry(i, 0, getEntry(i, column)); 475 } 476 477 return out; 478 479 } 480 481 /** {@inheritDoc} */ setColumnMatrix(final int column, final FieldMatrix<T> matrix)482 public void setColumnMatrix(final int column, final FieldMatrix<T> matrix) 483 throws MatrixIndexException, InvalidMatrixException { 484 485 checkColumnIndex(column); 486 final int nRows = getRowDimension(); 487 if ((matrix.getRowDimension() != nRows) || 488 (matrix.getColumnDimension() != 1)) { 489 throw new InvalidMatrixException( 490 LocalizedFormats.DIMENSIONS_MISMATCH_2x2, 491 matrix.getRowDimension(), matrix.getColumnDimension(), nRows, 1); 492 } 493 for (int i = 0; i < nRows; ++i) { 494 setEntry(i, column, matrix.getEntry(i, 0)); 495 } 496 497 } 498 499 /** {@inheritDoc} */ getRowVector(final int row)500 public FieldVector<T> getRowVector(final int row) 501 throws MatrixIndexException { 502 return new ArrayFieldVector<T>(getRow(row), false); 503 } 504 505 /** {@inheritDoc} */ setRowVector(final int row, final FieldVector<T> vector)506 public void setRowVector(final int row, final FieldVector<T> vector) 507 throws MatrixIndexException, InvalidMatrixException { 508 509 checkRowIndex(row); 510 final int nCols = getColumnDimension(); 511 if (vector.getDimension() != nCols) { 512 throw new InvalidMatrixException( 513 LocalizedFormats.DIMENSIONS_MISMATCH_2x2, 514 1, vector.getDimension(), 1, nCols); 515 } 516 for (int i = 0; i < nCols; ++i) { 517 setEntry(row, i, vector.getEntry(i)); 518 } 519 520 } 521 522 /** {@inheritDoc} */ getColumnVector(final int column)523 public FieldVector<T> getColumnVector(final int column) 524 throws MatrixIndexException { 525 return new ArrayFieldVector<T>(getColumn(column), false); 526 } 527 528 /** {@inheritDoc} */ setColumnVector(final int column, final FieldVector<T> vector)529 public void setColumnVector(final int column, final FieldVector<T> vector) 530 throws MatrixIndexException, InvalidMatrixException { 531 532 checkColumnIndex(column); 533 final int nRows = getRowDimension(); 534 if (vector.getDimension() != nRows) { 535 throw new InvalidMatrixException( 536 LocalizedFormats.DIMENSIONS_MISMATCH_2x2, 537 vector.getDimension(), 1, nRows, 1); 538 } 539 for (int i = 0; i < nRows; ++i) { 540 setEntry(i, column, vector.getEntry(i)); 541 } 542 543 } 544 545 /** {@inheritDoc} */ getRow(final int row)546 public T[] getRow(final int row) 547 throws MatrixIndexException { 548 549 checkRowIndex(row); 550 final int nCols = getColumnDimension(); 551 final T[] out = buildArray(field, nCols); 552 for (int i = 0; i < nCols; ++i) { 553 out[i] = getEntry(row, i); 554 } 555 556 return out; 557 558 } 559 560 /** {@inheritDoc} */ setRow(final int row, final T[] array)561 public void setRow(final int row, final T[] array) 562 throws MatrixIndexException, InvalidMatrixException { 563 564 checkRowIndex(row); 565 final int nCols = getColumnDimension(); 566 if (array.length != nCols) { 567 throw new InvalidMatrixException( 568 LocalizedFormats.DIMENSIONS_MISMATCH_2x2, 569 1, array.length, 1, nCols); 570 } 571 for (int i = 0; i < nCols; ++i) { 572 setEntry(row, i, array[i]); 573 } 574 575 } 576 577 /** {@inheritDoc} */ getColumn(final int column)578 public T[] getColumn(final int column) 579 throws MatrixIndexException { 580 581 checkColumnIndex(column); 582 final int nRows = getRowDimension(); 583 final T[] out = buildArray(field, nRows); 584 for (int i = 0; i < nRows; ++i) { 585 out[i] = getEntry(i, column); 586 } 587 588 return out; 589 590 } 591 592 /** {@inheritDoc} */ setColumn(final int column, final T[] array)593 public void setColumn(final int column, final T[] array) 594 throws MatrixIndexException, InvalidMatrixException { 595 596 checkColumnIndex(column); 597 final int nRows = getRowDimension(); 598 if (array.length != nRows) { 599 throw new InvalidMatrixException( 600 LocalizedFormats.DIMENSIONS_MISMATCH_2x2, 601 array.length, 1, nRows, 1); 602 } 603 for (int i = 0; i < nRows; ++i) { 604 setEntry(i, column, array[i]); 605 } 606 607 } 608 609 /** {@inheritDoc} */ getEntry(int row, int column)610 public abstract T getEntry(int row, int column) 611 throws MatrixIndexException; 612 613 /** {@inheritDoc} */ setEntry(int row, int column, T value)614 public abstract void setEntry(int row, int column, T value) 615 throws MatrixIndexException; 616 617 /** {@inheritDoc} */ addToEntry(int row, int column, T increment)618 public abstract void addToEntry(int row, int column, T increment) 619 throws MatrixIndexException; 620 621 /** {@inheritDoc} */ multiplyEntry(int row, int column, T factor)622 public abstract void multiplyEntry(int row, int column, T factor) 623 throws MatrixIndexException; 624 625 /** {@inheritDoc} */ transpose()626 public FieldMatrix<T> transpose() { 627 628 final int nRows = getRowDimension(); 629 final int nCols = getColumnDimension(); 630 final FieldMatrix<T> out = createMatrix(nCols, nRows); 631 walkInOptimizedOrder(new DefaultFieldMatrixPreservingVisitor<T>(field.getZero()) { 632 633 /** {@inheritDoc} */ 634 @Override 635 public void visit(final int row, final int column, final T value) { 636 out.setEntry(column, row, value); 637 } 638 639 }); 640 641 return out; 642 643 } 644 645 /** {@inheritDoc} */ isSquare()646 public boolean isSquare() { 647 return getColumnDimension() == getRowDimension(); 648 } 649 650 /** {@inheritDoc} */ getRowDimension()651 public abstract int getRowDimension(); 652 653 /** {@inheritDoc} */ getColumnDimension()654 public abstract int getColumnDimension(); 655 656 /** {@inheritDoc} */ getTrace()657 public T getTrace() 658 throws NonSquareMatrixException { 659 final int nRows = getRowDimension(); 660 final int nCols = getColumnDimension(); 661 if (nRows != nCols) { 662 throw new NonSquareMatrixException(nRows, nCols); 663 } 664 T trace = field.getZero(); 665 for (int i = 0; i < nRows; ++i) { 666 trace = trace.add(getEntry(i, i)); 667 } 668 return trace; 669 } 670 671 /** {@inheritDoc} */ operate(final T[] v)672 public T[] operate(final T[] v) 673 throws IllegalArgumentException { 674 675 final int nRows = getRowDimension(); 676 final int nCols = getColumnDimension(); 677 if (v.length != nCols) { 678 throw MathRuntimeException.createIllegalArgumentException( 679 LocalizedFormats.VECTOR_LENGTH_MISMATCH, 680 v.length, nCols); 681 } 682 683 final T[] out = buildArray(field, nRows); 684 for (int row = 0; row < nRows; ++row) { 685 T sum = field.getZero(); 686 for (int i = 0; i < nCols; ++i) { 687 sum = sum.add(getEntry(row, i).multiply(v[i])); 688 } 689 out[row] = sum; 690 } 691 692 return out; 693 694 } 695 696 /** {@inheritDoc} */ operate(final FieldVector<T> v)697 public FieldVector<T> operate(final FieldVector<T> v) 698 throws IllegalArgumentException { 699 try { 700 return new ArrayFieldVector<T>(operate(((ArrayFieldVector<T>) v).getDataRef()), false); 701 } catch (ClassCastException cce) { 702 final int nRows = getRowDimension(); 703 final int nCols = getColumnDimension(); 704 if (v.getDimension() != nCols) { 705 throw MathRuntimeException.createIllegalArgumentException( 706 LocalizedFormats.VECTOR_LENGTH_MISMATCH, 707 v.getDimension(), nCols); 708 } 709 710 final T[] out = buildArray(field, nRows); 711 for (int row = 0; row < nRows; ++row) { 712 T sum = field.getZero(); 713 for (int i = 0; i < nCols; ++i) { 714 sum = sum.add(getEntry(row, i).multiply(v.getEntry(i))); 715 } 716 out[row] = sum; 717 } 718 719 return new ArrayFieldVector<T>(out, false); 720 } 721 } 722 723 /** {@inheritDoc} */ preMultiply(final T[] v)724 public T[] preMultiply(final T[] v) 725 throws IllegalArgumentException { 726 727 final int nRows = getRowDimension(); 728 final int nCols = getColumnDimension(); 729 if (v.length != nRows) { 730 throw MathRuntimeException.createIllegalArgumentException( 731 LocalizedFormats.VECTOR_LENGTH_MISMATCH, 732 v.length, nRows); 733 } 734 735 final T[] out = buildArray(field, nCols); 736 for (int col = 0; col < nCols; ++col) { 737 T sum = field.getZero(); 738 for (int i = 0; i < nRows; ++i) { 739 sum = sum.add(getEntry(i, col).multiply(v[i])); 740 } 741 out[col] = sum; 742 } 743 744 return out; 745 746 } 747 748 /** {@inheritDoc} */ preMultiply(final FieldVector<T> v)749 public FieldVector<T> preMultiply(final FieldVector<T> v) 750 throws IllegalArgumentException { 751 try { 752 return new ArrayFieldVector<T>(preMultiply(((ArrayFieldVector<T>) v).getDataRef()), false); 753 } catch (ClassCastException cce) { 754 755 final int nRows = getRowDimension(); 756 final int nCols = getColumnDimension(); 757 if (v.getDimension() != nRows) { 758 throw MathRuntimeException.createIllegalArgumentException( 759 LocalizedFormats.VECTOR_LENGTH_MISMATCH, 760 v.getDimension(), nRows); 761 } 762 763 final T[] out = buildArray(field, nCols); 764 for (int col = 0; col < nCols; ++col) { 765 T sum = field.getZero(); 766 for (int i = 0; i < nRows; ++i) { 767 sum = sum.add(getEntry(i, col).multiply(v.getEntry(i))); 768 } 769 out[col] = sum; 770 } 771 772 return new ArrayFieldVector<T>(out); 773 774 } 775 } 776 777 /** {@inheritDoc} */ walkInRowOrder(final FieldMatrixChangingVisitor<T> visitor)778 public T walkInRowOrder(final FieldMatrixChangingVisitor<T> visitor) 779 throws MatrixVisitorException { 780 final int rows = getRowDimension(); 781 final int columns = getColumnDimension(); 782 visitor.start(rows, columns, 0, rows - 1, 0, columns - 1); 783 for (int row = 0; row < rows; ++row) { 784 for (int column = 0; column < columns; ++column) { 785 final T oldValue = getEntry(row, column); 786 final T newValue = visitor.visit(row, column, oldValue); 787 setEntry(row, column, newValue); 788 } 789 } 790 return visitor.end(); 791 } 792 793 /** {@inheritDoc} */ walkInRowOrder(final FieldMatrixPreservingVisitor<T> visitor)794 public T walkInRowOrder(final FieldMatrixPreservingVisitor<T> visitor) 795 throws MatrixVisitorException { 796 final int rows = getRowDimension(); 797 final int columns = getColumnDimension(); 798 visitor.start(rows, columns, 0, rows - 1, 0, columns - 1); 799 for (int row = 0; row < rows; ++row) { 800 for (int column = 0; column < columns; ++column) { 801 visitor.visit(row, column, getEntry(row, column)); 802 } 803 } 804 return visitor.end(); 805 } 806 807 /** {@inheritDoc} */ walkInRowOrder(final FieldMatrixChangingVisitor<T> visitor, final int startRow, final int endRow, final int startColumn, final int endColumn)808 public T walkInRowOrder(final FieldMatrixChangingVisitor<T> visitor, 809 final int startRow, final int endRow, 810 final int startColumn, final int endColumn) 811 throws MatrixIndexException, MatrixVisitorException { 812 checkSubMatrixIndex(startRow, endRow, startColumn, endColumn); 813 visitor.start(getRowDimension(), getColumnDimension(), 814 startRow, endRow, startColumn, endColumn); 815 for (int row = startRow; row <= endRow; ++row) { 816 for (int column = startColumn; column <= endColumn; ++column) { 817 final T oldValue = getEntry(row, column); 818 final T newValue = visitor.visit(row, column, oldValue); 819 setEntry(row, column, newValue); 820 } 821 } 822 return visitor.end(); 823 } 824 825 /** {@inheritDoc} */ walkInRowOrder(final FieldMatrixPreservingVisitor<T> visitor, final int startRow, final int endRow, final int startColumn, final int endColumn)826 public T walkInRowOrder(final FieldMatrixPreservingVisitor<T> visitor, 827 final int startRow, final int endRow, 828 final int startColumn, final int endColumn) 829 throws MatrixIndexException, MatrixVisitorException { 830 checkSubMatrixIndex(startRow, endRow, startColumn, endColumn); 831 visitor.start(getRowDimension(), getColumnDimension(), 832 startRow, endRow, startColumn, endColumn); 833 for (int row = startRow; row <= endRow; ++row) { 834 for (int column = startColumn; column <= endColumn; ++column) { 835 visitor.visit(row, column, getEntry(row, column)); 836 } 837 } 838 return visitor.end(); 839 } 840 841 /** {@inheritDoc} */ walkInColumnOrder(final FieldMatrixChangingVisitor<T> visitor)842 public T walkInColumnOrder(final FieldMatrixChangingVisitor<T> visitor) 843 throws MatrixVisitorException { 844 final int rows = getRowDimension(); 845 final int columns = getColumnDimension(); 846 visitor.start(rows, columns, 0, rows - 1, 0, columns - 1); 847 for (int column = 0; column < columns; ++column) { 848 for (int row = 0; row < rows; ++row) { 849 final T oldValue = getEntry(row, column); 850 final T newValue = visitor.visit(row, column, oldValue); 851 setEntry(row, column, newValue); 852 } 853 } 854 return visitor.end(); 855 } 856 857 /** {@inheritDoc} */ walkInColumnOrder(final FieldMatrixPreservingVisitor<T> visitor)858 public T walkInColumnOrder(final FieldMatrixPreservingVisitor<T> visitor) 859 throws MatrixVisitorException { 860 final int rows = getRowDimension(); 861 final int columns = getColumnDimension(); 862 visitor.start(rows, columns, 0, rows - 1, 0, columns - 1); 863 for (int column = 0; column < columns; ++column) { 864 for (int row = 0; row < rows; ++row) { 865 visitor.visit(row, column, getEntry(row, column)); 866 } 867 } 868 return visitor.end(); 869 } 870 871 /** {@inheritDoc} */ walkInColumnOrder(final FieldMatrixChangingVisitor<T> visitor, final int startRow, final int endRow, final int startColumn, final int endColumn)872 public T walkInColumnOrder(final FieldMatrixChangingVisitor<T> visitor, 873 final int startRow, final int endRow, 874 final int startColumn, final int endColumn) 875 throws MatrixIndexException, MatrixVisitorException { 876 checkSubMatrixIndex(startRow, endRow, startColumn, endColumn); 877 visitor.start(getRowDimension(), getColumnDimension(), 878 startRow, endRow, startColumn, endColumn); 879 for (int column = startColumn; column <= endColumn; ++column) { 880 for (int row = startRow; row <= endRow; ++row) { 881 final T oldValue = getEntry(row, column); 882 final T newValue = visitor.visit(row, column, oldValue); 883 setEntry(row, column, newValue); 884 } 885 } 886 return visitor.end(); 887 } 888 889 /** {@inheritDoc} */ walkInColumnOrder(final FieldMatrixPreservingVisitor<T> visitor, final int startRow, final int endRow, final int startColumn, final int endColumn)890 public T walkInColumnOrder(final FieldMatrixPreservingVisitor<T> visitor, 891 final int startRow, final int endRow, 892 final int startColumn, final int endColumn) 893 throws MatrixIndexException, MatrixVisitorException { 894 checkSubMatrixIndex(startRow, endRow, startColumn, endColumn); 895 visitor.start(getRowDimension(), getColumnDimension(), 896 startRow, endRow, startColumn, endColumn); 897 for (int column = startColumn; column <= endColumn; ++column) { 898 for (int row = startRow; row <= endRow; ++row) { 899 visitor.visit(row, column, getEntry(row, column)); 900 } 901 } 902 return visitor.end(); 903 } 904 905 /** {@inheritDoc} */ walkInOptimizedOrder(final FieldMatrixChangingVisitor<T> visitor)906 public T walkInOptimizedOrder(final FieldMatrixChangingVisitor<T> visitor) 907 throws MatrixVisitorException { 908 return walkInRowOrder(visitor); 909 } 910 911 /** {@inheritDoc} */ walkInOptimizedOrder(final FieldMatrixPreservingVisitor<T> visitor)912 public T walkInOptimizedOrder(final FieldMatrixPreservingVisitor<T> visitor) 913 throws MatrixVisitorException { 914 return walkInRowOrder(visitor); 915 } 916 917 /** {@inheritDoc} */ walkInOptimizedOrder(final FieldMatrixChangingVisitor<T> visitor, final int startRow, final int endRow, final int startColumn, final int endColumn)918 public T walkInOptimizedOrder(final FieldMatrixChangingVisitor<T> visitor, 919 final int startRow, final int endRow, 920 final int startColumn, final int endColumn) 921 throws MatrixIndexException, MatrixVisitorException { 922 return walkInRowOrder(visitor, startRow, endRow, startColumn, endColumn); 923 } 924 925 /** {@inheritDoc} */ walkInOptimizedOrder(final FieldMatrixPreservingVisitor<T> visitor, final int startRow, final int endRow, final int startColumn, final int endColumn)926 public T walkInOptimizedOrder(final FieldMatrixPreservingVisitor<T> visitor, 927 final int startRow, final int endRow, 928 final int startColumn, final int endColumn) 929 throws MatrixIndexException, MatrixVisitorException { 930 return walkInRowOrder(visitor, startRow, endRow, startColumn, endColumn); 931 } 932 933 /** 934 * Get a string representation for this matrix. 935 * @return a string representation for this matrix 936 */ 937 @Override toString()938 public String toString() { 939 final int nRows = getRowDimension(); 940 final int nCols = getColumnDimension(); 941 final StringBuilder res = new StringBuilder(); 942 String fullClassName = getClass().getName(); 943 String shortClassName = fullClassName.substring(fullClassName.lastIndexOf('.') + 1); 944 res.append(shortClassName).append("{"); 945 946 for (int i = 0; i < nRows; ++i) { 947 if (i > 0) { 948 res.append(","); 949 } 950 res.append("{"); 951 for (int j = 0; j < nCols; ++j) { 952 if (j > 0) { 953 res.append(","); 954 } 955 res.append(getEntry(i, j)); 956 } 957 res.append("}"); 958 } 959 960 res.append("}"); 961 return res.toString(); 962 963 } 964 965 /** 966 * Returns true iff <code>object</code> is a 967 * <code>FieldMatrix</code> instance with the same dimensions as this 968 * and all corresponding matrix entries are equal. 969 * 970 * @param object the object to test equality against. 971 * @return true if object equals this 972 */ 973 @Override equals(final Object object)974 public boolean equals(final Object object) { 975 if (object == this ) { 976 return true; 977 } 978 if (object instanceof FieldMatrix<?> == false) { 979 return false; 980 } 981 FieldMatrix<?> m = (FieldMatrix<?>) object; 982 final int nRows = getRowDimension(); 983 final int nCols = getColumnDimension(); 984 if (m.getColumnDimension() != nCols || m.getRowDimension() != nRows) { 985 return false; 986 } 987 for (int row = 0; row < nRows; ++row) { 988 for (int col = 0; col < nCols; ++col) { 989 if (!getEntry(row, col).equals(m.getEntry(row, col))) { 990 return false; 991 } 992 } 993 } 994 return true; 995 } 996 997 /** 998 * Computes a hashcode for the matrix. 999 * 1000 * @return hashcode for matrix 1001 */ 1002 @Override hashCode()1003 public int hashCode() { 1004 int ret = 322562; 1005 final int nRows = getRowDimension(); 1006 final int nCols = getColumnDimension(); 1007 ret = ret * 31 + nRows; 1008 ret = ret * 31 + nCols; 1009 for (int row = 0; row < nRows; ++row) { 1010 for (int col = 0; col < nCols; ++col) { 1011 ret = ret * 31 + (11 * (row+1) + 17 * (col+1)) * getEntry(row, col).hashCode(); 1012 } 1013 } 1014 return ret; 1015 } 1016 1017 /** 1018 * Check if a row index is valid. 1019 * @param row row index to check 1020 * @exception MatrixIndexException if index is not valid 1021 */ checkRowIndex(final int row)1022 protected void checkRowIndex(final int row) { 1023 if (row < 0 || row >= getRowDimension()) { 1024 throw new MatrixIndexException(LocalizedFormats.ROW_INDEX_OUT_OF_RANGE, 1025 row, 0, getRowDimension() - 1); 1026 } 1027 } 1028 1029 /** 1030 * Check if a column index is valid. 1031 * @param column column index to check 1032 * @exception MatrixIndexException if index is not valid 1033 */ checkColumnIndex(final int column)1034 protected void checkColumnIndex(final int column) 1035 throws MatrixIndexException { 1036 if (column < 0 || column >= getColumnDimension()) { 1037 throw new MatrixIndexException(LocalizedFormats.COLUMN_INDEX_OUT_OF_RANGE, 1038 column, 0, getColumnDimension() - 1); 1039 } 1040 } 1041 1042 /** 1043 * Check if submatrix ranges indices are valid. 1044 * Rows and columns are indicated counting from 0 to n-1. 1045 * 1046 * @param startRow Initial row index 1047 * @param endRow Final row index 1048 * @param startColumn Initial column index 1049 * @param endColumn Final column index 1050 * @exception MatrixIndexException if the indices are not valid 1051 */ checkSubMatrixIndex(final int startRow, final int endRow, final int startColumn, final int endColumn)1052 protected void checkSubMatrixIndex(final int startRow, final int endRow, 1053 final int startColumn, final int endColumn) { 1054 checkRowIndex(startRow); 1055 checkRowIndex(endRow); 1056 if (startRow > endRow) { 1057 throw new MatrixIndexException(LocalizedFormats.INITIAL_ROW_AFTER_FINAL_ROW, 1058 startRow, endRow); 1059 } 1060 1061 checkColumnIndex(startColumn); 1062 checkColumnIndex(endColumn); 1063 if (startColumn > endColumn) { 1064 throw new MatrixIndexException(LocalizedFormats.INITIAL_COLUMN_AFTER_FINAL_COLUMN, 1065 startColumn, endColumn); 1066 } 1067 1068 1069 } 1070 1071 /** 1072 * Check if submatrix ranges indices are valid. 1073 * Rows and columns are indicated counting from 0 to n-1. 1074 * 1075 * @param selectedRows Array of row indices. 1076 * @param selectedColumns Array of column indices. 1077 * @exception MatrixIndexException if row or column selections are not valid 1078 */ checkSubMatrixIndex(final int[] selectedRows, final int[] selectedColumns)1079 protected void checkSubMatrixIndex(final int[] selectedRows, final int[] selectedColumns) { 1080 if (selectedRows.length * selectedColumns.length == 0) { 1081 if (selectedRows.length == 0) { 1082 throw new MatrixIndexException(LocalizedFormats.EMPTY_SELECTED_ROW_INDEX_ARRAY); 1083 } 1084 throw new MatrixIndexException(LocalizedFormats.EMPTY_SELECTED_COLUMN_INDEX_ARRAY); 1085 } 1086 1087 for (final int row : selectedRows) { 1088 checkRowIndex(row); 1089 } 1090 for (final int column : selectedColumns) { 1091 checkColumnIndex(column); 1092 } 1093 } 1094 1095 /** 1096 * Check if a matrix is addition compatible with the instance 1097 * @param m matrix to check 1098 * @exception IllegalArgumentException if matrix is not addition compatible with instance 1099 */ checkAdditionCompatible(final FieldMatrix<T> m)1100 protected void checkAdditionCompatible(final FieldMatrix<T> m) { 1101 if ((getRowDimension() != m.getRowDimension()) || 1102 (getColumnDimension() != m.getColumnDimension())) { 1103 throw MathRuntimeException.createIllegalArgumentException( 1104 LocalizedFormats.NOT_ADDITION_COMPATIBLE_MATRICES, 1105 getRowDimension(), getColumnDimension(), 1106 m.getRowDimension(), m.getColumnDimension()); 1107 } 1108 } 1109 1110 /** 1111 * Check if a matrix is subtraction compatible with the instance 1112 * @param m matrix to check 1113 * @exception IllegalArgumentException if matrix is not subtraction compatible with instance 1114 */ checkSubtractionCompatible(final FieldMatrix<T> m)1115 protected void checkSubtractionCompatible(final FieldMatrix<T> m) { 1116 if ((getRowDimension() != m.getRowDimension()) || 1117 (getColumnDimension() != m.getColumnDimension())) { 1118 throw MathRuntimeException.createIllegalArgumentException( 1119 LocalizedFormats.NOT_SUBTRACTION_COMPATIBLE_MATRICES, 1120 getRowDimension(), getColumnDimension(), 1121 m.getRowDimension(), m.getColumnDimension()); 1122 } 1123 } 1124 1125 /** 1126 * Check if a matrix is multiplication compatible with the instance 1127 * @param m matrix to check 1128 * @exception IllegalArgumentException if matrix is not multiplication compatible with instance 1129 */ checkMultiplicationCompatible(final FieldMatrix<T> m)1130 protected void checkMultiplicationCompatible(final FieldMatrix<T> m) { 1131 if (getColumnDimension() != m.getRowDimension()) { 1132 throw MathRuntimeException.createIllegalArgumentException( 1133 LocalizedFormats.NOT_MULTIPLICATION_COMPATIBLE_MATRICES, 1134 getRowDimension(), getColumnDimension(), 1135 m.getRowDimension(), m.getColumnDimension()); 1136 } 1137 } 1138 1139 } 1140