1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
27
28
29
30
31
32
33
34
35
36 public abstract class AbstractFieldMatrix<T extends FieldElement<T>> implements FieldMatrix<T> {
37
38
39 private final Field<T> field;
40
41
42
43
44
45
46
47
48 protected static <T extends FieldElement<T>> Field<T> extractField(final T[][] d)
49 throws IllegalArgumentException {
50 if (d.length == 0) {
51 throw MathRuntimeException.createIllegalArgumentException("matrix must have at least one row");
52 }
53 if (d[0].length == 0) {
54 throw MathRuntimeException.createIllegalArgumentException("matrix must have at least one column");
55 }
56 return d[0][0].getField();
57 }
58
59
60
61
62
63
64
65
66 protected static <T extends FieldElement<T>> Field<T> extractField(final T[] d)
67 throws IllegalArgumentException {
68 if (d.length == 0) {
69 throw MathRuntimeException.createIllegalArgumentException("matrix must have at least one row");
70 }
71 return d[0].getField();
72 }
73
74
75
76
77
78
79
80
81
82
83
84
85 @SuppressWarnings("unchecked")
86 protected static <T extends FieldElement<T>> T[][] buildArray(final Field<T> field,
87 final int rows,
88 final int columns) {
89 if (columns < 0) {
90 T[] dummyRow = (T[]) Array.newInstance(field.getZero().getClass(), 0);
91 return (T[][]) Array.newInstance(dummyRow.getClass(), rows);
92 }
93 T[][] array =
94 (T[][]) Array.newInstance(field.getZero().getClass(), new int[] { rows, columns });
95 for (int i = 0; i < array.length; ++i) {
96 Arrays.fill(array[i], field.getZero());
97 }
98 return array;
99 }
100
101
102
103
104
105
106
107
108
109
110 @SuppressWarnings("unchecked")
111 protected static <T extends FieldElement<T>> T[] buildArray(final Field<T> field,
112 final int length) {
113 T[] array = (T[]) Array.newInstance(field.getZero().getClass(), length);
114 Arrays.fill(array, field.getZero());
115 return array;
116 }
117
118
119
120
121 protected AbstractFieldMatrix() {
122 field = null;
123 }
124
125
126
127
128
129 protected AbstractFieldMatrix(final Field<T> field) {
130 this.field = field;
131 }
132
133
134
135
136
137
138
139
140
141 protected AbstractFieldMatrix(final Field<T> field,
142 final int rowDimension, final int columnDimension)
143 throws IllegalArgumentException {
144 if (rowDimension <= 0 ) {
145 throw MathRuntimeException.createIllegalArgumentException(
146 "invalid row dimension {0} (must be positive)",
147 rowDimension);
148 }
149 if (columnDimension <= 0) {
150 throw MathRuntimeException.createIllegalArgumentException(
151 "invalid column dimension {0} (must be positive)",
152 columnDimension);
153 }
154 this.field = field;
155 }
156
157
158 public Field<T> getField() {
159 return field;
160 }
161
162
163 public abstract FieldMatrix<T> createMatrix(final int rowDimension, final int columnDimension)
164 throws IllegalArgumentException;
165
166
167 public abstract FieldMatrix<T> copy();
168
169
170 public FieldMatrix<T> add(FieldMatrix<T> m) throws IllegalArgumentException {
171
172
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
189 public FieldMatrix<T> subtract(final FieldMatrix<T> m) throws IllegalArgumentException {
190
191
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
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
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
240 public FieldMatrix<T> multiply(final FieldMatrix<T> m)
241 throws IllegalArgumentException {
242
243
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
265 public FieldMatrix<T> preMultiply(final FieldMatrix<T> m)
266 throws IllegalArgumentException {
267 return m.multiply(this);
268 }
269
270
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
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
306 public FieldMatrix<T> getSubMatrix(final int[] selectedRows, final int[] selectedColumns)
307 throws MatrixIndexException {
308
309
310 checkSubMatrixIndex(selectedRows, selectedColumns);
311
312
313 final FieldMatrix<T> subMatrix =
314 createMatrix(selectedRows.length, selectedColumns.length);
315 subMatrix.walkInOptimizedOrder(new DefaultFieldMatrixChangingVisitor<T>(field.getZero()) {
316
317
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
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
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 "dimensions mismatch: got {0}x{1} but expected {2}x{3}",
342 destination.length, destination[0].length,
343 rowsCount, columnsCount);
344 }
345
346
347 walkInOptimizedOrder(new DefaultFieldMatrixPreservingVisitor<T>(field.getZero()) {
348
349
350 private int startRow;
351
352
353 private int startColumn;
354
355
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
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
375 public void copySubMatrix(int[] selectedRows, int[] selectedColumns, T[][] destination)
376 throws MatrixIndexException, IllegalArgumentException {
377
378
379 checkSubMatrixIndex(selectedRows, selectedColumns);
380 if ((destination.length < selectedRows.length) ||
381 (destination[0].length < selectedColumns.length)) {
382 throw MathRuntimeException.createIllegalArgumentException(
383 "dimensions mismatch: got {0}x{1} but expected {2}x{3}",
384 destination.length, destination[0].length,
385 selectedRows.length, selectedColumns.length);
386 }
387
388
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
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("matrix must have at least one row");
405 }
406
407 final int nCols = subMatrix[0].length;
408 if (nCols == 0) {
409 throw MathRuntimeException.createIllegalArgumentException("matrix must have 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 "some rows have length {0} while others have length {1}",
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
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
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 "dimensions mismatch: got {0}x{1} but expected {2}x{3}",
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
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
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 "dimensions mismatch: got {0}x{1} but expected {2}x{3}",
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
500 public FieldVector<T> getRowVector(final int row)
501 throws MatrixIndexException {
502 return new ArrayFieldVector<T>(getRow(row), false);
503 }
504
505
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 "dimensions mismatch: got {0}x{1} but expected {2}x{3}",
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
523 public FieldVector<T> getColumnVector(final int column)
524 throws MatrixIndexException {
525 return new ArrayFieldVector<T>(getColumn(column), false);
526 }
527
528
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 "dimensions mismatch: got {0}x{1} but expected {2}x{3}",
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
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
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 "dimensions mismatch: got {0}x{1} but expected {2}x{3}",
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
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
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 "dimensions mismatch: got {0}x{1} but expected {2}x{3}",
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
610 public abstract T getEntry(int row, int column)
611 throws MatrixIndexException;
612
613
614 public abstract void setEntry(int row, int column, T value)
615 throws MatrixIndexException;
616
617
618 public abstract void addToEntry(int row, int column, T increment)
619 throws MatrixIndexException;
620
621
622 public abstract void multiplyEntry(int row, int column, T factor)
623 throws MatrixIndexException;
624
625
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
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
646 public boolean isSquare() {
647 return (getColumnDimension() == getRowDimension());
648 }
649
650
651 public abstract int getRowDimension();
652
653
654 public abstract int getColumnDimension();
655
656
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
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 "vector length mismatch: got {0} but expected {1}",
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
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 "vector length mismatch: got {0} but expected {1}",
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
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 "vector length mismatch: got {0} but expected {1}",
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
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 "vector length mismatch: got {0} but expected {1}",
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
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
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
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
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
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
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
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
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
906 public T walkInOptimizedOrder(final FieldMatrixChangingVisitor<T> visitor)
907 throws MatrixVisitorException {
908 return walkInRowOrder(visitor);
909 }
910
911
912 public T walkInOptimizedOrder(final FieldMatrixPreservingVisitor<T> visitor)
913 throws MatrixVisitorException {
914 return walkInRowOrder(visitor);
915 }
916
917
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
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
935
936
937 @Override
938 public String toString() {
939 final int nRows = getRowDimension();
940 final int nCols = getColumnDimension();
941 final StringBuffer res = new StringBuffer();
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
967
968
969
970
971
972
973 @SuppressWarnings("unchecked")
974 @Override
975 public boolean equals(final Object object) {
976 if (object == this ) {
977 return true;
978 }
979 if (object instanceof FieldMatrix == false) {
980 return false;
981 }
982 FieldMatrix<T> m = (FieldMatrix<T>) object;
983 final int nRows = getRowDimension();
984 final int nCols = getColumnDimension();
985 if (m.getColumnDimension() != nCols || m.getRowDimension() != nRows) {
986 return false;
987 }
988 for (int row = 0; row < nRows; ++row) {
989 for (int col = 0; col < nCols; ++col) {
990 if (!getEntry(row, col).equals(m.getEntry(row, col))) {
991 return false;
992 }
993 }
994 }
995 return true;
996 }
997
998
999
1000
1001
1002
1003 @Override
1004 public int hashCode() {
1005 int ret = 322562;
1006 final int nRows = getRowDimension();
1007 final int nCols = getColumnDimension();
1008 ret = ret * 31 + nRows;
1009 ret = ret * 31 + nCols;
1010 for (int row = 0; row < nRows; ++row) {
1011 for (int col = 0; col < nCols; ++col) {
1012 ret = ret * 31 + (11 * (row+1) + 17 * (col+1)) * getEntry(row, col).hashCode();
1013 }
1014 }
1015 return ret;
1016 }
1017
1018
1019
1020
1021
1022
1023 protected void checkRowIndex(final int row) {
1024 if (row < 0 || row >= getRowDimension()) {
1025 throw new MatrixIndexException("row index {0} out of allowed range [{1}, {2}]",
1026 row, 0, getRowDimension() - 1);
1027 }
1028 }
1029
1030
1031
1032
1033
1034
1035 protected void checkColumnIndex(final int column)
1036 throws MatrixIndexException {
1037 if (column < 0 || column >= getColumnDimension()) {
1038 throw new MatrixIndexException("column index {0} out of allowed range [{1}, {2}]",
1039 column, 0, getColumnDimension() - 1);
1040 }
1041 }
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053 protected void checkSubMatrixIndex(final int startRow, final int endRow,
1054 final int startColumn, final int endColumn) {
1055 checkRowIndex(startRow);
1056 checkRowIndex(endRow);
1057 if (startRow > endRow) {
1058 throw new MatrixIndexException("initial row {0} after final row {1}",
1059 startRow, endRow);
1060 }
1061
1062 checkColumnIndex(startColumn);
1063 checkColumnIndex(endColumn);
1064 if (startColumn > endColumn) {
1065 throw new MatrixIndexException("initial column {0} after final column {1}",
1066 startColumn, endColumn);
1067 }
1068
1069
1070 }
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080 protected void checkSubMatrixIndex(final int[] selectedRows, final int[] selectedColumns) {
1081 if (selectedRows.length * selectedColumns.length == 0) {
1082 if (selectedRows.length == 0) {
1083 throw new MatrixIndexException("empty selected row index array");
1084 }
1085 throw new MatrixIndexException("empty selected column index array");
1086 }
1087
1088 for (final int row : selectedRows) {
1089 checkRowIndex(row);
1090 }
1091 for (final int column : selectedColumns) {
1092 checkColumnIndex(column);
1093 }
1094 }
1095
1096
1097
1098
1099
1100
1101 protected void checkAdditionCompatible(final FieldMatrix<T> m) {
1102 if ((getRowDimension() != m.getRowDimension()) ||
1103 (getColumnDimension() != m.getColumnDimension())) {
1104 throw MathRuntimeException.createIllegalArgumentException(
1105 "{0}x{1} and {2}x{3} matrices are not addition compatible",
1106 getRowDimension(), getColumnDimension(),
1107 m.getRowDimension(), m.getColumnDimension());
1108 }
1109 }
1110
1111
1112
1113
1114
1115
1116 protected void checkSubtractionCompatible(final FieldMatrix<T> m) {
1117 if ((getRowDimension() != m.getRowDimension()) ||
1118 (getColumnDimension() != m.getColumnDimension())) {
1119 throw MathRuntimeException.createIllegalArgumentException(
1120 "{0}x{1} and {2}x{3} matrices are not subtraction compatible",
1121 getRowDimension(), getColumnDimension(),
1122 m.getRowDimension(), m.getColumnDimension());
1123 }
1124 }
1125
1126
1127
1128
1129
1130
1131 protected void checkMultiplicationCompatible(final FieldMatrix<T> m) {
1132 if (getColumnDimension() != m.getRowDimension()) {
1133 throw MathRuntimeException.createIllegalArgumentException(
1134 "{0}x{1} and {2}x{3} matrices are not multiplication compatible",
1135 getRowDimension(), getColumnDimension(),
1136 m.getRowDimension(), m.getColumnDimension());
1137 }
1138 }
1139
1140 }