KickJava   Java API By Example, From Geeks To Geeks.

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


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.Complex;
20
21 /**
22  * <p> This class represents an optimized {@link Matrix matrix} implementation
23  * for {@link Complex complex} numbers.</p>
24  *
25  * <p> Instances of this class can be created from {@link ComplexVector},
26  * either as rows or columns if the matrix is transposed. For example:[code]
27  * ComplexVector<Rational> column0 = ComplexVector.valueOf(...);
28  * ComplexVector<Rational> column1 = ComplexVector.valueOf(...);
29  * ComplexMatrix<Rational> M = ComplexMatrix.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 ComplexMatrix extends Matrix<Complex> {
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<ComplexVector> _rows = new FastTable<ComplexVector>();
51
52     /**
53      * Returns a complex matrix from the specified 2-dimensional array.
54      * The first dimension being the row and the second being the column.
55      *
56      * @param elements this matrix elements.
57      * @return the matrix having the specified elements.
58      * @throws DimensionException if rows have different length.
59      * @see ComplexVector
60      */

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

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

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

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

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