KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jscience > mathematics > vectors > Float64Matrix


1 /*
2  * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
3  * Copyright (C) 2006 - JScience (http://jscience.org/)
4  * All rights reserved.
5  *
6  * Permission to use, copy, modify, and distribute this software is
7  * freely granted, provided that this notice is preserved.
8  */

9 package org.jscience.mathematics.vectors;
10
11 import java.util.Iterator JavaDoc;
12 import java.util.List JavaDoc;
13
14 import javolution.context.ConcurrentContext;
15 import javolution.lang.MathLib;
16 import javolution.util.FastTable;
17 import javolution.util.Index;
18
19 import org.jscience.mathematics.numbers.Float64;
20
21 /**
22  * <p> This class represents an optimized {@link Matrix matrix} implementation
23  * for {@link Float64 64 bits floating-point} numbers.</p>
24  *
25  * <p> Instances of this class can be created from {@link Float64Vector},
26  * either as rows or columns if the matrix is transposed. For example:[code]
27  * Float64Vector<Rational> column0 = Float64Vector.valueOf(...);
28  * Float64Vector<Rational> column1 = Float64Vector.valueOf(...);
29  * Float64Matrix<Rational> M = Float64Matrix.valueOf(column0, column1).transpose();
30  * [/code]</p>
31  *
32  * @author <a HREF="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
33  * @version 3.3, January 2, 2007
34  */

35 public final class Float64Matrix extends Matrix<Float64> {
36
37     /**
38      * Holds the number of columns n.
39      */

40     int _n;;
41
42     /**
43      * Indicates if this matrix is transposed (the rows are then the columns).
44      */

45     boolean _transposed;
46
47     /**
48      * Holds this matrix rows (or columns when transposed).
49      */

50     final FastTable<Float64Vector> _rows = new FastTable<Float64Vector>();
51
52     /**
53      * Returns a dense matrix from a 2-dimensional array of <code>double</code>
54      * values. The first dimension being the row and the second being the
55      * column.
56      *
57      * @param values the array of <code>double</code> values.
58      * @return the matrix having the specified elements.
59      * @throws DimensionException if rows have different length.
60      * @see Float64Vector
61      */

62     public static Float64Matrix valueOf(double[][] values) {
63         int m = values.length;
64         int n = values[0].length;
65         Float64Matrix M = Float64Matrix.newInstance(n, false);
66         for (int i = 0; i < m; i++) {
67             Float64Vector row = Float64Vector.valueOf(values[i]);
68             if (row.getDimension() != n)
69                 throw new DimensionException();
70             M._rows.add(row);
71         }
72         return M;
73     }
74
75     /**
76      * Returns a complex matrix holding the specified row vectors
77      * (column vectors if {@link #transpose transposed}).
78      *
79      * @param rows the row vectors.
80      * @return the matrix having the specified rows.
81      * @throws DimensionException if the rows do not have the same dimension.
82      */

83     public static Float64Matrix valueOf(Float64Vector... rows) {
84         final int n = rows[0].getDimension();
85         Float64Matrix M = Float64Matrix.newInstance(n, false);
86         for (int i = 0, m = rows.length; i < m; i++) {
87             Float64Vector rowi = rows[i];
88             if (rowi.getDimension() != n)
89                 throw new DimensionException(
90                         "All vectors must have the same dimension.");
91             M._rows.add(rowi);
92         }
93         return M;
94     }
95
96     /**
97      * Returns a complex matrix holding the row vectors from the specified
98      * collection (column vectors if {@link #transpose transposed}).
99      *
100      * @param rows the list of row vectors.
101      * @return the matrix having the specified rows.
102      * @throws DimensionException if the rows do not have the same dimension.
103      */

104     public static Float64Matrix valueOf(List JavaDoc<Float64Vector> rows) {
105         final int n = rows.get(0).getDimension();
106         Float64Matrix M = Float64Matrix.newInstance(n, false);
107         Iterator JavaDoc<Float64Vector> iterator = rows.iterator();
108         for (int i = 0, m = rows.size(); i < m; i++) {
109             Float64Vector rowi = iterator.next();
110             if (rowi.getDimension() != n)
111                 throw new DimensionException(
112                         "All vectors must have the same dimension.");
113             M._rows.add(rowi);
114         }
115         return M;
116     }
117     
118     /**
119      * Returns a complex matrix equivalent to the specified matrix.
120      *
121      * @param that the matrix to convert.
122      * @return <code>that</code> or a complex matrix holding the same elements
123      * as the specified matrix.
124      */

125     public static Float64Matrix valueOf(Matrix<Float64> that) {
126         if (that instanceof Float64Matrix) return (Float64Matrix)that;
127         int n = that.getNumberOfColumns();
128         int m = that.getNumberOfRows();
129         Float64Matrix M = Float64Matrix.newInstance(n, false);
130         for (int i = 0; i < m; i++) {
131             Float64Vector rowi = Float64Vector.valueOf(that.getRow(i));
132             M._rows.add(rowi);
133         }
134         return M;
135     }
136
137     @Override JavaDoc
138     public int getNumberOfRows() {
139         return _transposed ? _n : _rows.size();
140     }
141
142     @Override JavaDoc
143     public int getNumberOfColumns() {
144         return _transposed ? _rows.size() : _n;
145     }
146
147     @Override JavaDoc
148     public Float64 get(int i, int j) {
149         return _transposed ? _rows.get(j).get(i) : _rows.get(i).get(j);
150     }
151
152     @Override JavaDoc
153     public Float64Vector getRow(int i) {
154         if (!_transposed) return _rows.get(i);
155         // Else transposed.
156
int n = _rows.size();
157         int m = _n;
158         if ((i < 0) || (i >= m)) throw new DimensionException();
159         Float64Vector V = Float64Vector.newInstance(n);
160         for (int j=0; j < n; j++) {
161             V.set(j, _rows.get(j).get(i));
162         }
163         return V;
164     }
165
166     @Override JavaDoc
167     public Float64Vector getColumn(int j) {
168         if (_transposed) return _rows.get(j);
169         int m = _rows.size();
170         if ((j < 0) || (j >= _n)) throw new DimensionException();
171         Float64Vector V = Float64Vector.newInstance(m);
172         for (int i=0; i < m; i++) {
173             V.set(i, _rows.get(i).get(j));
174         }
175         return V;
176     }
177
178     @Override JavaDoc
179     public Float64Vector getDiagonal() {
180         int m = this.getNumberOfRows();
181         int n = this.getNumberOfColumns();
182         int dimension = MathLib.min(m, n);
183         Float64Vector V = Float64Vector.newInstance(dimension);
184         for (int i=0; i < dimension; i++) {
185             V.set(i, this.get(i, i));
186         }
187         return V;
188     }
189     
190     @Override JavaDoc
191     public Float64Matrix opposite() {
192         Float64Matrix M = Float64Matrix.newInstance(_n, _transposed);
193         for (int i = 0, p = _rows.size(); i < p; i++) {
194             M._rows.add(_rows.get(i).opposite());
195         }
196         return M;
197     }
198
199     @Override JavaDoc
200     public Float64Matrix plus(Matrix<Float64> that) {
201         if (this.getNumberOfRows() != that.getNumberOfRows())
202             throw new DimensionException();
203         Float64Matrix M = Float64Matrix.newInstance(_n, _transposed);
204         for (int i = 0, p = _rows.size(); i < p; i++) {
205             M._rows.add(_rows.get(i).plus(_transposed ? that.getColumn(i) : that.getRow(i)));
206         }
207         return M;
208     }
209
210     @Override JavaDoc
211     public Float64Matrix minus(Matrix<Float64> that) { // Returns more specialized type.
212
return this.plus(that.opposite());
213     }
214
215     @Override JavaDoc
216     public Float64Matrix times(Float64 k) {
217         Float64Matrix M = Float64Matrix.newInstance(_n, _transposed);
218         for (int i = 0, p = _rows.size(); i < p; i++) {
219             M._rows.add(_rows.get(i).times(k));
220         }
221         return M;
222     }
223
224     @Override JavaDoc
225     public Float64Vector times(Vector<Float64> v) {
226         if (v.getDimension() != this.getNumberOfColumns())
227             throw new DimensionException();
228         final int m = this.getNumberOfRows();
229         Float64Vector V = Float64Vector.newInstance(m);
230         for (int i = 0; i < m; i++) {
231             V.set(i, this.getRow(i).times(v));
232         }
233         return V;
234     }
235
236     @Override JavaDoc
237     public Float64Matrix times(Matrix<Float64> that) {
238         if (_transposed) // this.inverse().transpose() == this.transpose().inverse()
239
return this.transpose().inverse().transpose();
240         // this is a row matrix.
241
final int m = this.getNumberOfRows();
242         final int p = that.getNumberOfColumns();
243         if (that.getNumberOfRows() != _n)
244             throw new DimensionException();
245         // Creates a mxp matrix in transposed form (p columns vectors of size m)
246
Float64Matrix M = Float64Matrix.newInstance(m, true); // Transposed.
247
multiply(that, Index.valueOf(0), Index.valueOf(p), M._rows);
248         return M;
249     }
250     
251     // Multiplies this row matrix with the columns of the specified matrix.
252
private void multiply(
253             Matrix<Float64> that, Index startColumn, Index endColumn, FastTable<Float64Vector> columnsResult) {
254         final int start = startColumn.intValue();
255         final int end = endColumn.intValue();
256         if (end - start < 32) { // Direct calculation.
257
final int m = this._rows.size();
258             for (int j = start; j < end; j++) {
259                 Vector<Float64> thatColj = that.getColumn(j);
260                 Float64Vector column = Float64Vector.newInstance(m);
261                 columnsResult.add(column);
262                 for (int i = 0; i < m; i++) {
263                     Float64Vector thisRowi = this.getRow(i);
264                     column.set(i, thisRowi.times(thatColj));
265                 }
266             }
267         } else { // Concurrent execution.
268
FastTable<Float64Vector> r1 = FastTable.newInstance();
269             FastTable<Float64Vector> r2 = FastTable.newInstance();
270             Index half = Index.valueOf((start + end) >> 1);
271             ConcurrentContext.enter();
272             try {
273                 ConcurrentContext.execute(MULTIPLY, this, that, startColumn, half, r1);
274                 ConcurrentContext.execute(MULTIPLY, this, that, half, endColumn, r2);
275             } finally {
276                 ConcurrentContext.exit();
277             }
278             columnsResult.addAll(r1);
279             columnsResult.addAll(r2);
280             FastTable.recycle(r1);
281             FastTable.recycle(r2);
282         }
283     }
284     private static ConcurrentContext.Logic MULTIPLY = new ConcurrentContext.Logic() {
285         @SuppressWarnings JavaDoc("unchecked")
286         public void run() {
287             Float64Matrix _this = getArgument(0);
288             Matrix _that = getArgument(1);
289             Index _startColumn = getArgument(2);
290             Index _endColumn = getArgument(3);
291             FastTable _columnsResult = getArgument(4);
292             _this.multiply(_that, _startColumn, _endColumn, _columnsResult);
293         }
294     };
295     
296  
297     @Override JavaDoc
298     public Float64Matrix inverse() {
299         if (!isSquare())
300             throw new DimensionException("Matrix not square");
301         return Float64Matrix.valueOf(LUDecomposition.valueOf(this).inverse());
302     }
303     
304     @Override JavaDoc
305     public Float64 determinant() {
306         return LUDecomposition.valueOf(this).determinant();
307     }
308
309     @Override JavaDoc
310     public Float64Matrix transpose() {
311        Float64Matrix M = Float64Matrix.newInstance(_n, !_transposed);
312        M._rows.addAll(this._rows);
313        return M;
314     }
315
316     @Override JavaDoc
317     public Float64 cofactor(int i, int j) {
318         if (_transposed) {
319             int k = i; i = j; j = k; // Swaps i,j
320
}
321         int m = _rows.size();
322         Float64Matrix M = Float64Matrix.newInstance(m - 1, _transposed);
323         for (int k1=0; k1 < m; k1++) {
324             if (k1 == i) continue;
325             Float64Vector row = _rows.get(k1);
326             Float64Vector V = Float64Vector.newInstance(_n - 1);
327             M._rows.add(V);
328             for (int k2=0, k=0; k2 < _n; k2++) {
329                 if (k2 == j) continue;
330                 V.set(k++, row.get(k2));
331             }
332         }
333         return M.determinant();
334     }
335     
336     @Override JavaDoc
337     public Float64Matrix adjoint() {
338         Float64Matrix M = Float64Matrix.newInstance(_n, _transposed);
339         int m = _rows.size();
340         for (int i = 0; i < m; i++) {
341             Float64Vector row = Float64Vector.newInstance(_n);
342             M._rows.add(row);
343             for (int j = 0; j < _n; j++) {
344                 Float64 cofactor = _transposed ? cofactor(j, i) : cofactor(i, j);
345                 row.set(j, ((i + j) % 2 == 0) ? cofactor : cofactor.opposite());
346             }
347         }
348         return M.transpose();
349     }
350
351     @Override JavaDoc
352     public Float64Matrix tensor(Matrix<Float64> that) {
353         return Float64Matrix.valueOf(DenseMatrix.valueOf(this).tensor(that));
354     }
355
356     @Override JavaDoc
357     public Float64Vector vectorization() {
358         return Float64Vector.valueOf(DenseMatrix.valueOf(this).vectorization());
359     }
360     
361     @Override JavaDoc
362     public boolean move(ObjectSpace os) {
363         if (super.move(os)) {
364             // The rows table itself is intrinsic (all final members are)
365
// and implicitely moves with this matrix.
366
// But it may refer to locally/stack allocated vectors which
367
// need to be moved along.
368
for (int i=0, n=_rows.size(); i < n; i++) {
369                 _rows.get(i).move(os);
370             }
371             return true;
372         }
373         return false;
374     }
375         
376     ///////////////////////
377
// Factory creation. //
378
///////////////////////
379

380     static Float64Matrix newInstance(int n, boolean transposed) {
381         Float64Matrix M = FACTORY.object();
382         M._n = n;
383         M._transposed = transposed;
384         return M;
385     }
386     
387     private static Factory<Float64Matrix> FACTORY = new Factory<Float64Matrix>() {
388         @Override JavaDoc
389         protected Float64Matrix create() {
390             return new Float64Matrix();
391         }
392         @Override JavaDoc
393         protected void cleanup(Float64Matrix matrix) {
394             matrix._rows.reset();
395         }
396     };
397
398     private Float64Matrix() {
399     }
400
401     private static final long serialVersionUID = 1L;
402
403 }
Popular Tags