001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.math3.linear; 019 020import java.util.ArrayList; 021 022import org.apache.commons.math3.Field; 023import org.apache.commons.math3.FieldElement; 024import org.apache.commons.math3.exception.DimensionMismatchException; 025import org.apache.commons.math3.exception.NoDataException; 026import org.apache.commons.math3.exception.NotPositiveException; 027import org.apache.commons.math3.exception.NotStrictlyPositiveException; 028import org.apache.commons.math3.exception.NullArgumentException; 029import org.apache.commons.math3.exception.NumberIsTooSmallException; 030import org.apache.commons.math3.exception.OutOfRangeException; 031import org.apache.commons.math3.exception.util.LocalizedFormats; 032import org.apache.commons.math3.util.MathArrays; 033 034/** 035 * Basic implementation of {@link FieldMatrix} methods regardless of the underlying storage. 036 * <p>All the methods implemented here use {@link #getEntry(int, int)} to access 037 * matrix elements. Derived class can provide faster implementations. </p> 038 * 039 * @param <T> Type of the field elements. 040 * 041 * @since 2.0 042 */ 043public abstract class AbstractFieldMatrix<T extends FieldElement<T>> 044 implements FieldMatrix<T> { 045 /** Field to which the elements belong. */ 046 private final Field<T> field; 047 048 /** 049 * Constructor for use with Serializable 050 */ 051 protected AbstractFieldMatrix() { 052 field = null; 053 } 054 055 /** 056 * Creates a matrix with no data 057 * @param field field to which the elements belong 058 */ 059 protected AbstractFieldMatrix(final Field<T> field) { 060 this.field = field; 061 } 062 063 /** 064 * Create a new FieldMatrix<T> with the supplied row and column dimensions. 065 * 066 * @param field Field to which the elements belong. 067 * @param rowDimension Number of rows in the new matrix. 068 * @param columnDimension Number of columns in the new matrix. 069 * @throws NotStrictlyPositiveException if row or column dimension is not 070 * positive. 071 */ 072 protected AbstractFieldMatrix(final Field<T> field, 073 final int rowDimension, 074 final int columnDimension) 075 throws NotStrictlyPositiveException { 076 if (rowDimension <= 0) { 077 throw new NotStrictlyPositiveException(LocalizedFormats.DIMENSION, 078 rowDimension); 079 } 080 if (columnDimension <= 0) { 081 throw new NotStrictlyPositiveException(LocalizedFormats.DIMENSION, 082 columnDimension); 083 } 084 this.field = field; 085 } 086 087 /** 088 * Get the elements type from an array. 089 * 090 * @param <T> Type of the field elements. 091 * @param d Data array. 092 * @return the field to which the array elements belong. 093 * @throws NullArgumentException if the array is {@code null}. 094 * @throws NoDataException if the array is empty. 095 */ 096 protected static <T extends FieldElement<T>> Field<T> extractField(final T[][] d) 097 throws NoDataException, NullArgumentException { 098 if (d == null) { 099 throw new NullArgumentException(); 100 } 101 if (d.length == 0) { 102 throw new NoDataException(LocalizedFormats.AT_LEAST_ONE_ROW); 103 } 104 if (d[0].length == 0) { 105 throw new NoDataException(LocalizedFormats.AT_LEAST_ONE_COLUMN); 106 } 107 return d[0][0].getField(); 108 } 109 110 /** 111 * Get the elements type from an array. 112 * 113 * @param <T> Type of the field elements. 114 * @param d Data array. 115 * @return the field to which the array elements belong. 116 * @throws NoDataException if array is empty. 117 */ 118 protected static <T extends FieldElement<T>> Field<T> extractField(final T[] d) 119 throws NoDataException { 120 if (d.length == 0) { 121 throw new NoDataException(LocalizedFormats.AT_LEAST_ONE_ROW); 122 } 123 return d[0].getField(); 124 } 125 126 /** Build an array of elements. 127 * <p> 128 * Complete arrays are filled with field.getZero() 129 * </p> 130 * @param <T> Type of the field elements 131 * @param field field to which array elements belong 132 * @param rows number of rows 133 * @param columns number of columns (may be negative to build partial 134 * arrays in the same way <code>new Field[rows][]</code> works) 135 * @return a new array 136 * @deprecated as of 3.2, replaced by {@link MathArrays#buildArray(Field, int, int)} 137 */ 138 @Deprecated 139 protected static <T extends FieldElement<T>> T[][] buildArray(final Field<T> field, 140 final int rows, 141 final int columns) { 142 return MathArrays.buildArray(field, rows, columns); 143 } 144 145 /** Build an array of elements. 146 * <p> 147 * Arrays are filled with field.getZero() 148 * </p> 149 * @param <T> the type of the field elements 150 * @param field field to which array elements belong 151 * @param length of the array 152 * @return a new array 153 * @deprecated as of 3.2, replaced by {@link MathArrays#buildArray(Field, int)} 154 */ 155 @Deprecated 156 protected static <T extends FieldElement<T>> T[] buildArray(final Field<T> field, 157 final int length) { 158 return MathArrays.buildArray(field, length); 159 } 160 161 /** {@inheritDoc} */ 162 public Field<T> getField() { 163 return field; 164 } 165 166 /** {@inheritDoc} */ 167 public abstract FieldMatrix<T> createMatrix(final int rowDimension, 168 final int columnDimension) 169 throws NotStrictlyPositiveException; 170 171 /** {@inheritDoc} */ 172 public abstract FieldMatrix<T> copy(); 173 174 /** {@inheritDoc} */ 175 public FieldMatrix<T> add(FieldMatrix<T> m) 176 throws MatrixDimensionMismatchException { 177 // safety check 178 checkAdditionCompatible(m); 179 180 final int rowCount = getRowDimension(); 181 final int columnCount = getColumnDimension(); 182 final FieldMatrix<T> out = createMatrix(rowCount, columnCount); 183 for (int row = 0; row < rowCount; ++row) { 184 for (int col = 0; col < columnCount; ++col) { 185 out.setEntry(row, col, getEntry(row, col).add(m.getEntry(row, col))); 186 } 187 } 188 189 return out; 190 } 191 192 /** {@inheritDoc} */ 193 public FieldMatrix<T> subtract(final FieldMatrix<T> m) 194 throws MatrixDimensionMismatchException { 195 // safety check 196 checkSubtractionCompatible(m); 197 198 final int rowCount = getRowDimension(); 199 final int columnCount = getColumnDimension(); 200 final FieldMatrix<T> out = createMatrix(rowCount, columnCount); 201 for (int row = 0; row < rowCount; ++row) { 202 for (int col = 0; col < columnCount; ++col) { 203 out.setEntry(row, col, getEntry(row, col).subtract(m.getEntry(row, col))); 204 } 205 } 206 207 return out; 208 } 209 210 /** {@inheritDoc} */ 211 public FieldMatrix<T> scalarAdd(final T d) { 212 213 final int rowCount = getRowDimension(); 214 final int columnCount = getColumnDimension(); 215 final FieldMatrix<T> out = createMatrix(rowCount, columnCount); 216 for (int row = 0; row < rowCount; ++row) { 217 for (int col = 0; col < columnCount; ++col) { 218 out.setEntry(row, col, getEntry(row, col).add(d)); 219 } 220 } 221 222 return out; 223 } 224 225 /** {@inheritDoc} */ 226 public FieldMatrix<T> scalarMultiply(final T d) { 227 final int rowCount = getRowDimension(); 228 final int columnCount = getColumnDimension(); 229 final FieldMatrix<T> out = createMatrix(rowCount, columnCount); 230 for (int row = 0; row < rowCount; ++row) { 231 for (int col = 0; col < columnCount; ++col) { 232 out.setEntry(row, col, getEntry(row, col).multiply(d)); 233 } 234 } 235 236 return out; 237 } 238 239 /** {@inheritDoc} */ 240 public FieldMatrix<T> multiply(final FieldMatrix<T> m) 241 throws DimensionMismatchException { 242 // safety check 243 checkMultiplicationCompatible(m); 244 245 final int nRows = getRowDimension(); 246 final int nCols = m.getColumnDimension(); 247 final int nSum = getColumnDimension(); 248 final FieldMatrix<T> out = createMatrix(nRows, nCols); 249 for (int row = 0; row < nRows; ++row) { 250 for (int col = 0; col < nCols; ++col) { 251 T sum = field.getZero(); 252 for (int i = 0; i < nSum; ++i) { 253 sum = sum.add(getEntry(row, i).multiply(m.getEntry(i, col))); 254 } 255 out.setEntry(row, col, sum); 256 } 257 } 258 259 return out; 260 } 261 262 /** {@inheritDoc} */ 263 public FieldMatrix<T> preMultiply(final FieldMatrix<T> m) 264 throws DimensionMismatchException { 265 return m.multiply(this); 266 } 267 268 /** {@inheritDoc} */ 269 public FieldMatrix<T> power(final int p) throws NonSquareMatrixException, 270 NotPositiveException { 271 if (p < 0) { 272 throw new NotPositiveException(p); 273 } 274 275 if (!isSquare()) { 276 throw new NonSquareMatrixException(getRowDimension(), getColumnDimension()); 277 } 278 279 if (p == 0) { 280 return MatrixUtils.createFieldIdentityMatrix(this.getField(), this.getRowDimension()); 281 } 282 283 if (p == 1) { 284 return this.copy(); 285 } 286 287 final int power = p - 1; 288 289 /* 290 * Only log_2(p) operations is used by doing as follows: 291 * 5^214 = 5^128 * 5^64 * 5^16 * 5^4 * 5^2 292 * 293 * In general, the same approach is used for A^p. 294 */ 295 296 final char[] binaryRepresentation = Integer.toBinaryString(power) 297 .toCharArray(); 298 final ArrayList<Integer> nonZeroPositions = new ArrayList<Integer>(); 299 300 for (int i = 0; i < binaryRepresentation.length; ++i) { 301 if (binaryRepresentation[i] == '1') { 302 final int pos = binaryRepresentation.length - i - 1; 303 nonZeroPositions.add(pos); 304 } 305 } 306 307 ArrayList<FieldMatrix<T>> results = new ArrayList<FieldMatrix<T>>( 308 binaryRepresentation.length); 309 310 results.add(0, this.copy()); 311 312 for (int i = 1; i < binaryRepresentation.length; ++i) { 313 final FieldMatrix<T> s = results.get(i - 1); 314 final FieldMatrix<T> r = s.multiply(s); 315 results.add(i, r); 316 } 317 318 FieldMatrix<T> result = this.copy(); 319 320 for (Integer i : nonZeroPositions) { 321 result = result.multiply(results.get(i)); 322 } 323 324 return result; 325 } 326 327 /** {@inheritDoc} */ 328 public T[][] getData() { 329 final T[][] data = MathArrays.buildArray(field, getRowDimension(), getColumnDimension()); 330 331 for (int i = 0; i < data.length; ++i) { 332 final T[] dataI = data[i]; 333 for (int j = 0; j < dataI.length; ++j) { 334 dataI[j] = getEntry(i, j); 335 } 336 } 337 338 return data; 339 } 340 341 /** {@inheritDoc} */ 342 public FieldMatrix<T> getSubMatrix(final int startRow, final int endRow, 343 final int startColumn, final int endColumn) 344 throws NumberIsTooSmallException, OutOfRangeException { 345 checkSubMatrixIndex(startRow, endRow, startColumn, endColumn); 346 347 final FieldMatrix<T> subMatrix = 348 createMatrix(endRow - startRow + 1, endColumn - startColumn + 1); 349 for (int i = startRow; i <= endRow; ++i) { 350 for (int j = startColumn; j <= endColumn; ++j) { 351 subMatrix.setEntry(i - startRow, j - startColumn, getEntry(i, j)); 352 } 353 } 354 355 return subMatrix; 356 357 } 358 359 /** {@inheritDoc} */ 360 public FieldMatrix<T> getSubMatrix(final int[] selectedRows, 361 final int[] selectedColumns) 362 throws NoDataException, NullArgumentException, OutOfRangeException { 363 364 // safety checks 365 checkSubMatrixIndex(selectedRows, selectedColumns); 366 367 // copy entries 368 final FieldMatrix<T> subMatrix = 369 createMatrix(selectedRows.length, selectedColumns.length); 370 subMatrix.walkInOptimizedOrder(new DefaultFieldMatrixChangingVisitor<T>(field.getZero()) { 371 372 /** {@inheritDoc} */ 373 @Override 374 public T visit(final int row, final int column, final T value) { 375 return getEntry(selectedRows[row], selectedColumns[column]); 376 } 377 378 }); 379 380 return subMatrix; 381 382 } 383 384 /** {@inheritDoc} */ 385 public void copySubMatrix(final int startRow, final int endRow, 386 final int startColumn, final int endColumn, 387 final T[][] destination) 388 throws MatrixDimensionMismatchException, NumberIsTooSmallException, 389 OutOfRangeException{ 390 // safety checks 391 checkSubMatrixIndex(startRow, endRow, startColumn, endColumn); 392 final int rowsCount = endRow + 1 - startRow; 393 final int columnsCount = endColumn + 1 - startColumn; 394 if ((destination.length < rowsCount) || (destination[0].length < columnsCount)) { 395 throw new MatrixDimensionMismatchException(destination.length, 396 destination[0].length, 397 rowsCount, 398 columnsCount); 399 } 400 401 // copy entries 402 walkInOptimizedOrder(new DefaultFieldMatrixPreservingVisitor<T>(field.getZero()) { 403 404 /** Initial row index. */ 405 private int startRow; 406 407 /** Initial column index. */ 408 private int startColumn; 409 410 /** {@inheritDoc} */ 411 @Override 412 public void start(final int rows, final int columns, 413 final int startRow, final int endRow, 414 final int startColumn, final int endColumn) { 415 this.startRow = startRow; 416 this.startColumn = startColumn; 417 } 418 419 /** {@inheritDoc} */ 420 @Override 421 public void visit(final int row, final int column, final T value) { 422 destination[row - startRow][column - startColumn] = value; 423 } 424 425 }, startRow, endRow, startColumn, endColumn); 426 427 } 428 429 /** {@inheritDoc} */ 430 public void copySubMatrix(int[] selectedRows, int[] selectedColumns, T[][] destination) 431 throws MatrixDimensionMismatchException, NoDataException, 432 NullArgumentException, OutOfRangeException { 433 // safety checks 434 checkSubMatrixIndex(selectedRows, selectedColumns); 435 if ((destination.length < selectedRows.length) || 436 (destination[0].length < selectedColumns.length)) { 437 throw new MatrixDimensionMismatchException(destination.length, 438 destination[0].length, 439 selectedRows.length, 440 selectedColumns.length); 441 } 442 443 // copy entries 444 for (int i = 0; i < selectedRows.length; i++) { 445 final T[] destinationI = destination[i]; 446 for (int j = 0; j < selectedColumns.length; j++) { 447 destinationI[j] = getEntry(selectedRows[i], selectedColumns[j]); 448 } 449 } 450 451 } 452 453 /** {@inheritDoc} */ 454 public void setSubMatrix(final T[][] subMatrix, final int row, 455 final int column) 456 throws DimensionMismatchException, OutOfRangeException, 457 NoDataException, NullArgumentException { 458 if (subMatrix == null) { 459 throw new NullArgumentException(); 460 } 461 final int nRows = subMatrix.length; 462 if (nRows == 0) { 463 throw new NoDataException(LocalizedFormats.AT_LEAST_ONE_ROW); 464 } 465 466 final int nCols = subMatrix[0].length; 467 if (nCols == 0) { 468 throw new NoDataException(LocalizedFormats.AT_LEAST_ONE_COLUMN); 469 } 470 471 for (int r = 1; r < nRows; ++r) { 472 if (subMatrix[r].length != nCols) { 473 throw new DimensionMismatchException(nCols, subMatrix[r].length); 474 } 475 } 476 477 checkRowIndex(row); 478 checkColumnIndex(column); 479 checkRowIndex(nRows + row - 1); 480 checkColumnIndex(nCols + column - 1); 481 482 for (int i = 0; i < nRows; ++i) { 483 for (int j = 0; j < nCols; ++j) { 484 setEntry(row + i, column + j, subMatrix[i][j]); 485 } 486 } 487 } 488 489 /** {@inheritDoc} */ 490 public FieldMatrix<T> getRowMatrix(final int row) throws OutOfRangeException { 491 checkRowIndex(row); 492 final int nCols = getColumnDimension(); 493 final FieldMatrix<T> out = createMatrix(1, nCols); 494 for (int i = 0; i < nCols; ++i) { 495 out.setEntry(0, i, getEntry(row, i)); 496 } 497 498 return out; 499 500 } 501 502 /** {@inheritDoc} */ 503 public void setRowMatrix(final int row, final FieldMatrix<T> matrix) 504 throws OutOfRangeException, MatrixDimensionMismatchException { 505 checkRowIndex(row); 506 final int nCols = getColumnDimension(); 507 if ((matrix.getRowDimension() != 1) || 508 (matrix.getColumnDimension() != nCols)) { 509 throw new MatrixDimensionMismatchException(matrix.getRowDimension(), 510 matrix.getColumnDimension(), 511 1, nCols); 512 } 513 for (int i = 0; i < nCols; ++i) { 514 setEntry(row, i, matrix.getEntry(0, i)); 515 } 516 517 } 518 519 /** {@inheritDoc} */ 520 public FieldMatrix<T> getColumnMatrix(final int column) 521 throws OutOfRangeException { 522 523 checkColumnIndex(column); 524 final int nRows = getRowDimension(); 525 final FieldMatrix<T> out = createMatrix(nRows, 1); 526 for (int i = 0; i < nRows; ++i) { 527 out.setEntry(i, 0, getEntry(i, column)); 528 } 529 530 return out; 531 532 } 533 534 /** {@inheritDoc} */ 535 public void setColumnMatrix(final int column, final FieldMatrix<T> matrix) 536 throws OutOfRangeException, MatrixDimensionMismatchException { 537 checkColumnIndex(column); 538 final int nRows = getRowDimension(); 539 if ((matrix.getRowDimension() != nRows) || 540 (matrix.getColumnDimension() != 1)) { 541 throw new MatrixDimensionMismatchException(matrix.getRowDimension(), 542 matrix.getColumnDimension(), 543 nRows, 1); 544 } 545 for (int i = 0; i < nRows; ++i) { 546 setEntry(i, column, matrix.getEntry(i, 0)); 547 } 548 549 } 550 551 /** {@inheritDoc} */ 552 public FieldVector<T> getRowVector(final int row) 553 throws OutOfRangeException { 554 return new ArrayFieldVector<T>(field, getRow(row), false); 555 } 556 557 /** {@inheritDoc} */ 558 public void setRowVector(final int row, final FieldVector<T> vector) 559 throws OutOfRangeException, MatrixDimensionMismatchException { 560 checkRowIndex(row); 561 final int nCols = getColumnDimension(); 562 if (vector.getDimension() != nCols) { 563 throw new MatrixDimensionMismatchException(1, vector.getDimension(), 564 1, nCols); 565 } 566 for (int i = 0; i < nCols; ++i) { 567 setEntry(row, i, vector.getEntry(i)); 568 } 569 570 } 571 572 /** {@inheritDoc} */ 573 public FieldVector<T> getColumnVector(final int column) 574 throws OutOfRangeException { 575 return new ArrayFieldVector<T>(field, getColumn(column), false); 576 } 577 578 /** {@inheritDoc} */ 579 public void setColumnVector(final int column, final FieldVector<T> vector) 580 throws OutOfRangeException, MatrixDimensionMismatchException { 581 582 checkColumnIndex(column); 583 final int nRows = getRowDimension(); 584 if (vector.getDimension() != nRows) { 585 throw new MatrixDimensionMismatchException(vector.getDimension(), 1, 586 nRows, 1); 587 } 588 for (int i = 0; i < nRows; ++i) { 589 setEntry(i, column, vector.getEntry(i)); 590 } 591 592 } 593 594 /** {@inheritDoc} */ 595 public T[] getRow(final int row) throws OutOfRangeException { 596 checkRowIndex(row); 597 final int nCols = getColumnDimension(); 598 final T[] out = MathArrays.buildArray(field, nCols); 599 for (int i = 0; i < nCols; ++i) { 600 out[i] = getEntry(row, i); 601 } 602 603 return out; 604 605 } 606 607 /** {@inheritDoc} */ 608 public void setRow(final int row, final T[] array) 609 throws OutOfRangeException, MatrixDimensionMismatchException { 610 checkRowIndex(row); 611 final int nCols = getColumnDimension(); 612 if (array.length != nCols) { 613 throw new MatrixDimensionMismatchException(1, array.length, 1, nCols); 614 } 615 for (int i = 0; i < nCols; ++i) { 616 setEntry(row, i, array[i]); 617 } 618 619 } 620 621 /** {@inheritDoc} */ 622 public T[] getColumn(final int column) throws OutOfRangeException { 623 checkColumnIndex(column); 624 final int nRows = getRowDimension(); 625 final T[] out = MathArrays.buildArray(field, nRows); 626 for (int i = 0; i < nRows; ++i) { 627 out[i] = getEntry(i, column); 628 } 629 630 return out; 631 632 } 633 634 /** {@inheritDoc} */ 635 public void setColumn(final int column, final T[] array) 636 throws OutOfRangeException, MatrixDimensionMismatchException { 637 checkColumnIndex(column); 638 final int nRows = getRowDimension(); 639 if (array.length != nRows) { 640 throw new MatrixDimensionMismatchException(array.length, 1, nRows, 1); 641 } 642 for (int i = 0; i < nRows; ++i) { 643 setEntry(i, column, array[i]); 644 } 645 } 646 647 /** {@inheritDoc} */ 648 public abstract T getEntry(int row, int column) throws OutOfRangeException; 649 650 /** {@inheritDoc} */ 651 public abstract void setEntry(int row, int column, T value) throws OutOfRangeException; 652 653 /** {@inheritDoc} */ 654 public abstract void addToEntry(int row, int column, T increment) throws OutOfRangeException; 655 656 /** {@inheritDoc} */ 657 public abstract void multiplyEntry(int row, int column, T factor) throws OutOfRangeException; 658 659 /** {@inheritDoc} */ 660 public FieldMatrix<T> transpose() { 661 final int nRows = getRowDimension(); 662 final int nCols = getColumnDimension(); 663 final FieldMatrix<T> out = createMatrix(nCols, nRows); 664 walkInOptimizedOrder(new DefaultFieldMatrixPreservingVisitor<T>(field.getZero()) { 665 /** {@inheritDoc} */ 666 @Override 667 public void visit(final int row, final int column, final T value) { 668 out.setEntry(column, row, value); 669 } 670 }); 671 672 return out; 673 } 674 675 /** {@inheritDoc} */ 676 public boolean isSquare() { 677 return getColumnDimension() == getRowDimension(); 678 } 679 680 /** {@inheritDoc} */ 681 public abstract int getRowDimension(); 682 683 /** {@inheritDoc} */ 684 public abstract int getColumnDimension(); 685 686 /** {@inheritDoc} */ 687 public T getTrace() throws NonSquareMatrixException { 688 final int nRows = getRowDimension(); 689 final int nCols = getColumnDimension(); 690 if (nRows != nCols) { 691 throw new NonSquareMatrixException(nRows, nCols); 692 } 693 T trace = field.getZero(); 694 for (int i = 0; i < nRows; ++i) { 695 trace = trace.add(getEntry(i, i)); 696 } 697 return trace; 698 } 699 700 /** {@inheritDoc} */ 701 public T[] operate(final T[] v) throws DimensionMismatchException { 702 703 final int nRows = getRowDimension(); 704 final int nCols = getColumnDimension(); 705 if (v.length != nCols) { 706 throw new DimensionMismatchException(v.length, nCols); 707 } 708 709 final T[] out = MathArrays.buildArray(field, nRows); 710 for (int row = 0; row < nRows; ++row) { 711 T sum = field.getZero(); 712 for (int i = 0; i < nCols; ++i) { 713 sum = sum.add(getEntry(row, i).multiply(v[i])); 714 } 715 out[row] = sum; 716 } 717 718 return out; 719 } 720 721 /** {@inheritDoc} */ 722 public FieldVector<T> operate(final FieldVector<T> v) 723 throws DimensionMismatchException { 724 try { 725 return new ArrayFieldVector<T>(field, operate(((ArrayFieldVector<T>) v).getDataRef()), false); 726 } catch (ClassCastException cce) { 727 final int nRows = getRowDimension(); 728 final int nCols = getColumnDimension(); 729 if (v.getDimension() != nCols) { 730 throw new DimensionMismatchException(v.getDimension(), nCols); 731 } 732 733 final T[] out = MathArrays.buildArray(field, nRows); 734 for (int row = 0; row < nRows; ++row) { 735 T sum = field.getZero(); 736 for (int i = 0; i < nCols; ++i) { 737 sum = sum.add(getEntry(row, i).multiply(v.getEntry(i))); 738 } 739 out[row] = sum; 740 } 741 742 return new ArrayFieldVector<T>(field, out, false); 743 } 744 } 745 746 /** {@inheritDoc} */ 747 public T[] preMultiply(final T[] v) throws DimensionMismatchException { 748 749 final int nRows = getRowDimension(); 750 final int nCols = getColumnDimension(); 751 if (v.length != nRows) { 752 throw new DimensionMismatchException(v.length, nRows); 753 } 754 755 final T[] out = MathArrays.buildArray(field, nCols); 756 for (int col = 0; col < nCols; ++col) { 757 T sum = field.getZero(); 758 for (int i = 0; i < nRows; ++i) { 759 sum = sum.add(getEntry(i, col).multiply(v[i])); 760 } 761 out[col] = sum; 762 } 763 764 return out; 765 } 766 767 /** {@inheritDoc} */ 768 public FieldVector<T> preMultiply(final FieldVector<T> v) 769 throws DimensionMismatchException { 770 try { 771 return new ArrayFieldVector<T>(field, preMultiply(((ArrayFieldVector<T>) v).getDataRef()), false); 772 } catch (ClassCastException cce) { 773 final int nRows = getRowDimension(); 774 final int nCols = getColumnDimension(); 775 if (v.getDimension() != nRows) { 776 throw new DimensionMismatchException(v.getDimension(), nRows); 777 } 778 779 final T[] out = MathArrays.buildArray(field, nCols); 780 for (int col = 0; col < nCols; ++col) { 781 T sum = field.getZero(); 782 for (int i = 0; i < nRows; ++i) { 783 sum = sum.add(getEntry(i, col).multiply(v.getEntry(i))); 784 } 785 out[col] = sum; 786 } 787 788 return new ArrayFieldVector<T>(field, out, false); 789 } 790 } 791 792 /** {@inheritDoc} */ 793 public T walkInRowOrder(final FieldMatrixChangingVisitor<T> visitor) { 794 final int rows = getRowDimension(); 795 final int columns = getColumnDimension(); 796 visitor.start(rows, columns, 0, rows - 1, 0, columns - 1); 797 for (int row = 0; row < rows; ++row) { 798 for (int column = 0; column < columns; ++column) { 799 final T oldValue = getEntry(row, column); 800 final T newValue = visitor.visit(row, column, oldValue); 801 setEntry(row, column, newValue); 802 } 803 } 804 return visitor.end(); 805 } 806 807 /** {@inheritDoc} */ 808 public T walkInRowOrder(final FieldMatrixPreservingVisitor<T> visitor) { 809 final int rows = getRowDimension(); 810 final int columns = getColumnDimension(); 811 visitor.start(rows, columns, 0, rows - 1, 0, columns - 1); 812 for (int row = 0; row < rows; ++row) { 813 for (int column = 0; column < columns; ++column) { 814 visitor.visit(row, column, getEntry(row, column)); 815 } 816 } 817 return visitor.end(); 818 } 819 820 /** {@inheritDoc} */ 821 public T walkInRowOrder(final FieldMatrixChangingVisitor<T> visitor, 822 final int startRow, final int endRow, 823 final int startColumn, final int endColumn) 824 throws NumberIsTooSmallException, OutOfRangeException { 825 checkSubMatrixIndex(startRow, endRow, startColumn, endColumn); 826 visitor.start(getRowDimension(), getColumnDimension(), 827 startRow, endRow, startColumn, endColumn); 828 for (int row = startRow; row <= endRow; ++row) { 829 for (int column = startColumn; column <= endColumn; ++column) { 830 final T oldValue = getEntry(row, column); 831 final T newValue = visitor.visit(row, column, oldValue); 832 setEntry(row, column, newValue); 833 } 834 } 835 return visitor.end(); 836 } 837 838 /** {@inheritDoc} */ 839 public T walkInRowOrder(final FieldMatrixPreservingVisitor<T> visitor, 840 final int startRow, final int endRow, 841 final int startColumn, final int endColumn) 842 throws NumberIsTooSmallException, OutOfRangeException { 843 checkSubMatrixIndex(startRow, endRow, startColumn, endColumn); 844 visitor.start(getRowDimension(), getColumnDimension(), 845 startRow, endRow, startColumn, endColumn); 846 for (int row = startRow; row <= endRow; ++row) { 847 for (int column = startColumn; column <= endColumn; ++column) { 848 visitor.visit(row, column, getEntry(row, column)); 849 } 850 } 851 return visitor.end(); 852 } 853 854 /** {@inheritDoc} */ 855 public T walkInColumnOrder(final FieldMatrixChangingVisitor<T> visitor) { 856 final int rows = getRowDimension(); 857 final int columns = getColumnDimension(); 858 visitor.start(rows, columns, 0, rows - 1, 0, columns - 1); 859 for (int column = 0; column < columns; ++column) { 860 for (int row = 0; row < rows; ++row) { 861 final T oldValue = getEntry(row, column); 862 final T newValue = visitor.visit(row, column, oldValue); 863 setEntry(row, column, newValue); 864 } 865 } 866 return visitor.end(); 867 } 868 869 /** {@inheritDoc} */ 870 public T walkInColumnOrder(final FieldMatrixPreservingVisitor<T> visitor) { 871 final int rows = getRowDimension(); 872 final int columns = getColumnDimension(); 873 visitor.start(rows, columns, 0, rows - 1, 0, columns - 1); 874 for (int column = 0; column < columns; ++column) { 875 for (int row = 0; row < rows; ++row) { 876 visitor.visit(row, column, getEntry(row, column)); 877 } 878 } 879 return visitor.end(); 880 } 881 882 /** {@inheritDoc} */ 883 public T walkInColumnOrder(final FieldMatrixChangingVisitor<T> visitor, 884 final int startRow, final int endRow, 885 final int startColumn, final int endColumn) 886 throws NumberIsTooSmallException, OutOfRangeException { 887 checkSubMatrixIndex(startRow, endRow, startColumn, endColumn); 888 visitor.start(getRowDimension(), getColumnDimension(), 889 startRow, endRow, startColumn, endColumn); 890 for (int column = startColumn; column <= endColumn; ++column) { 891 for (int row = startRow; row <= endRow; ++row) { 892 final T oldValue = getEntry(row, column); 893 final T newValue = visitor.visit(row, column, oldValue); 894 setEntry(row, column, newValue); 895 } 896 } 897 return visitor.end(); 898 } 899 900 /** {@inheritDoc} */ 901 public T walkInColumnOrder(final FieldMatrixPreservingVisitor<T> visitor, 902 final int startRow, final int endRow, 903 final int startColumn, final int endColumn) 904 throws NumberIsTooSmallException, OutOfRangeException{ 905 checkSubMatrixIndex(startRow, endRow, startColumn, endColumn); 906 visitor.start(getRowDimension(), getColumnDimension(), 907 startRow, endRow, startColumn, endColumn); 908 for (int column = startColumn; column <= endColumn; ++column) { 909 for (int row = startRow; row <= endRow; ++row) { 910 visitor.visit(row, column, getEntry(row, column)); 911 } 912 } 913 return visitor.end(); 914 } 915 916 /** {@inheritDoc} */ 917 public T walkInOptimizedOrder(final FieldMatrixChangingVisitor<T> visitor) { 918 return walkInRowOrder(visitor); 919 } 920 921 /** {@inheritDoc} */ 922 public T walkInOptimizedOrder(final FieldMatrixPreservingVisitor<T> visitor) { 923 return walkInRowOrder(visitor); 924 } 925 926 /** {@inheritDoc} */ 927 public T walkInOptimizedOrder(final FieldMatrixChangingVisitor<T> visitor, 928 final int startRow, final int endRow, 929 final int startColumn, final int endColumn) 930 throws NumberIsTooSmallException, OutOfRangeException { 931 return walkInRowOrder(visitor, startRow, endRow, startColumn, endColumn); 932 } 933 934 /** {@inheritDoc} */ 935 public T walkInOptimizedOrder(final FieldMatrixPreservingVisitor<T> visitor, 936 final int startRow, final int endRow, 937 final int startColumn, final int endColumn) 938 throws NumberIsTooSmallException, OutOfRangeException { 939 return walkInRowOrder(visitor, startRow, endRow, startColumn, endColumn); 940 } 941 942 /** 943 * Get a string representation for this matrix. 944 * @return a string representation for this matrix 945 */ 946 @Override 947 public String toString() { 948 final int nRows = getRowDimension(); 949 final int nCols = getColumnDimension(); 950 final StringBuffer res = new StringBuffer(); 951 String fullClassName = getClass().getName(); 952 String shortClassName = fullClassName.substring(fullClassName.lastIndexOf('.') + 1); 953 res.append(shortClassName).append("{"); 954 955 for (int i = 0; i < nRows; ++i) { 956 if (i > 0) { 957 res.append(","); 958 } 959 res.append("{"); 960 for (int j = 0; j < nCols; ++j) { 961 if (j > 0) { 962 res.append(","); 963 } 964 res.append(getEntry(i, j)); 965 } 966 res.append("}"); 967 } 968 969 res.append("}"); 970 return res.toString(); 971 } 972 973 /** 974 * Returns true iff <code>object</code> is a 975 * <code>FieldMatrix</code> instance with the same dimensions as this 976 * and all corresponding matrix entries are equal. 977 * 978 * @param object the object to test equality against. 979 * @return true if object equals this 980 */ 981 @Override 982 public boolean equals(final Object object) { 983 if (object == this ) { 984 return true; 985 } 986 if (object instanceof FieldMatrix<?> == false) { 987 return false; 988 } 989 FieldMatrix<?> m = (FieldMatrix<?>) object; 990 final int nRows = getRowDimension(); 991 final int nCols = getColumnDimension(); 992 if (m.getColumnDimension() != nCols || m.getRowDimension() != nRows) { 993 return false; 994 } 995 for (int row = 0; row < nRows; ++row) { 996 for (int col = 0; col < nCols; ++col) { 997 if (!getEntry(row, col).equals(m.getEntry(row, col))) { 998 return false; 999 } 1000 } 1001 } 1002 return true; 1003 } 1004 1005 /** 1006 * Computes a hashcode for the matrix. 1007 * 1008 * @return hashcode for matrix 1009 */ 1010 @Override 1011 public int hashCode() { 1012 int ret = 322562; 1013 final int nRows = getRowDimension(); 1014 final int nCols = getColumnDimension(); 1015 ret = ret * 31 + nRows; 1016 ret = ret * 31 + nCols; 1017 for (int row = 0; row < nRows; ++row) { 1018 for (int col = 0; col < nCols; ++col) { 1019 ret = ret * 31 + (11 * (row+1) + 17 * (col+1)) * getEntry(row, col).hashCode(); 1020 } 1021 } 1022 return ret; 1023 } 1024 1025 /** 1026 * Check if a row index is valid. 1027 * 1028 * @param row Row index to check. 1029 * @throws OutOfRangeException if {@code index} is not valid. 1030 */ 1031 protected void checkRowIndex(final int row) throws OutOfRangeException { 1032 if (row < 0 || row >= getRowDimension()) { 1033 throw new OutOfRangeException(LocalizedFormats.ROW_INDEX, 1034 row, 0, getRowDimension() - 1); 1035 } 1036 } 1037 1038 /** 1039 * Check if a column index is valid. 1040 * 1041 * @param column Column index to check. 1042 * @throws OutOfRangeException if {@code index} is not valid. 1043 */ 1044 protected void checkColumnIndex(final int column) 1045 throws OutOfRangeException { 1046 if (column < 0 || column >= getColumnDimension()) { 1047 throw new OutOfRangeException(LocalizedFormats.COLUMN_INDEX, 1048 column, 0, getColumnDimension() - 1); 1049 } 1050 } 1051 1052 /** 1053 * Check if submatrix ranges indices are valid. 1054 * Rows and columns are indicated counting from 0 to n-1. 1055 * 1056 * @param startRow Initial row index. 1057 * @param endRow Final row index. 1058 * @param startColumn Initial column index. 1059 * @param endColumn Final column index. 1060 * @throws OutOfRangeException if the indices are not valid. 1061 * @throws NumberIsTooSmallException if {@code endRow < startRow} or 1062 * {@code endColumn < startColumn}. 1063 */ 1064 protected void checkSubMatrixIndex(final int startRow, final int endRow, 1065 final int startColumn, final int endColumn) 1066 throws NumberIsTooSmallException, OutOfRangeException { 1067 checkRowIndex(startRow); 1068 checkRowIndex(endRow); 1069 if (endRow < startRow) { 1070 throw new NumberIsTooSmallException(LocalizedFormats.INITIAL_ROW_AFTER_FINAL_ROW, 1071 endRow, startRow, true); 1072 } 1073 1074 checkColumnIndex(startColumn); 1075 checkColumnIndex(endColumn); 1076 if (endColumn < startColumn) { 1077 throw new NumberIsTooSmallException(LocalizedFormats.INITIAL_COLUMN_AFTER_FINAL_COLUMN, 1078 endColumn, startColumn, true); 1079 } 1080 } 1081 1082 /** 1083 * Check if submatrix ranges indices are valid. 1084 * Rows and columns are indicated counting from 0 to n-1. 1085 * 1086 * @param selectedRows Array of row indices. 1087 * @param selectedColumns Array of column indices. 1088 * @throws NullArgumentException if the arrays are {@code null}. 1089 * @throws NoDataException if the arrays have zero length. 1090 * @throws OutOfRangeException if row or column selections are not valid. 1091 */ 1092 protected void checkSubMatrixIndex(final int[] selectedRows, final int[] selectedColumns) 1093 throws NoDataException, NullArgumentException, OutOfRangeException { 1094 if (selectedRows == null || 1095 selectedColumns == null) { 1096 throw new NullArgumentException(); 1097 } 1098 if (selectedRows.length == 0 || 1099 selectedColumns.length == 0) { 1100 throw new NoDataException(); 1101 } 1102 1103 for (final int row : selectedRows) { 1104 checkRowIndex(row); 1105 } 1106 for (final int column : selectedColumns) { 1107 checkColumnIndex(column); 1108 } 1109 } 1110 1111 /** 1112 * Check if a matrix is addition compatible with the instance. 1113 * 1114 * @param m Matrix to check. 1115 * @throws MatrixDimensionMismatchException if the matrix is not 1116 * addition-compatible with instance. 1117 */ 1118 protected void checkAdditionCompatible(final FieldMatrix<T> m) 1119 throws MatrixDimensionMismatchException { 1120 if ((getRowDimension() != m.getRowDimension()) || 1121 (getColumnDimension() != m.getColumnDimension())) { 1122 throw new MatrixDimensionMismatchException(m.getRowDimension(), m.getColumnDimension(), 1123 getRowDimension(), getColumnDimension()); 1124 } 1125 } 1126 1127 /** 1128 * Check if a matrix is subtraction compatible with the instance. 1129 * 1130 * @param m Matrix to check. 1131 * @throws MatrixDimensionMismatchException if the matrix is not 1132 * subtraction-compatible with instance. 1133 */ 1134 protected void checkSubtractionCompatible(final FieldMatrix<T> m) 1135 throws MatrixDimensionMismatchException { 1136 if ((getRowDimension() != m.getRowDimension()) || 1137 (getColumnDimension() != m.getColumnDimension())) { 1138 throw new MatrixDimensionMismatchException(m.getRowDimension(), m.getColumnDimension(), 1139 getRowDimension(), getColumnDimension()); 1140 } 1141 } 1142 1143 /** 1144 * Check if a matrix is multiplication compatible with the instance. 1145 * 1146 * @param m Matrix to check. 1147 * @throws DimensionMismatchException if the matrix is not 1148 * multiplication-compatible with instance. 1149 */ 1150 protected void checkMultiplicationCompatible(final FieldMatrix<T> m) 1151 throws DimensionMismatchException { 1152 if (getColumnDimension() != m.getRowDimension()) { 1153 throw new DimensionMismatchException(m.getRowDimension(), getColumnDimension()); 1154 } 1155 } 1156}