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
9
* http://www.apache.org/licenses/LICENSE-2.0
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.
18
package org.apache.commons.math.linear;
20
import java.io.Serializable;
22
import org.apache.commons.math.Field;
23
import org.apache.commons.math.FieldElement;
24
import org.apache.commons.math.MathRuntimeException;
27
* Implementation of FieldMatrix<T> using a {@link FieldElement}[][] array to store entries.
29
* As specified in the {@link FieldMatrix} interface, matrix element indexing
30
* is 0-based -- e.g., <code>getEntry(0, 0)</code>
31
* returns the element in the first row, first column of the matrix.</li></ul>
34
* @param <T> the type of the field elements
35
* @version $Revision: 783702 $ $Date: 2009-06-11 04:54:02 -0400 (Thu, 11 Jun 2009) $
37
public class Array2DRowFieldMatrix<T extends FieldElement<T>> extends AbstractFieldMatrix<T> implements Serializable {
39
/** Serializable version identifier */
40
private static final long serialVersionUID = 7260756672015356458L;
42
/** Entries of the matrix */
46
* Creates a matrix with no data
47
* @param field field to which the elements belong
49
public Array2DRowFieldMatrix(final Field<T> field) {
54
* Create a new FieldMatrix<T> with the supplied row and column dimensions.
56
* @param field field to which the elements belong
57
* @param rowDimension the number of rows in the new matrix
58
* @param columnDimension the number of columns in the new matrix
59
* @throws IllegalArgumentException if row or column dimension is not
62
public Array2DRowFieldMatrix(final Field<T> field,
63
final int rowDimension, final int columnDimension)
64
throws IllegalArgumentException {
65
super(field, rowDimension, columnDimension);
66
data = buildArray(field, rowDimension, columnDimension);
70
* Create a new FieldMatrix<T> using the input array as the underlying
72
* <p>The input array is copied, not referenced. This constructor has
73
* the same effect as calling {@link #Array2DRowFieldMatrix(FieldElement[][], boolean)}
74
* with the second argument set to <code>true</code>.</p>
76
* @param d data for new matrix
77
* @throws IllegalArgumentException if <code>d</code> is not rectangular
78
* (not all rows have the same length) or empty
79
* @throws NullPointerException if <code>d</code> is null
80
* @see #Array2DRowFieldMatrix(FieldElement[][], boolean)
82
public Array2DRowFieldMatrix(final T[][] d)
83
throws IllegalArgumentException, NullPointerException {
84
super(extractField(d));
89
* Create a new FieldMatrix<T> using the input array as the underlying
91
* <p>If an array is built specially in order to be embedded in a
92
* FieldMatrix<T> and not used directly, the <code>copyArray</code> may be
93
* set to <code>false</code. This will prevent the copying and improve
94
* performance as no new array will be built and no data will be copied.</p>
95
* @param d data for new matrix
96
* @param copyArray if true, the input array will be copied, otherwise
97
* it will be referenced
98
* @throws IllegalArgumentException if <code>d</code> is not rectangular
99
* (not all rows have the same length) or empty
100
* @throws NullPointerException if <code>d</code> is null
101
* @see #Array2DRowFieldMatrix(FieldElement[][])
103
public Array2DRowFieldMatrix(final T[][] d, final boolean copyArray)
104
throws IllegalArgumentException, NullPointerException {
105
super(extractField(d));
110
throw new NullPointerException();
112
final int nRows = d.length;
114
throw MathRuntimeException.createIllegalArgumentException("matrix must have at least one row");
116
final int nCols = d[0].length;
118
throw MathRuntimeException.createIllegalArgumentException("matrix must have at least one column");
120
for (int r = 1; r < nRows; r++) {
121
if (d[r].length != nCols) {
122
throw MathRuntimeException.createIllegalArgumentException(
123
"some rows have length {0} while others have length {1}",
132
* Create a new (column) FieldMatrix<T> using <code>v</code> as the
133
* data for the unique column of the <code>v.length x 1</code> matrix
135
* <p>The input array is copied, not referenced.</p>
137
* @param v column vector holding data for new matrix
139
public Array2DRowFieldMatrix(final T[] v) {
140
super(extractField(v));
141
final int nRows = v.length;
142
data = buildArray(getField(), nRows, 1);
143
for (int row = 0; row < nRows; row++) {
144
data[row][0] = v[row];
150
public FieldMatrix<T> createMatrix(final int rowDimension, final int columnDimension)
151
throws IllegalArgumentException {
152
return new Array2DRowFieldMatrix<T>(getField(), rowDimension, columnDimension);
157
public FieldMatrix<T> copy() {
158
return new Array2DRowFieldMatrix<T>(copyOut(), false);
163
public FieldMatrix<T> add(final FieldMatrix<T> m)
164
throws IllegalArgumentException {
166
return add((Array2DRowFieldMatrix<T>) m);
167
} catch (ClassCastException cce) {
173
* Compute the sum of this and <code>m</code>.
175
* @param m matrix to be added
177
* @throws IllegalArgumentException if m is not the same size as this
179
public Array2DRowFieldMatrix<T> add(final Array2DRowFieldMatrix<T> m)
180
throws IllegalArgumentException {
183
checkAdditionCompatible(m);
185
final int rowCount = getRowDimension();
186
final int columnCount = getColumnDimension();
187
final T[][] outData = buildArray(getField(), rowCount, columnCount);
188
for (int row = 0; row < rowCount; row++) {
189
final T[] dataRow = data[row];
190
final T[] mRow = m.data[row];
191
final T[] outDataRow = outData[row];
192
for (int col = 0; col < columnCount; col++) {
193
outDataRow[col] = dataRow[col].add(mRow[col]);
197
return new Array2DRowFieldMatrix<T>(outData, false);
203
public FieldMatrix<T> subtract(final FieldMatrix<T> m)
204
throws IllegalArgumentException {
206
return subtract((Array2DRowFieldMatrix<T>) m);
207
} catch (ClassCastException cce) {
208
return super.subtract(m);
213
* Compute this minus <code>m</code>.
215
* @param m matrix to be subtracted
217
* @throws IllegalArgumentException if m is not the same size as this
219
public Array2DRowFieldMatrix<T> subtract(final Array2DRowFieldMatrix<T> m)
220
throws IllegalArgumentException {
223
checkSubtractionCompatible(m);
225
final int rowCount = getRowDimension();
226
final int columnCount = getColumnDimension();
227
final T[][] outData = buildArray(getField(), rowCount, columnCount);
228
for (int row = 0; row < rowCount; row++) {
229
final T[] dataRow = data[row];
230
final T[] mRow = m.data[row];
231
final T[] outDataRow = outData[row];
232
for (int col = 0; col < columnCount; col++) {
233
outDataRow[col] = dataRow[col].subtract(mRow[col]);
237
return new Array2DRowFieldMatrix<T>(outData, false);
243
public FieldMatrix<T> multiply(final FieldMatrix<T> m)
244
throws IllegalArgumentException {
246
return multiply((Array2DRowFieldMatrix<T>) m);
247
} catch (ClassCastException cce) {
248
return super.multiply(m);
253
* Returns the result of postmultiplying this by <code>m</code>.
254
* @param m matrix to postmultiply by
256
* @throws IllegalArgumentException
257
* if columnDimension(this) != rowDimension(m)
259
public Array2DRowFieldMatrix<T> multiply(final Array2DRowFieldMatrix<T> m)
260
throws IllegalArgumentException {
263
checkMultiplicationCompatible(m);
265
final int nRows = this.getRowDimension();
266
final int nCols = m.getColumnDimension();
267
final int nSum = this.getColumnDimension();
268
final T[][] outData = buildArray(getField(), nRows, nCols);
269
for (int row = 0; row < nRows; row++) {
270
final T[] dataRow = data[row];
271
final T[] outDataRow = outData[row];
272
for (int col = 0; col < nCols; col++) {
273
T sum = getField().getZero();
274
for (int i = 0; i < nSum; i++) {
275
sum = sum.add(dataRow[i].multiply(m.data[i][col]));
277
outDataRow[col] = sum;
281
return new Array2DRowFieldMatrix<T>(outData, false);
287
public T[][] getData() {
292
* Returns a reference to the underlying data array.
294
* Does <strong>not</strong> make a fresh copy of the underlying data.</p>
296
* @return 2-dimensional array of entries
298
public T[][] getDataRef() {
304
public void setSubMatrix(final T[][] subMatrix, final int row, final int column)
305
throws MatrixIndexException {
308
throw MathRuntimeException.createIllegalStateException(
309
"first {0} rows are not initialized yet",
313
throw MathRuntimeException.createIllegalStateException(
314
"first {0} columns are not initialized yet",
317
final int nRows = subMatrix.length;
319
throw MathRuntimeException.createIllegalArgumentException("matrix must have at least one row");
322
final int nCols = subMatrix[0].length;
324
throw MathRuntimeException.createIllegalArgumentException("matrix must have at least one column");
326
data = buildArray(getField(), subMatrix.length, nCols);
327
for (int i = 0; i < data.length; ++i) {
328
if (subMatrix[i].length != nCols) {
329
throw MathRuntimeException.createIllegalArgumentException(
330
"some rows have length {0} while others have length {1}",
331
nCols, subMatrix[i].length);
333
System.arraycopy(subMatrix[i], 0, data[i + row], column, nCols);
336
super.setSubMatrix(subMatrix, row, column);
343
public T getEntry(final int row, final int column)
344
throws MatrixIndexException {
346
return data[row][column];
347
} catch (ArrayIndexOutOfBoundsException e) {
348
throw new MatrixIndexException(
349
"no entry at indices ({0}, {1}) in a {2}x{3} matrix",
350
row, column, getRowDimension(), getColumnDimension());
356
public void setEntry(final int row, final int column, final T value)
357
throws MatrixIndexException {
359
data[row][column] = value;
360
} catch (ArrayIndexOutOfBoundsException e) {
361
throw new MatrixIndexException(
362
"no entry at indices ({0}, {1}) in a {2}x{3} matrix",
363
row, column, getRowDimension(), getColumnDimension());
369
public void addToEntry(final int row, final int column, final T increment)
370
throws MatrixIndexException {
372
data[row][column] = data[row][column].add(increment);
373
} catch (ArrayIndexOutOfBoundsException e) {
374
throw new MatrixIndexException(
375
"no entry at indices ({0}, {1}) in a {2}x{3} matrix",
376
row, column, getRowDimension(), getColumnDimension());
382
public void multiplyEntry(final int row, final int column, final T factor)
383
throws MatrixIndexException {
385
data[row][column] = data[row][column].multiply(factor);
386
} catch (ArrayIndexOutOfBoundsException e) {
387
throw new MatrixIndexException(
388
"no entry at indices ({0}, {1}) in a {2}x{3} matrix",
389
row, column, getRowDimension(), getColumnDimension());
395
public int getRowDimension() {
396
return (data == null) ? 0 : data.length;
401
public int getColumnDimension() {
402
return ((data == null) || (data[0] == null)) ? 0 : data[0].length;
407
public T[] operate(final T[] v)
408
throws IllegalArgumentException {
409
final int nRows = this.getRowDimension();
410
final int nCols = this.getColumnDimension();
411
if (v.length != nCols) {
412
throw MathRuntimeException.createIllegalArgumentException(
413
"vector length mismatch: got {0} but expected {1}",
416
final T[] out = buildArray(getField(), nRows);
417
for (int row = 0; row < nRows; row++) {
418
final T[] dataRow = data[row];
419
T sum = getField().getZero();
420
for (int i = 0; i < nCols; i++) {
421
sum = sum.add(dataRow[i].multiply(v[i]));
430
public T[] preMultiply(final T[] v)
431
throws IllegalArgumentException {
433
final int nRows = getRowDimension();
434
final int nCols = getColumnDimension();
435
if (v.length != nRows) {
436
throw MathRuntimeException.createIllegalArgumentException(
437
"vector length mismatch: got {0} but expected {1}",
441
final T[] out = buildArray(getField(), nCols);
442
for (int col = 0; col < nCols; ++col) {
443
T sum = getField().getZero();
444
for (int i = 0; i < nRows; ++i) {
445
sum = sum.add(data[i][col].multiply(v[i]));
456
public T walkInRowOrder(final FieldMatrixChangingVisitor<T> visitor)
457
throws MatrixVisitorException {
458
final int rows = getRowDimension();
459
final int columns = getColumnDimension();
460
visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
461
for (int i = 0; i < rows; ++i) {
462
final T[] rowI = data[i];
463
for (int j = 0; j < columns; ++j) {
464
rowI[j] = visitor.visit(i, j, rowI[j]);
467
return visitor.end();
472
public T walkInRowOrder(final FieldMatrixPreservingVisitor<T> visitor)
473
throws MatrixVisitorException {
474
final int rows = getRowDimension();
475
final int columns = getColumnDimension();
476
visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
477
for (int i = 0; i < rows; ++i) {
478
final T[] rowI = data[i];
479
for (int j = 0; j < columns; ++j) {
480
visitor.visit(i, j, rowI[j]);
483
return visitor.end();
488
public T walkInRowOrder(final FieldMatrixChangingVisitor<T> visitor,
489
final int startRow, final int endRow,
490
final int startColumn, final int endColumn)
491
throws MatrixIndexException, MatrixVisitorException {
492
checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
493
visitor.start(getRowDimension(), getColumnDimension(),
494
startRow, endRow, startColumn, endColumn);
495
for (int i = startRow; i <= endRow; ++i) {
496
final T[] rowI = data[i];
497
for (int j = startColumn; j <= endColumn; ++j) {
498
rowI[j] = visitor.visit(i, j, rowI[j]);
501
return visitor.end();
506
public T walkInRowOrder(final FieldMatrixPreservingVisitor<T> visitor,
507
final int startRow, final int endRow,
508
final int startColumn, final int endColumn)
509
throws MatrixIndexException, MatrixVisitorException {
510
checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
511
visitor.start(getRowDimension(), getColumnDimension(),
512
startRow, endRow, startColumn, endColumn);
513
for (int i = startRow; i <= endRow; ++i) {
514
final T[] rowI = data[i];
515
for (int j = startColumn; j <= endColumn; ++j) {
516
visitor.visit(i, j, rowI[j]);
519
return visitor.end();
524
public T walkInColumnOrder(final FieldMatrixChangingVisitor<T> visitor)
525
throws MatrixVisitorException {
526
final int rows = getRowDimension();
527
final int columns = getColumnDimension();
528
visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
529
for (int j = 0; j < columns; ++j) {
530
for (int i = 0; i < rows; ++i) {
531
final T[] rowI = data[i];
532
rowI[j] = visitor.visit(i, j, rowI[j]);
535
return visitor.end();
540
public T walkInColumnOrder(final FieldMatrixPreservingVisitor<T> visitor)
541
throws MatrixVisitorException {
542
final int rows = getRowDimension();
543
final int columns = getColumnDimension();
544
visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
545
for (int j = 0; j < columns; ++j) {
546
for (int i = 0; i < rows; ++i) {
547
visitor.visit(i, j, data[i][j]);
550
return visitor.end();
555
public T walkInColumnOrder(final FieldMatrixChangingVisitor<T> visitor,
556
final int startRow, final int endRow,
557
final int startColumn, final int endColumn)
558
throws MatrixIndexException, MatrixVisitorException {
559
checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
560
visitor.start(getRowDimension(), getColumnDimension(),
561
startRow, endRow, startColumn, endColumn);
562
for (int j = startColumn; j <= endColumn; ++j) {
563
for (int i = startRow; i <= endRow; ++i) {
564
final T[] rowI = data[i];
565
rowI[j] = visitor.visit(i, j, rowI[j]);
568
return visitor.end();
573
public T walkInColumnOrder(final FieldMatrixPreservingVisitor<T> visitor,
574
final int startRow, final int endRow,
575
final int startColumn, final int endColumn)
576
throws MatrixIndexException, MatrixVisitorException {
577
checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
578
visitor.start(getRowDimension(), getColumnDimension(),
579
startRow, endRow, startColumn, endColumn);
580
for (int j = startColumn; j <= endColumn; ++j) {
581
for (int i = startRow; i <= endRow; ++i) {
582
visitor.visit(i, j, data[i][j]);
585
return visitor.end();
589
* Returns a fresh copy of the underlying data array.
591
* @return a copy of the underlying data array.
593
private T[][] copyOut() {
594
final int nRows = this.getRowDimension();
595
final T[][] out = buildArray(getField(), nRows, getColumnDimension());
596
// can't copy 2-d array in one shot, otherwise get row references
597
for (int i = 0; i < nRows; i++) {
598
System.arraycopy(data[i], 0, out[i], 0, data[i].length);
604
* Replaces data with a fresh copy of the input array.
606
* Verifies that the input array is rectangular and non-empty.</p>
608
* @param in data to copy in
609
* @throws IllegalArgumentException if input array is empty or not
611
* @throws NullPointerException if input array is null
613
private void copyIn(final T[][] in) {
614
setSubMatrix(in, 0, 0);