~ubuntu-branches/ubuntu/maverick/commons-math/maverick

« back to all changes in this revision

Viewing changes to src/main/java/org/apache/commons/math/linear/AbstractRealMatrix.java

  • Committer: Bazaar Package Importer
  • Author(s): Damien Raude-Morvan
  • Date: 2009-08-22 01:13:25 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20090822011325-hi4peq1ua5weguwn
Tags: 2.0-1
* New upstream release.
* Set Maintainer field to Debian Java Team
* Add myself as Uploaders
* Switch to Quilt patch system:
  - Refresh all patchs
  - Remove B-D on dpatch, Add B-D on quilt
  - Include patchsys-quilt.mk in debian/rules
* Bump Standards-Version to 3.8.3:
  - Add a README.source to describe patch system
* Maven POMs:
  - Add a Build-Depends-Indep dependency on maven-repo-helper
  - Use mh_installpom and mh_installjar to install the POM and the jar to the
    Maven repository
* Use default-jdk/jre:
  - Depends on java5-runtime-headless
  - Build-Depends on default-jdk
  - Use /usr/lib/jvm/default-java as JAVA_HOME
* Move api documentation to /usr/share/doc/libcommons-math-java/api
* Build-Depends on junit4 instead of junit

Show diffs side-by-side

added added

removed removed

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