001// --- BEGIN LICENSE BLOCK ---
002/* 
003 * Copyright (c) 2009, Mikio L. Braun
004 * All rights reserved.
005 * 
006 * Redistribution and use in source and binary forms, with or without
007 * modification, are permitted provided that the following conditions are
008 * met:
009 * 
010 *     * Redistributions of source code must retain the above copyright
011 *       notice, this list of conditions and the following disclaimer.
012 * 
013 *     * Redistributions in binary form must reproduce the above
014 *       copyright notice, this list of conditions and the following
015 *       disclaimer in the documentation and/or other materials provided
016 *       with the distribution.
017 * 
018 *     * Neither the name of the Technische Universit?t Berlin nor the
019 *       names of its contributors may be used to endorse or promote
020 *       products derived from this software without specific prior
021 *       written permission.
022 * 
023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
024 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
025 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
026 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
027 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
028 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
029 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
030 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
031 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
032 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
033 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
034 */
035// --- END LICENSE BLOCK ---
036
037package org.jblas;
038
039import org.jblas.exceptions.SizeException;
040
041import java.io.DataInputStream;
042import java.io.DataOutputStream;
043import java.io.FileInputStream;
044import java.io.FileOutputStream;
045import java.io.IOException;
046
047public class ComplexFloatMatrix {
048        
049        public int rows;
050        public int columns;
051        public int length;
052        public float[] data = null; // rows are contiguous
053
054        /**************************************************************************
055         * 
056         * Constructors and factory functions
057         * 
058         **************************************************************************/
059
060        /** Create a new matrix with <i>newRows</i> rows, <i>newColumns</i> columns
061         * using <i>newData></i> as the data. The length of the data is not checked!
062         */
063        public ComplexFloatMatrix(int newRows, int newColumns, float... newData) {
064                rows = newRows;
065                columns = newColumns;
066                length = rows * columns;
067
068                if (newData.length != 2 * newRows * newColumns)
069                        throw new IllegalArgumentException(
070                                        "Passed data must match matrix dimensions.");
071
072                data = newData;
073        }
074        
075        /**
076         * Creates a new <i>n</i> times <i>m</i> <tt>ComplexFloatMatrix</tt>.
077         * @param newRows the number of rows (<i>n</i>) of the new matrix.
078         * @param newColumns the number of columns (<i>m</i>) of the new matrix.
079         */
080        public ComplexFloatMatrix(int newRows, int newColumns) {
081                this(newRows, newColumns, new float[2 * newRows * newColumns]);
082        }
083        
084        /**
085         * Creates a new <tt>ComplexFloatMatrix</tt> of size 0 times 0.
086         */
087        public ComplexFloatMatrix() {
088                this(0, 0, null);
089        }
090
091        /**
092         * Create a Matrix of length <tt>len</tt>. By default, this creates a row vector.
093         * @param len
094         */
095        public ComplexFloatMatrix(int len) {
096                this(len, 1, new float[2 * len]);
097        }
098        
099        public ComplexFloatMatrix(float[] newData) {
100                this(newData.length/2);
101                                
102                data = newData;
103        }
104
105        public ComplexFloatMatrix(ComplexFloat[] newData) {
106                this(newData.length);
107                                
108                for (int i = 0; i < newData.length; i++)
109                        put(i, newData[i]);
110        }
111                
112        
113        /** Construct a complex matrix from a real matrix. */
114        public ComplexFloatMatrix(FloatMatrix m) {
115            this(m.rows, m.columns);
116            
117            NativeBlas.scopy(m.length, m.data, 0, 1, data, 0, 2);
118        }
119
120        /** Construct a complex matrix from separate real and imaginary parts. Either 
121         * part can be set to null in which case it will be ignored.
122         */
123        public ComplexFloatMatrix(FloatMatrix real, FloatMatrix imag) {
124            this(real.rows, real.columns);
125            real.assertSameSize(imag);
126            
127            if (real != null)
128                NativeBlas.scopy(length, real.data, 0, 1, data, 0, 2);
129            if (imag != null)
130                NativeBlas.scopy(length, imag.data, 0, 1, data, 1, 2);
131        }
132        
133        /**
134         * Creates a new matrix by reading it from a file.
135         * @param filename the path and name of the file to read the matrix from
136         * @throws IOException 
137         */
138        public ComplexFloatMatrix(String filename) throws IOException {
139                load(filename);
140        }
141        
142        /**
143         * Creates a new <i>n</i> times <i>m</i> <tt>ComplexFloatMatrix</tt> from
144         * the given <i>n</i> times <i>m</i> 2D data array. The first dimension of the array makes the
145         * rows (<i>n</i>) and the second dimension the columns (<i>m</i>). For example, the
146         * given code <br/><br/>
147         * <code>new ComplexFloatMatrix(new float[][]{{1d, 2d, 3d}, {4d, 5d, 6d}, {7d, 8d, 9d}}).print();</code><br/><br/>
148         * will constructs the following matrix:
149         * <pre>
150         * 1.0f 2.0f    3.0f
151         * 4.0f 5.0f    6.0f
152         * 7.0f 8.0f    9.0f
153         * </pre>.
154         * @param data <i>n</i> times <i>m</i> data array
155         */ 
156        public ComplexFloatMatrix(float[][] data) {
157                this(data.length, data[0].length);
158                                                
159                for (int r = 0; r < rows; r++)
160                        assert(data[r].length == columns);
161                
162                for (int r = 0; r < rows; r++)
163                        for (int c = 0; c < columns; c++)
164                                put(r, c, data[r][c]);
165        }
166        
167        /**
168         * Creates a new matrix in which all values are equal 0.
169         * @param rows number of rows
170         * @param columns number of columns
171         * @return new matrix
172         */
173        public static ComplexFloatMatrix zeros(int rows, int columns) {
174                return new ComplexFloatMatrix(rows, columns);
175        }
176        
177        public static ComplexFloatMatrix zeros(int length) {
178                return zeros(length, 1);
179        }
180
181        /**
182         * Creates a new matrix in which all values are equal 1.
183         * @param rows number of rows
184         * @param columns number of columns
185         * @return new matrix
186         */
187        public static ComplexFloatMatrix ones(int rows, int columns) {
188                ComplexFloatMatrix m = new ComplexFloatMatrix(rows, columns);
189                
190                for (int i = 0; i < rows * columns; i++)
191                        m.put(i, 1.0f);
192                
193                return m;
194        }
195        
196        public static ComplexFloatMatrix ones(int length) {
197                return ones(length, 1);
198        }
199        
200        /**
201         * Creates a new matrix where the values of the given vector are the diagonal values of
202         * the matrix.
203         * @param x the diagonal values
204         * @return new matrix
205         */
206        public static ComplexFloatMatrix diag(ComplexFloatMatrix x) {
207                ComplexFloatMatrix m = new ComplexFloatMatrix(x.length, x.length);
208                
209                for (int i = 0; i < x.length; i++)
210                        m.put(i, i, x.get(i));
211                
212                return m;
213        }
214        
215        /**
216         * Create a 1 * 1 - matrix. For many operations, this matrix functions like a
217         * normal float
218         * @param s value of the matrix
219         * @return the constructed ComplexFloatMatrix 
220         */
221        public static ComplexFloatMatrix scalar(float s) {
222                ComplexFloatMatrix m = new ComplexFloatMatrix(1, 1);
223                m.put(0, 0, s);
224                return m;
225        }
226        
227        /** Test whether a matrix is scalar */
228        public boolean isScalar() {
229                return length == 1;
230        }
231        
232        /** Return the first element of the matrix */
233        public ComplexFloat scalar() {
234                return get(0);
235        }
236        
237        public static ComplexFloatMatrix concatHorizontally(ComplexFloatMatrix A, ComplexFloatMatrix B) {
238                if (A.rows != B.rows)
239                        throw new SizeException("Matrices don't have same number of rows.");
240                
241                ComplexFloatMatrix result = new ComplexFloatMatrix(A.rows, A.columns + B.columns);
242                SimpleBlas.copy(A, result);
243                NativeBlas.ccopy(B.length, B.data, 0, 1, result.data, A.length, 1);
244                return result;
245        }
246
247        public static ComplexFloatMatrix concatVertically(ComplexFloatMatrix A, ComplexFloatMatrix B) {
248                if (A.columns != B.columns)
249                        throw new SizeException("Matrices don't have same number of columns.");
250                
251                ComplexFloatMatrix result = new ComplexFloatMatrix(A.rows + B.rows, A.columns);
252
253                for (int i = 0; i < A.columns; i++) {
254                        NativeBlas.ccopy(A.rows, A.data, A.index(0, i), 1, result.data, result.index(0, i), 1);
255                        NativeBlas.ccopy(B.rows, B.data, B.index(0, i), 1, result.data, result.index(A.rows, i), 1);
256                }
257                
258                return result;
259        }
260        
261        /**************************************************************************
262         * Working with slices (Man! 30+ methods just to make this a bit flexible...) 
263         */
264
265        public ComplexFloatMatrix get(int[] indices) {
266                ComplexFloatMatrix result = new ComplexFloatMatrix(indices.length);
267                
268                for (int i = 0; i < indices.length; i++)
269                        result.put(i, get(indices[i]));
270                
271                return result;
272        }
273        
274        public ComplexFloatMatrix get(int r, int[] indices) {
275                ComplexFloatMatrix result = new ComplexFloatMatrix(1, indices.length);
276                
277                for (int i = 0; i < indices.length; i++)
278                        result.put(i, get(r, indices[i]));
279                
280                return result;
281        }
282        
283        public ComplexFloatMatrix get(int[] indices, int c) {
284                ComplexFloatMatrix result = new ComplexFloatMatrix(indices.length, c);
285                
286                for (int i = 0; i < indices.length; i++)
287                        result.put(i, get(indices[i], c));
288                
289                return result;
290        }
291        
292        public ComplexFloatMatrix get(int[] rindices, int[] cindices) {
293                ComplexFloatMatrix result = new ComplexFloatMatrix(rindices.length, cindices.length);
294                
295                for (int i = 0; i < rindices.length; i++)
296                        for (int j = 0; j < cindices.length; j++)
297                                result.put(i, j, get(rindices[i], cindices[j]));
298                
299                return result;
300        }
301        
302        public ComplexFloatMatrix get(ComplexFloatMatrix indices) {
303                return get(indices.findIndices());
304        }
305
306        public ComplexFloatMatrix get(int r, ComplexFloatMatrix indices) {
307                return get(r, indices.findIndices());
308        }
309        
310        public ComplexFloatMatrix get(ComplexFloatMatrix indices, int c) {
311                return get(indices.findIndices(), c);
312        }
313
314        public ComplexFloatMatrix get(ComplexFloatMatrix rindices, ComplexFloatMatrix cindices) {
315                return get(rindices.findIndices(), cindices.findIndices());
316        }
317        
318        private void checkLength(int l) {
319                if (length != l)
320                        throw new SizeException("Matrix does not have the necessary length (" + length + " != " + l + ").");
321        }
322
323        private void checkRows(int r) {
324                if (rows != r)
325                        throw new SizeException("Matrix does not have the necessary length (" + length + " != " + r + ").");
326        }
327        
328        private void checkColumns(int c) {
329                if (columns != c)
330                        throw new SizeException("Matrix does not have the necessary length (" + length + " != " + c + ").");
331        }
332
333        public ComplexFloatMatrix put(int[] indices, ComplexFloatMatrix x) {
334                if (x.isScalar())
335                        return put(indices, x.scalar());
336                x.checkLength(indices.length);
337                
338                for (int i = 0; i < indices.length; i++)
339                        put(indices[i], x.get(i));
340                
341                return this;
342        }
343        
344        public ComplexFloatMatrix put(int r, int[] indices, ComplexFloatMatrix x) {
345                if (x.isScalar())
346                        return put(r, indices, x.scalar());
347                x.checkColumns(indices.length);
348                
349                for (int i = 0; i < indices.length; i++)
350                        put(r, indices[i], x.get(i));
351                
352                return this;
353        }
354        
355        public ComplexFloatMatrix put(int[] indices, int c, ComplexFloatMatrix x) {
356                if (x.isScalar())
357                        return put(indices, c, x.scalar());             
358                x.checkRows(indices.length);
359                
360                for (int i = 0; i < indices.length; i++)
361                        put(indices[i], c, x.get(i));
362                
363                return this;
364        }
365        
366        public ComplexFloatMatrix put(int[] rindices, int[] cindices, ComplexFloatMatrix x) {
367                if (x.isScalar())
368                        return put(rindices, cindices, x.scalar());             
369                x.checkRows(rindices.length);
370                x.checkColumns(cindices.length);
371                
372                for (int i = 0; i < rindices.length; i++)
373                        for (int j = 0; j < cindices.length; j++)
374                                put(rindices[i], cindices[j], x.get(i,j));
375                
376                return this;
377        }
378        
379        public ComplexFloatMatrix put(int[] indices, float v) {
380                for (int i = 0; i < indices.length; i++)
381                        put(indices[i], v);
382                
383                return this;
384        }
385
386        public ComplexFloatMatrix putReal(int[] indices, float v) {
387                return put(indices, v);
388        }
389
390        public ComplexFloatMatrix putImag(int[] indices, float v) {
391                for (int i = 0; i < indices.length; i++)
392                        putImag(indices[i], v);
393                
394                return this;
395        }
396
397        public ComplexFloatMatrix put(int[] indices, ComplexFloat v) {
398                for (int i = 0; i < indices.length; i++)
399                        put(indices[i], v);
400                
401                return this;
402        }
403
404        public ComplexFloatMatrix put(int r, int[] indices, float v) {
405                for (int i = 0; i < indices.length; i++)
406                        put(r, indices[i], v);
407                
408                return this;
409        }
410
411        public ComplexFloatMatrix putReal(int r, int[] indices, float v) {
412                return put(r, indices, v);
413        }
414
415        public ComplexFloatMatrix putImag(int r, int[] indices, float v) {
416                for (int i = 0; i < indices.length; i++)
417                        putImag(r, indices[i], v);
418                
419                return this;
420        }
421
422        public ComplexFloatMatrix put(int r, int[] indices, ComplexFloat v) {
423                for (int i = 0; i < indices.length; i++)
424                        put(r, indices[i], v);
425                
426                return this;
427        }
428
429        public ComplexFloatMatrix put(int[] indices, int c, float v) {
430                for (int i = 0; i < indices.length; i++)
431                        put(indices[i], c, v);
432                
433                return this;
434        }
435        
436        public ComplexFloatMatrix putReal(int[] indices, int c, float v) {
437                return put(indices, c, v);
438        }
439        
440        public ComplexFloatMatrix putImag(int[] indices, int c, float v) {
441                for (int i = 0; i < indices.length; i++)
442                        putImag(indices[i], c, v);
443                
444                return this;
445        }
446        
447        public ComplexFloatMatrix put(int[] indices, int c, ComplexFloat v) {
448                for (int i = 0; i < indices.length; i++)
449                        put(indices[i], c, v);
450                
451                return this;
452        }
453        
454        public ComplexFloatMatrix put(int[] rindices, int[] cindices, float v) {
455                for (int i = 0; i < rindices.length; i++)
456                        for (int j = 0; j < cindices.length; j++)
457                                put(rindices[i], cindices[j], v);
458                
459                return this;
460        }
461        
462        public ComplexFloatMatrix putReal(int[] rindices, int[] cindices, float v) {
463                return put(rindices, cindices, v);
464        }
465        
466        public ComplexFloatMatrix putImag(int[] rindices, int[] cindices, float v) {
467                for (int i = 0; i < rindices.length; i++)
468                        for (int j = 0; j < cindices.length; j++)
469                                put(rindices[i], cindices[j], v);
470                
471                return this;
472        }
473
474        public ComplexFloatMatrix put(int[] rindices, int[] cindices, ComplexFloat v) {
475                for (int i = 0; i < rindices.length; i++)
476                        for (int j = 0; j < cindices.length; j++)
477                                put(rindices[i], cindices[j], v);
478                
479                return this;
480        }
481
482        public ComplexFloatMatrix put(ComplexFloatMatrix indices, ComplexFloatMatrix v) {
483                return put(indices.findIndices(), v);
484        }
485
486        public ComplexFloatMatrix put(int r, ComplexFloatMatrix indices, ComplexFloatMatrix v) {
487                return put(r, indices.findIndices(), v);
488        }
489        
490        public ComplexFloatMatrix put(ComplexFloatMatrix indices, int c, ComplexFloatMatrix v) {
491                return put(indices.findIndices(), c, v);
492        }
493
494        public ComplexFloatMatrix put(ComplexFloatMatrix rindices, ComplexFloatMatrix cindices, ComplexFloatMatrix v) {
495                return put(rindices.findIndices(), cindices.findIndices(), v);
496        }
497
498        public ComplexFloatMatrix put(ComplexFloatMatrix indices, float v) {
499                return put(indices.findIndices(), v);
500        }
501
502        public ComplexFloatMatrix putReal(ComplexFloatMatrix indices, float v) {
503                return put(indices, v);
504        }
505
506        public ComplexFloatMatrix putImag(ComplexFloatMatrix indices, float v) {
507                return putImag(indices.findIndices(), v);
508        }
509
510        public ComplexFloatMatrix put(ComplexFloatMatrix indices, ComplexFloat v) {
511                return put(indices.findIndices(), v);
512        }
513        
514        public ComplexFloatMatrix put(int r, ComplexFloatMatrix indices, float v) {
515                return put(r, indices.findIndices(), v);
516        }
517        
518        public ComplexFloatMatrix putReal(int r, ComplexFloatMatrix indices, float v) {
519                return put(r, indices, v);
520        }
521
522        public ComplexFloatMatrix putImag(int r, ComplexFloatMatrix indices, float v) {
523                return putImag(r, indices.findIndices(), v);
524        }
525
526        public ComplexFloatMatrix put(int r, ComplexFloatMatrix indices, ComplexFloat v) {
527                return put(r, indices.findIndices(), v);
528        }
529
530        public ComplexFloatMatrix put(ComplexFloatMatrix indices, int c, float v) {
531                return put(indices.findIndices(), c, v);
532        }
533
534        public ComplexFloatMatrix putReal(ComplexFloatMatrix indices, int c, float v) {
535                return put(indices, c, v);
536        }
537
538        public ComplexFloatMatrix putImag(ComplexFloatMatrix indices, int c, float v) {
539                return putImag(indices.findIndices(), c, v);
540        }
541
542        public ComplexFloatMatrix put(ComplexFloatMatrix indices, int c, ComplexFloat v) {
543                return put(indices.findIndices(), c, v);
544        }
545
546        public ComplexFloatMatrix put(ComplexFloatMatrix rindices, ComplexFloatMatrix cindices, float v) {
547                return put(rindices.findIndices(), cindices.findIndices(), v);
548        }
549
550        public ComplexFloatMatrix putReal(ComplexFloatMatrix rindices, ComplexFloatMatrix cindices, float v) {
551                return putReal(rindices, cindices, v);
552        }
553
554        public ComplexFloatMatrix putImag(ComplexFloatMatrix rindices, ComplexFloatMatrix cindices, float v) {
555                return putImag(rindices.findIndices(), cindices.findIndices(), v);
556        }
557
558        public ComplexFloatMatrix put(ComplexFloatMatrix rindices, ComplexFloatMatrix cindices, ComplexFloat v) {
559                return put(rindices.findIndices(), cindices.findIndices(), v);
560        }
561
562        
563        public int[] findIndices() {
564                int len = 0;
565                for (int i = 0; i < length; i++)
566                        if (!get(i).isZero())
567                                len++;
568                
569                int[] indices = new int[len];
570                int c = 0;
571                
572                for (int i = 0; i < length; i++)
573                        if (!get(i).isZero())
574                                indices[c++] = i;
575                
576                return indices;
577        }
578        
579        /**************************************************************************
580         * Basic operations (copying, resizing, element access)
581         */
582        
583        /** Return transposed copy of this matrix */
584        public ComplexFloatMatrix transpose() {
585                ComplexFloatMatrix result = new ComplexFloatMatrix(columns, rows);
586
587                ComplexFloat c = new ComplexFloat(0);
588
589                for (int i = 0; i < rows; i++)
590                        for (int j = 0; j < columns; j++)
591                                result.put(j, i, get(i, j, c));
592                
593                return result;
594        }
595
596        public ComplexFloatMatrix hermitian() {
597            ComplexFloatMatrix result = new ComplexFloatMatrix(columns, rows);
598
599            ComplexFloat c = new ComplexFloat(0);
600
601            for (int i = 0; i < rows; i++)
602                for (int j = 0; j < columns; j++)
603                    result.put(j, i, get(i, j, c).conji());
604            return result;
605        }
606
607        /**
608         * Compute complex conjugate (in-place).
609         */
610        public ComplexFloatMatrix conji() {
611            ComplexFloat c = new ComplexFloat(0.0f);
612            for (int i = 0; i < length; i++)
613                put(i, get(i, c).conji());
614            return this;
615        }
616
617        /**
618         * Compute complex conjugate.
619         */
620        public ComplexFloatMatrix conj() {
621            return dup().conji();
622        }
623
624                
625        /** Compare two matrices.
626         * @param o Object to compare to
627         * @return true if and only if other is also a ComplexFloatMatrix which has the same size and the
628         * maximal absolute difference in matrix elements is smaller thatn 1e-6.  */
629        public boolean equals(Object o) {
630                if (!(o instanceof ComplexFloatMatrix))
631                        return false;
632
633                ComplexFloatMatrix other = (ComplexFloatMatrix) o;
634
635                if (!sameSize(other))
636                        return false;
637                
638                FloatMatrix diff = MatrixFunctions.absi(sub(other)).getReal();
639                
640                return diff.max() / (rows * columns) < 1e-6;
641        }
642
643        
644        /** Resize the matrix. All elements will be set to zero. */
645        public void resize(int newRows, int newColumns) {
646                rows = newRows;
647                columns = newColumns;
648                length = newRows * newColumns;
649                data = new float[2 * rows * columns];
650        }
651
652        
653        /** Reshape the matrix. Number of elements must not change. */
654        public ComplexFloatMatrix reshape(int newRows, int newColumns) {
655                if (length != newRows * newColumns)
656                        throw new IllegalArgumentException(
657                                        "Number of elements must not change.");
658
659                rows = newRows;
660                columns = newColumns;
661                
662                return this;
663        }
664
665        /** Checks whether two matrices have the same size. */
666        public boolean sameSize(ComplexFloatMatrix a) {
667                return rows == a.rows && columns == a.columns;
668        }
669
670        /** 
671         * Assert that two matrices have the same size.
672         * 
673         * @param a the other matrix
674         * @throws SizeException if matrix sizes don't match. 
675         * */
676        public void assertSameSize(ComplexFloatMatrix a) {
677                if (!sameSize(a))
678                        throw new SizeException("Matrices must have the same size.");
679        }
680        
681        /** 
682         * Check whether this can be multiplied with a. 
683         * 
684         * @param a right-hand-side of the multiplication.
685         * @return true iff <tt>this.columns == a.rows</tt>
686         */
687        public boolean multipliesWith(ComplexFloatMatrix a) {
688                return columns == a.rows;
689        }
690        
691        public void assertMultipliesWith(ComplexFloatMatrix a) {
692                if (!multipliesWith(a))
693                        throw new SizeException("Number of columns of left matrix must be equal to number of rows of right matrix.");
694        }
695        
696        public boolean sameLength(ComplexFloatMatrix a) {
697                return length == a.length;
698        }
699        
700        public void assertSameLength(ComplexFloatMatrix a) {
701                if (!sameLength(a))
702                        throw new SizeException("Matrices must have same length (is: " + length + " and " + a.length + ")");
703        }
704        
705        /** Copy ComplexFloatMatrix a to this. this a is resized if necessary. */
706        public ComplexFloatMatrix copy(ComplexFloatMatrix a) {
707                if (!sameSize(a))
708                        resize(a.rows, a.columns);
709                
710                SimpleBlas.copy(a, this);
711                return a;
712        }
713        
714        /** Returns a duplicate of this matrix. Geometry is the same (including offsets, transpose, etc.),
715         * but the buffer is not shared.
716         */
717        public ComplexFloatMatrix dup() {
718                ComplexFloatMatrix out = new ComplexFloatMatrix(rows, columns);
719
720                JavaBlas.rcopy(2*length, data, 0, 1, out.data, 0, 1);
721                
722                return out;
723        }
724        
725        public ComplexFloatMatrix swapColumns(int i, int j) {
726                NativeBlas.cswap(rows, data, index(0, i), 1, data, index(0, j), 1);
727                return this;
728        }
729        
730        public ComplexFloatMatrix swapRows(int i, int j) {
731                NativeBlas.cswap(columns, data, index(i, 0), rows, data, index(j, 0), rows);
732                return this;
733        }
734                
735        /** Set matrix element */
736        public ComplexFloatMatrix put(int rowIndex, int columnIndex, float value) {
737                data[2*index(rowIndex, columnIndex)] =  value;
738                return this;
739        }
740
741        public ComplexFloatMatrix put(int rowIndex, int columnIndex, float realValue, float complexValue) {
742                data[2*index(rowIndex, columnIndex)] =  realValue;
743                data[2*index(rowIndex, columnIndex)+1] =  complexValue;
744                return this;
745        }
746
747        public ComplexFloatMatrix put(int rowIndex, int columnIndex, ComplexFloat value) {
748                int i = 2*index(rowIndex, columnIndex);
749                data[i] = value.real(); data[i+1] = value.imag();
750                return this;
751        }
752
753        public ComplexFloatMatrix putReal(int rowIndex, int columnIndex, float value) {
754                data[2*index(rowIndex, columnIndex)] = value;
755                return this;
756        }
757
758        public ComplexFloatMatrix putImag(int rowIndex, int columnIndex, float value) {
759                data[2*index(rowIndex, columnIndex)+1] = value;
760                return this;
761        }
762        
763        /** Retrieve matrix element */
764        public ComplexFloat get(int rowIndex, int columnIndex) {
765            int i = 2*index(rowIndex, columnIndex);
766            return new ComplexFloat(data[i], data[i+1]);
767        }
768
769        /** Get matrix element, passing the variable to store the result. */
770        public ComplexFloat get(int rowIndex, int columnIndex, ComplexFloat result) {
771            return get(index(rowIndex, columnIndex), result);
772        }
773        
774        public FloatMatrix getReal() {
775                FloatMatrix result = new FloatMatrix(rows, columns);
776                
777                NativeBlas.scopy(length, data, 0, 2, result.data, 0, 1);
778                
779                return result;
780        }
781
782        /** Get index of an element */
783        public int index(int rowIndex, int columnIndex) {
784                //System.out.printf("Index for (%d, %d) -> %d\n", rowIndex, columnIndex, (rows * columnIndex + rowIndex) * 2);
785                return rows * columnIndex + rowIndex;
786        }
787
788        public ComplexFloat get(int i) {
789                return new ComplexFloat(data[i * 2], data[i * 2 + 1]);
790        }
791        
792        public ComplexFloat get(int i, ComplexFloat result) {
793            return result.set(data[i * 2], data[i*2+1]);
794        }
795        
796        public float getReal(int i) {
797                return data[2*i];
798        }
799        
800        public float getImag(int i) {
801                return data[2*i + 1]; 
802        }
803
804        public ComplexFloatMatrix put(int i, float v) {
805                data[2*i] = v;
806                return this;
807        }
808
809        public ComplexFloatMatrix put(int i, float r, float c) {
810            data[2*i] = r;
811            data[2*i+1] = c;
812            return this;
813        }
814        
815        public ComplexFloatMatrix put(int i, ComplexFloat v) {
816                data[2*i] = v.real();
817                data[2*i+1] = v.imag();
818                return this;
819        }
820        
821        public ComplexFloatMatrix putReal(int i, float v) {
822                return put(i, v);
823        }
824        
825        public ComplexFloatMatrix putImag(int i, float v) {
826                data[2*i+1] = v;
827                return this;
828        }
829
830        public int getRows() {
831                return rows;
832        }
833        
834        public int getColumns() {
835                return columns;
836        }
837        
838        public int getLength() {
839                return length;
840        }
841        
842        /** Checks whether the matrix is empty. */
843        public boolean isEmpty() {
844                return columns == 0 || rows == 0;
845        }
846        
847        /** Checks whether the matrix is square. */
848        public boolean isSquare() {
849                return columns == rows;
850        }
851        
852        public void assertSquare() {
853                if (!isSquare())
854                        throw new SizeException("Matrix must be square!");
855        }
856        
857        /** Checks whether the matrix is a vector. */
858        public boolean isVector() {
859                return columns == 1 || rows == 1;
860        }
861        
862        public boolean isRowVector() {
863                return columns == 1;
864        }
865        
866        public boolean isColumnVector() {
867                return rows == 1;
868        }
869                
870        /** Get diagonal of the matrix. */
871        public ComplexFloatMatrix diag() {
872                ComplexFloatMatrix d = new ComplexFloatMatrix(rows);
873                NativeBlas.ccopy(rows, data, 0, rows + 1, d.data, 0, 1);
874                return d;
875        }
876        
877        /** Get real part of the matrix. */
878        public FloatMatrix real() {
879            FloatMatrix result = new FloatMatrix(rows, columns);
880            NativeBlas.scopy(length, data, 0, 2, result.data, 0, 1);
881            return result;
882        }
883        
884        /** Get imaginary part of the matrix. */
885        public FloatMatrix imag() {
886            FloatMatrix result = new FloatMatrix(rows, columns);
887            NativeBlas.scopy(length, data, 1, 2, result.data, 0, 1);
888            return result;            
889        }
890
891        
892        /** 
893         * Pretty-print this matrix to <tt>System.out</tt>. 
894         * */
895        public void print() {
896                System.out.println(toString());
897        }
898
899        /** 
900         * Generate string representation of this matrix 
901         * (multi-line).
902         * */
903        public String toString() {
904                StringBuilder s = new StringBuilder();
905
906                s.append("[");
907                
908                for (int i = 0; i < rows; i++) {
909                        for (int j = 0; j < columns; j++) {
910                                s.append(get(i, j));
911                                if (j < columns - 1)
912                                        s.append(", ");
913                        }
914                        if (i < rows - 1)
915                                s.append("; ");
916                }
917
918                s.append("]");
919                
920                return s.toString();
921        }
922
923        public float[] toDoubleArray() {
924                float[] array = new float[2*length];
925                
926                for (int i = 0; i < 2*length; i++)
927                        array[i] = data[i];
928                
929                return array;
930        }
931        
932        public ComplexFloat[] toArray() {
933                ComplexFloat[] array = new ComplexFloat[length];
934                
935                for (int i = 0; i < length; i++)
936                        array[i] = get(i);
937                
938                return array;           
939        }
940        
941        public ComplexFloat[][] toArray2() {
942                ComplexFloat[][] array = new ComplexFloat[rows][columns];
943                
944                for (int r = 0; r < rows; r++)
945                        for (int c = 0; c < columns; c++)
946                                array[r][c] = get(r, c);
947                                
948                return array;
949        }
950        
951        public boolean[] toBooleanArray() {
952                boolean[] array = new boolean[length];
953                
954                for (int i = 0; i < length; i++)
955                        array[i] = get(i).isZero() ? false : true;
956                
957                return array;
958        }
959        
960        public boolean[][] toBooleanArray2() {
961                boolean[][] array = new boolean[rows][columns];
962                
963                for (int r = 0; r < rows; r++)
964                        for (int c = 0; c < columns; c++)
965                                array[r][c] = get(r, c).isZero() ? false : true;
966                                
967                return array;
968        }
969
970        /**************************************************************************
971         * Arithmetic Operations
972         */
973
974        /** 
975         * Ensures that the result vector has the same length as this. If not,
976         * resizing result is tried, which fails if result == this or result == other.
977         */
978        private void ensureResultLength(ComplexFloatMatrix other, ComplexFloatMatrix result) {
979                if (!sameLength(result)) {
980                        if (result == this || result == other)
981                                throw new SizeException("Cannot resize result matrix because it is used in-place.");
982                        result.resize(rows, columns);
983                }
984        }
985
986        /** Add two matrices. */
987        public ComplexFloatMatrix addi(ComplexFloatMatrix other, ComplexFloatMatrix result) {
988                if (other.isScalar())
989                        return addi(other.scalar(), result);
990                
991                assertSameLength(other);
992                ensureResultLength(other, result);
993                
994                if (result == this)
995                        SimpleBlas.axpy(ComplexFloat.UNIT, other, result);
996                else if (result == other)
997                        SimpleBlas.axpy(ComplexFloat.UNIT, this, result);
998                else {
999                        SimpleBlas.copy(this, result);
1000                        SimpleBlas.axpy(ComplexFloat.UNIT, other, result);
1001                }
1002
1003                return result;
1004        }
1005        
1006        /** Add a scalar to a matrix. */
1007        public ComplexFloatMatrix addi(ComplexFloat v, ComplexFloatMatrix result) {
1008                ensureResultLength(null, result);
1009                
1010                for (int i = 0; i < length; i++)
1011                        result.put(i, get(i).add(v));
1012                return result;
1013        }
1014        
1015        public ComplexFloatMatrix addi(float v, ComplexFloatMatrix result) {
1016                return addi(new ComplexFloat(v), result);
1017        }
1018
1019        /** Subtract two matrices. */
1020        public ComplexFloatMatrix subi(ComplexFloatMatrix other, ComplexFloatMatrix result) {
1021                if (other.isScalar())
1022                        return subi(other.scalar(), result);
1023                
1024                assertSameLength(other);
1025                ensureResultLength(other, result);
1026                
1027                if (result == this)
1028                        SimpleBlas.axpy(ComplexFloat.NEG_UNIT, other, result);
1029                else if (result == other) {
1030                        SimpleBlas.scal(ComplexFloat.NEG_UNIT, result);
1031                        SimpleBlas.axpy(ComplexFloat.UNIT, this, result);
1032                }
1033                else {
1034                        SimpleBlas.copy(this, result);
1035                        SimpleBlas.axpy(ComplexFloat.NEG_UNIT, other, result);
1036                }
1037                return result;
1038        }
1039        
1040        /** Subtract a scalar from a matrix */
1041        public ComplexFloatMatrix subi(ComplexFloat v, ComplexFloatMatrix result) {
1042                ensureResultLength(null, result);
1043                
1044                for (int i = 0; i < length; i++)
1045                        result.put(i, get(i).sub(v));
1046                return result;
1047        }
1048        
1049        public ComplexFloatMatrix subi(float v, ComplexFloatMatrix result) {
1050                return subi(new ComplexFloat(v), result);
1051        }
1052
1053        /** 
1054         * Subtract two matrices, but subtract first from second matrix, that is, 
1055         * compute <em>result = other - this</em>. 
1056         * */
1057        public ComplexFloatMatrix rsubi(ComplexFloatMatrix other, ComplexFloatMatrix result) {
1058                return other.subi(this, result);
1059        }
1060        
1061        /** Subtract a matrix from a scalar */
1062        public ComplexFloatMatrix rsubi(ComplexFloat a, ComplexFloatMatrix result) {
1063                ensureResultLength(null, result);
1064                
1065                for (int i = 0; i < length; i++)
1066                        result.put(i, a.sub(get(i)));
1067                return result;
1068        }
1069
1070        public ComplexFloatMatrix rsubi(float a, ComplexFloatMatrix result) {
1071                return rsubi(new ComplexFloat(a), result);
1072        }
1073
1074        /** (Elementwise) Multiplication */ 
1075        public ComplexFloatMatrix muli(ComplexFloatMatrix other, ComplexFloatMatrix result) {
1076                if (other.isScalar())
1077                        return muli(other.scalar(), result);
1078                
1079                assertSameLength(other);
1080                ensureResultLength(other, result);
1081                
1082                ComplexFloat c = new ComplexFloat(0.0f);
1083                ComplexFloat d = new ComplexFloat(0.0f);
1084                
1085                for (int i = 0; i < length; i++)
1086                        result.put(i, get(i, c).muli(other.get(i, d)));
1087                return result;
1088        }
1089        
1090        /** (Elementwise) Multiplication with a scalar */
1091        public ComplexFloatMatrix muli(ComplexFloat v, ComplexFloatMatrix result) {
1092                ensureResultLength(null, result);
1093                
1094                ComplexFloat c = new ComplexFloat(0.0f);
1095                
1096                for (int i = 0; i < length; i++)
1097                        result.put(i, get(i, c).muli(v));
1098                return result;
1099        }
1100
1101        public ComplexFloatMatrix muli(float v, ComplexFloatMatrix result) {
1102                return muli(new ComplexFloat(v), result);
1103        }
1104
1105        /** Matrix-Matrix Multiplication */
1106        public ComplexFloatMatrix mmuli(ComplexFloatMatrix other, ComplexFloatMatrix result) {
1107                if (other.isScalar())
1108                        return muli(other.scalar(), result);
1109
1110                /* check sizes and resize if necessary */
1111                assertMultipliesWith(other);
1112                if (result.rows != rows || result.columns != other.columns) {
1113                        if (result != this && result != other)
1114                                result.resize(rows, other.columns);
1115                        else
1116                                throw new SizeException("Cannot resize result matrix because it is used in-place.");
1117                }
1118                
1119                if (result == this || result == other) {
1120                        /* actually, blas cannot do multiplications in-place. Therefore, we will fake by
1121                         * allocating a temporary object on the side and copy the result later.
1122                         */
1123                        ComplexFloatMatrix temp = new ComplexFloatMatrix(result.rows, result.columns);
1124                        SimpleBlas.gemm(ComplexFloat.UNIT, this, other, ComplexFloat.ZERO, temp);
1125                        SimpleBlas.copy(temp, result);
1126                }
1127                else {
1128                        SimpleBlas.gemm(ComplexFloat.UNIT, this, other, ComplexFloat.ZERO, result);
1129                }               
1130                return result;
1131        }
1132        
1133        /** Matrix-Matrix Multiplication with a scalar (for symmetry, does the
1134         * same as muli(scalar)
1135         */
1136        public ComplexFloatMatrix mmuli(ComplexFloat v, ComplexFloatMatrix result) {
1137                return muli(v, result);
1138        }
1139
1140        public ComplexFloatMatrix mmuli(float v, ComplexFloatMatrix result) {
1141                return muli(v, result);
1142        }
1143        
1144        /** (Elementwise) division */
1145        public ComplexFloatMatrix divi(ComplexFloatMatrix other, ComplexFloatMatrix result) {
1146                if (other.isScalar())
1147                        return divi(other.scalar(), result);
1148                
1149                assertSameLength(other);
1150                ensureResultLength(other, result);
1151                
1152                ComplexFloat c1 = new ComplexFloat(0.0f);
1153                ComplexFloat c2 = new ComplexFloat(0.0f);
1154                
1155                for (int i = 0; i < length; i++)
1156                        result.put(i, get(i, c1).divi(other.get(i, c2)));
1157                return result;
1158        }
1159                
1160        /** (Elementwise) division with a scalar */
1161        public ComplexFloatMatrix divi(ComplexFloat a, ComplexFloatMatrix result) {
1162                ensureResultLength(null, result);
1163                
1164                ComplexFloat c = new ComplexFloat(0.0f);
1165                
1166                for (int i = 0; i < length; i++)
1167                        result.put(i, get(i, c).divi(a));
1168                return result;
1169        }       
1170
1171        public ComplexFloatMatrix divi(float a, ComplexFloatMatrix result) {
1172                return divi(new ComplexFloat(a), result);
1173        }
1174
1175        /** 
1176         * (Elementwise) division, with operands switched. Computes
1177         * <em>result = other / this</em>. */
1178        public ComplexFloatMatrix rdivi(ComplexFloatMatrix other, ComplexFloatMatrix result) {
1179                if (other.isScalar())
1180                        return divi(other.scalar(), result);
1181                
1182                assertSameLength(other);
1183                ensureResultLength(other, result);
1184
1185                ComplexFloat c1 = new ComplexFloat(0.0f);
1186                ComplexFloat c2 = new ComplexFloat(0.0f);
1187
1188                for (int i = 0; i < length; i++)
1189                        result.put(i, other.get(i, c1).divi(get(i, c2)));
1190                return result;
1191        }
1192                
1193        /** (Elementwise) division with a scalar, with operands switched. Computes
1194         * <em>result = a / this</em>.*/
1195        public ComplexFloatMatrix rdivi(ComplexFloat a, ComplexFloatMatrix result) {
1196                ensureResultLength(null, result);
1197
1198                ComplexFloat c1 = new ComplexFloat(0.0f);
1199                ComplexFloat c2 = new ComplexFloat(0.0f);
1200
1201                for (int i = 0; i < length; i++) {
1202                    c1.copy(a);
1203                    result.put(i, c1.divi(get(i, c2)));                    
1204                }
1205                return result;
1206        }
1207
1208        public ComplexFloatMatrix rdivi(float a, ComplexFloatMatrix result) {
1209                return rdivi(new ComplexFloat(a), result);
1210        }
1211        
1212        public ComplexFloatMatrix negi() {
1213                ComplexFloat c = new ComplexFloat(0.0f);
1214                for (int i = 0; i < length; i++)
1215                        put(i, get(i, c).negi());
1216                return this;
1217        }
1218        
1219        public ComplexFloatMatrix neg() {
1220                return dup().negi();
1221        }
1222
1223        public ComplexFloatMatrix noti() {
1224                ComplexFloat c = new ComplexFloat(0.0f);
1225                for (int i = 0; i < length; i++)
1226                        put(i, get(i, c).isZero() ? 1.0f : 0.0f);
1227                return this;
1228        }
1229        
1230        public ComplexFloatMatrix not() {
1231                return dup().noti();
1232        }
1233        
1234        public ComplexFloatMatrix truthi() {
1235                ComplexFloat c = new ComplexFloat(0.0f);
1236                for (int i = 0; i < length; i++)
1237                        put(i, get(i, c).isZero() ? 0.0f : 1.0f);
1238                return this;
1239        }
1240        
1241        public ComplexFloatMatrix truth() {
1242                return dup().truthi();
1243        }
1244
1245        /****************************************************************
1246         * Rank one-updates
1247         */
1248        
1249        /** Computes a rank-1-update A = A + alpha * x * y'. */ 
1250        public ComplexFloatMatrix rankOneUpdate(ComplexFloat alpha, ComplexFloatMatrix x, ComplexFloatMatrix y) {
1251                if (rows != x.length)
1252                        throw new SizeException("Vector x has wrong length (" + x.length + " != " + rows + ").");
1253                if (columns != y.length)
1254                        throw new SizeException("Vector y has wrong length (" + x.length + " != " + columns + ").");                    
1255                
1256                SimpleBlas.gerc(alpha, x, y, this);
1257                return this;
1258        }
1259
1260        public ComplexFloatMatrix rankOneUpdate(float alpha, ComplexFloatMatrix x, ComplexFloatMatrix y) {
1261                return rankOneUpdate(new ComplexFloat(alpha), x, y);
1262        }
1263
1264        /** Computes a rank-1-update A = A + alpha * x * x'. */ 
1265        public ComplexFloatMatrix rankOneUpdate(float alpha, ComplexFloatMatrix x) {
1266                return rankOneUpdate(new ComplexFloat(alpha), x, x);
1267        }
1268
1269        /** Computes a rank-1-update A = A + alpha * x * x'. */ 
1270        public ComplexFloatMatrix rankOneUpdate(ComplexFloat alpha, ComplexFloatMatrix x) {
1271                return rankOneUpdate(alpha, x, x);
1272        }
1273
1274        /** Computes a rank-1-update A = A + x * x'. */ 
1275        public ComplexFloatMatrix rankOneUpdate(ComplexFloatMatrix x) {
1276                return rankOneUpdate(1.0f, x, x);
1277        }
1278
1279        /** Computes a rank-1-update A = A + x * y'. */ 
1280        public ComplexFloatMatrix rankOneUpdate(ComplexFloatMatrix x, ComplexFloatMatrix y) {
1281                return rankOneUpdate(1.0f, x, y);
1282        }
1283
1284        /****************************************************************
1285         * Logical operations
1286         */
1287        
1288        public ComplexFloat sum() {
1289                ComplexFloat s = new ComplexFloat(0.0f);
1290                ComplexFloat c = new ComplexFloat(0.0f);
1291                for (int i = 0; i < length; i++)
1292                        s.addi(get(i, c));
1293                return s;
1294        }
1295        
1296        public ComplexFloat mean() {
1297                return sum().div((float)length);
1298        }
1299        
1300        /** Computes this^T * other */
1301        public ComplexFloat dotc(ComplexFloatMatrix other) {
1302                return SimpleBlas.dotc(this, other);
1303        }
1304        
1305        /** Computes this^H * other */
1306        public ComplexFloat dotu(ComplexFloatMatrix other) {
1307                return SimpleBlas.dotu(this, other);
1308        }
1309
1310        public float norm2() {
1311                return SimpleBlas.nrm2(this);
1312        }
1313        
1314        public float normmax() {
1315                int i = SimpleBlas.iamax(this);
1316                return get(i).abs();
1317        }
1318
1319        public float norm1() {
1320                return SimpleBlas.asum(this);
1321        }
1322                
1323        /** Return a vector containing the sums of the columns (having number of columns many entries) */
1324        public ComplexFloatMatrix columnSums() {
1325                ComplexFloatMatrix v =
1326                        new ComplexFloatMatrix(1, columns);
1327
1328                for (int c = 0; c < columns; c++)
1329                        v.put(c, getColumn(c).sum());
1330
1331                return v;
1332        }
1333
1334        public ComplexFloatMatrix columnMeans() {
1335                return columnSums().divi(rows);
1336        }
1337        
1338        public ComplexFloatMatrix rowSums() {
1339                ComplexFloatMatrix v = new ComplexFloatMatrix(rows);
1340
1341                for (int r = 0; r < rows; r++)
1342                        v.put(r, getRow(r).sum());
1343
1344                return v;
1345        }
1346
1347        public ComplexFloatMatrix rowMeans() {
1348                return rowSums().divi(columns);
1349        }
1350
1351        public ComplexFloatMatrix getColumn(int c) {
1352                ComplexFloatMatrix result = new ComplexFloatMatrix(rows, 1);
1353                NativeBlas.ccopy(rows, data, index(0, c), 1, result.data, 0, 1);
1354                return result;
1355        }
1356        
1357        public void putColumn(int c, ComplexFloatMatrix v) {
1358                NativeBlas.ccopy(rows, v.data, 0, 1, data, index(0, c), 1);
1359        }
1360
1361        public ComplexFloatMatrix getRow(int r) {
1362                ComplexFloatMatrix result = new ComplexFloatMatrix(1, columns);
1363                NativeBlas.ccopy(columns, data, index(r, 0), rows, result.data, 0, 1);
1364                return result;
1365        }
1366        
1367        public void putRow(int r, ComplexFloatMatrix v) {
1368                NativeBlas.ccopy(columns, v.data, 0, 1, data, index(r, 0), rows);
1369        }
1370
1371        /**************************************************************************
1372         * Elementwise Functions
1373         */
1374
1375        /** Add a row vector to all rows of the matrix */
1376        public void addRowVector(ComplexFloatMatrix x) {
1377                for (int r = 0; r < rows; r++) {
1378                        NativeBlas.caxpy(columns, ComplexFloat.UNIT, x.data, 0, 1, data, index(r, 0), rows);
1379                }
1380        }
1381
1382        /** Add a vector to all columns of the matrix */
1383        public void addColumnVector(ComplexFloatMatrix x) {
1384                for (int c = 0; c < columns; c++) {
1385                        NativeBlas.caxpy(rows, ComplexFloat.UNIT, x.data, 0, 1, data, index(0, c), 1);
1386                }
1387        }
1388
1389        /** Add a row vector to all rows of the matrix */
1390        public void subRowVector(ComplexFloatMatrix x) {
1391                for (int r = 0; r < rows; r++) {
1392                        NativeBlas.caxpy(columns, ComplexFloat.NEG_UNIT, x.data, 0, 1, data, index(r, 0), rows);
1393                }
1394        }
1395
1396        /** Add a vector to all columns of the matrix */
1397        public void subColumnVector(ComplexFloatMatrix x) {
1398                for (int c = 0; c < columns; c++) {
1399                        NativeBlas.caxpy(rows, ComplexFloat.NEG_UNIT, x.data, 0, 1, data, index(0, c), 1);
1400                }
1401        }
1402
1403        /**
1404         * Writes out this matrix to the given data stream.
1405         * @param dos the data output stream to write to.
1406         * @throws IOException 
1407         */
1408        public void out(DataOutputStream dos) throws IOException {
1409                dos.writeUTF("float");
1410                dos.writeInt(columns);
1411                dos.writeInt(rows);
1412                
1413                dos.writeInt(data.length);
1414                for(int i=0; i < data.length;i++)
1415                        dos.writeDouble(data[i]);
1416        }
1417        
1418        /**
1419         * Reads in a matrix from the given data stream. Note
1420         * that the old data of this matrix will be discarded.
1421         * @param dis the data input stream to read from.
1422         * @throws IOException 
1423         */
1424        public void in(DataInputStream dis) throws IOException {
1425                if(!dis.readUTF().equals("float")) 
1426                        throw new IllegalStateException("The matrix in the specified file is not of the correct type!");
1427                
1428                this.columns    = dis.readInt();
1429                this.rows               = dis.readInt();
1430
1431                final int MAX = dis.readInt();
1432                data = new float[MAX];
1433                for(int i=0; i < MAX;i++)
1434                        data[i] = dis.readFloat();
1435        }       
1436        
1437        /**
1438         * Saves this matrix to the specified file.
1439         * @param filename the file to write the matrix in.
1440         * @throws IOException thrown on errors while writing the matrix to the file
1441         */
1442        public void save(String filename) throws IOException {
1443                DataOutputStream dos = new DataOutputStream(new FileOutputStream(filename, false));
1444                this.out(dos);
1445        }
1446        
1447        /**
1448         * Loads a matrix from a file into this matrix. Note that the old data
1449         * of this matrix will be discarded.
1450         * @param filename the file to read the matrix from
1451         * @throws IOException thrown on errors while reading the matrix
1452         */
1453        public void load(String filename) throws IOException {
1454                DataInputStream dis = new DataInputStream(new FileInputStream(filename));
1455                this.in(dis);
1456        }
1457
1458        /****************************************************************
1459         * Autogenerated code
1460         */
1461        
1462        /***** Code for operators ***************************************/ 
1463
1464        /* Overloads for the usual arithmetic operations */
1465        /*#
1466         def gen_overloads(base, result_rows, result_cols); <<-EOS
1467        public ComplexFloatMatrix #{base}i(ComplexFloatMatrix other) {
1468                return #{base}i(other, this);
1469        }
1470                
1471        public ComplexFloatMatrix #{base}(ComplexFloatMatrix other) {
1472                return #{base}i(other, new ComplexFloatMatrix(#{result_rows}, #{result_cols}));
1473        }
1474
1475        public ComplexFloatMatrix #{base}i(ComplexFloat v) {
1476                return #{base}i(v, this);
1477        }
1478        
1479        public ComplexFloatMatrix #{base}i(float v) {
1480                return #{base}i(new ComplexFloat(v), this);
1481        }
1482
1483        public ComplexFloatMatrix #{base}(ComplexFloat v) {
1484                return #{base}i(v, new ComplexFloatMatrix(rows, columns));
1485        }       
1486
1487        public ComplexFloatMatrix #{base}(float v) {
1488                return #{base}i(new ComplexFloat(v), new ComplexFloatMatrix(rows, columns));
1489        }       
1490                
1491                EOS
1492          end
1493        #*/
1494
1495        /* Generating code for logical operators. This not only generates the stubs 
1496         * but really all of the code.
1497         */
1498        
1499        /*#
1500         def gen_compare(name, op); <<-EOS
1501         public ComplexFloatMatrix #{name}i(ComplexFloatMatrix other, ComplexFloatMatrix result) {
1502            if (other.isScalar())
1503               return #{name}i(other.scalar(), result);
1504               
1505                assertSameLength(other);
1506                ensureResultLength(other, result);
1507                
1508                ComplexFloat c1 = new ComplexFloat(0.0f);
1509                ComplexFloat c2 = new ComplexFloat(0.0f);
1510          
1511                for (int i = 0; i < length; i++)
1512                    result.put(i, get(i, c1).#{op}(other.get(i, c2)) ? 1.0f : 0.0f);
1513           return result;
1514         }
1515         
1516         public ComplexFloatMatrix #{name}i(ComplexFloatMatrix other) {
1517           return #{name}i(other, this);
1518         }
1519         
1520         public ComplexFloatMatrix #{name}(ComplexFloatMatrix other) {
1521           return #{name}i(other, new ComplexFloatMatrix(rows, columns));
1522         }
1523         
1524         public ComplexFloatMatrix #{name}i(ComplexFloat value, ComplexFloatMatrix result) {
1525           ensureResultLength(null, result);
1526           ComplexFloat c = new ComplexFloat(0.0f);
1527           for (int i = 0; i < length; i++)
1528             result.put(i, get(i, c).#{op}(value) ? 1.0f : 0.0f);
1529           return result;
1530         }
1531
1532         public ComplexFloatMatrix #{name}i(float value, ComplexFloatMatrix result) {
1533           return #{name}i(new ComplexFloat(value), result);
1534         }
1535
1536         public ComplexFloatMatrix #{name}i(ComplexFloat value) {
1537           return #{name}i(value, this);
1538         }
1539         
1540         public ComplexFloatMatrix #{name}i(float value) {
1541           return #{name}i(new ComplexFloat(value));
1542         }
1543         
1544         public ComplexFloatMatrix #{name}(ComplexFloat value) {
1545           return #{name}i(value, new ComplexFloatMatrix(rows, columns));
1546         }
1547         
1548         public ComplexFloatMatrix #{name}(float value) {
1549           return #{name}i(new ComplexFloat(value));
1550         }
1551
1552         EOS
1553         end
1554         #*/
1555        
1556        /*#
1557         def gen_logical(name, op); <<-EOS
1558         public ComplexFloatMatrix #{name}i(ComplexFloatMatrix other, ComplexFloatMatrix result) {
1559                assertSameLength(other);
1560                ensureResultLength(other, result);
1561                
1562                ComplexFloat t1 = new ComplexFloat(0.0f);
1563                ComplexFloat t2 = new ComplexFloat(0.0f);
1564         
1565               for (int i = 0; i < length; i++)
1566                  result.put(i, (!get(i, t1).isZero()) #{op} (!other.get(i, t2).isZero()) ? 1.0f : 0.0f);
1567           return result;
1568         }
1569         
1570         public ComplexFloatMatrix #{name}i(ComplexFloatMatrix other) {
1571           return #{name}i(other, this);
1572         }
1573         
1574         public ComplexFloatMatrix #{name}(ComplexFloatMatrix other) {
1575           return #{name}i(other, new ComplexFloatMatrix(rows, columns));
1576         }
1577         
1578         public ComplexFloatMatrix #{name}i(ComplexFloat value, ComplexFloatMatrix result) {
1579                ensureResultLength(null, result);
1580                boolean val = !value.isZero();
1581                ComplexFloat t = new ComplexFloat(0.0f);
1582                for (int i = 0; i < length; i++)
1583                     result.put(i, !get(i, t).isZero() #{op} val ? 1.0f : 0.0f);
1584           return result;
1585         }
1586
1587         public ComplexFloatMatrix #{name}i(float value, ComplexFloatMatrix result) {
1588           return #{name}i(new ComplexFloat(value), result);
1589         }
1590
1591         public ComplexFloatMatrix #{name}i(ComplexFloat value) {
1592           return #{name}i(value, this);
1593         }
1594
1595         public ComplexFloatMatrix #{name}i(float value) {
1596           return #{name}i(new ComplexFloat(value), this);
1597         }
1598
1599         public ComplexFloatMatrix #{name}(ComplexFloat value) {
1600           return #{name}i(value, new ComplexFloatMatrix(rows, columns));
1601         }
1602         
1603         public ComplexFloatMatrix #{name}(float value) {
1604           return #{name}i(new ComplexFloat(value));
1605         }
1606         EOS
1607         end
1608         #*/
1609
1610        /*# collect(gen_overloads('add', 'rows', 'columns'),
1611          gen_overloads('sub', 'rows', 'columns'),
1612          gen_overloads('rsub', 'rows', 'columns'),
1613          gen_overloads('div', 'rows', 'columns'),
1614          gen_overloads('rdiv', 'rows', 'columns'),
1615          gen_overloads('mul', 'rows', 'columns'),
1616          gen_overloads('mmul', 'rows', 'other.columns'),
1617          gen_compare('eq', 'eq'),
1618          gen_compare('ne', 'eq'),
1619          gen_logical('and', '&'),
1620          gen_logical('or', '|'),
1621          gen_logical('xor', '^'))
1622         #*/
1623//RJPP-BEGIN------------------------------------------------------------
1624        public ComplexFloatMatrix addi(ComplexFloatMatrix other) {
1625                return addi(other, this);
1626        }
1627                
1628        public ComplexFloatMatrix add(ComplexFloatMatrix other) {
1629                return addi(other, new ComplexFloatMatrix(rows, columns));
1630        }
1631
1632        public ComplexFloatMatrix addi(ComplexFloat v) {
1633                return addi(v, this);
1634        }
1635        
1636        public ComplexFloatMatrix addi(float v) {
1637                return addi(new ComplexFloat(v), this);
1638        }
1639
1640        public ComplexFloatMatrix add(ComplexFloat v) {
1641                return addi(v, new ComplexFloatMatrix(rows, columns));
1642        }       
1643
1644        public ComplexFloatMatrix add(float v) {
1645                return addi(new ComplexFloat(v), new ComplexFloatMatrix(rows, columns));
1646        }       
1647                
1648
1649        public ComplexFloatMatrix subi(ComplexFloatMatrix other) {
1650                return subi(other, this);
1651        }
1652                
1653        public ComplexFloatMatrix sub(ComplexFloatMatrix other) {
1654                return subi(other, new ComplexFloatMatrix(rows, columns));
1655        }
1656
1657        public ComplexFloatMatrix subi(ComplexFloat v) {
1658                return subi(v, this);
1659        }
1660        
1661        public ComplexFloatMatrix subi(float v) {
1662                return subi(new ComplexFloat(v), this);
1663        }
1664
1665        public ComplexFloatMatrix sub(ComplexFloat v) {
1666                return subi(v, new ComplexFloatMatrix(rows, columns));
1667        }       
1668
1669        public ComplexFloatMatrix sub(float v) {
1670                return subi(new ComplexFloat(v), new ComplexFloatMatrix(rows, columns));
1671        }       
1672                
1673
1674        public ComplexFloatMatrix rsubi(ComplexFloatMatrix other) {
1675                return rsubi(other, this);
1676        }
1677                
1678        public ComplexFloatMatrix rsub(ComplexFloatMatrix other) {
1679                return rsubi(other, new ComplexFloatMatrix(rows, columns));
1680        }
1681
1682        public ComplexFloatMatrix rsubi(ComplexFloat v) {
1683                return rsubi(v, this);
1684        }
1685        
1686        public ComplexFloatMatrix rsubi(float v) {
1687                return rsubi(new ComplexFloat(v), this);
1688        }
1689
1690        public ComplexFloatMatrix rsub(ComplexFloat v) {
1691                return rsubi(v, new ComplexFloatMatrix(rows, columns));
1692        }       
1693
1694        public ComplexFloatMatrix rsub(float v) {
1695                return rsubi(new ComplexFloat(v), new ComplexFloatMatrix(rows, columns));
1696        }       
1697                
1698
1699        public ComplexFloatMatrix divi(ComplexFloatMatrix other) {
1700                return divi(other, this);
1701        }
1702                
1703        public ComplexFloatMatrix div(ComplexFloatMatrix other) {
1704                return divi(other, new ComplexFloatMatrix(rows, columns));
1705        }
1706
1707        public ComplexFloatMatrix divi(ComplexFloat v) {
1708                return divi(v, this);
1709        }
1710        
1711        public ComplexFloatMatrix divi(float v) {
1712                return divi(new ComplexFloat(v), this);
1713        }
1714
1715        public ComplexFloatMatrix div(ComplexFloat v) {
1716                return divi(v, new ComplexFloatMatrix(rows, columns));
1717        }       
1718
1719        public ComplexFloatMatrix div(float v) {
1720                return divi(new ComplexFloat(v), new ComplexFloatMatrix(rows, columns));
1721        }       
1722                
1723
1724        public ComplexFloatMatrix rdivi(ComplexFloatMatrix other) {
1725                return rdivi(other, this);
1726        }
1727                
1728        public ComplexFloatMatrix rdiv(ComplexFloatMatrix other) {
1729                return rdivi(other, new ComplexFloatMatrix(rows, columns));
1730        }
1731
1732        public ComplexFloatMatrix rdivi(ComplexFloat v) {
1733                return rdivi(v, this);
1734        }
1735        
1736        public ComplexFloatMatrix rdivi(float v) {
1737                return rdivi(new ComplexFloat(v), this);
1738        }
1739
1740        public ComplexFloatMatrix rdiv(ComplexFloat v) {
1741                return rdivi(v, new ComplexFloatMatrix(rows, columns));
1742        }       
1743
1744        public ComplexFloatMatrix rdiv(float v) {
1745                return rdivi(new ComplexFloat(v), new ComplexFloatMatrix(rows, columns));
1746        }       
1747                
1748
1749        public ComplexFloatMatrix muli(ComplexFloatMatrix other) {
1750                return muli(other, this);
1751        }
1752                
1753        public ComplexFloatMatrix mul(ComplexFloatMatrix other) {
1754                return muli(other, new ComplexFloatMatrix(rows, columns));
1755        }
1756
1757        public ComplexFloatMatrix muli(ComplexFloat v) {
1758                return muli(v, this);
1759        }
1760        
1761        public ComplexFloatMatrix muli(float v) {
1762                return muli(new ComplexFloat(v), this);
1763        }
1764
1765        public ComplexFloatMatrix mul(ComplexFloat v) {
1766                return muli(v, new ComplexFloatMatrix(rows, columns));
1767        }       
1768
1769        public ComplexFloatMatrix mul(float v) {
1770                return muli(new ComplexFloat(v), new ComplexFloatMatrix(rows, columns));
1771        }       
1772                
1773
1774        public ComplexFloatMatrix mmuli(ComplexFloatMatrix other) {
1775                return mmuli(other, this);
1776        }
1777                
1778        public ComplexFloatMatrix mmul(ComplexFloatMatrix other) {
1779                return mmuli(other, new ComplexFloatMatrix(rows, other.columns));
1780        }
1781
1782        public ComplexFloatMatrix mmuli(ComplexFloat v) {
1783                return mmuli(v, this);
1784        }
1785        
1786        public ComplexFloatMatrix mmuli(float v) {
1787                return mmuli(new ComplexFloat(v), this);
1788        }
1789
1790        public ComplexFloatMatrix mmul(ComplexFloat v) {
1791                return mmuli(v, new ComplexFloatMatrix(rows, columns));
1792        }       
1793
1794        public ComplexFloatMatrix mmul(float v) {
1795                return mmuli(new ComplexFloat(v), new ComplexFloatMatrix(rows, columns));
1796        }       
1797                
1798
1799         public ComplexFloatMatrix eqi(ComplexFloatMatrix other, ComplexFloatMatrix result) {
1800            if (other.isScalar())
1801               return eqi(other.scalar(), result);
1802               
1803                assertSameLength(other);
1804                ensureResultLength(other, result);
1805                
1806                ComplexFloat c1 = new ComplexFloat(0.0f);
1807                ComplexFloat c2 = new ComplexFloat(0.0f);
1808          
1809                for (int i = 0; i < length; i++)
1810                    result.put(i, get(i, c1).eq(other.get(i, c2)) ? 1.0f : 0.0f);
1811           return result;
1812         }
1813         
1814         public ComplexFloatMatrix eqi(ComplexFloatMatrix other) {
1815           return eqi(other, this);
1816         }
1817         
1818         public ComplexFloatMatrix eq(ComplexFloatMatrix other) {
1819           return eqi(other, new ComplexFloatMatrix(rows, columns));
1820         }
1821         
1822         public ComplexFloatMatrix eqi(ComplexFloat value, ComplexFloatMatrix result) {
1823           ensureResultLength(null, result);
1824           ComplexFloat c = new ComplexFloat(0.0f);
1825           for (int i = 0; i < length; i++)
1826             result.put(i, get(i, c).eq(value) ? 1.0f : 0.0f);
1827           return result;
1828         }
1829
1830         public ComplexFloatMatrix eqi(float value, ComplexFloatMatrix result) {
1831           return eqi(new ComplexFloat(value), result);
1832         }
1833
1834         public ComplexFloatMatrix eqi(ComplexFloat value) {
1835           return eqi(value, this);
1836         }
1837         
1838         public ComplexFloatMatrix eqi(float value) {
1839           return eqi(new ComplexFloat(value));
1840         }
1841         
1842         public ComplexFloatMatrix eq(ComplexFloat value) {
1843           return eqi(value, new ComplexFloatMatrix(rows, columns));
1844         }
1845         
1846         public ComplexFloatMatrix eq(float value) {
1847           return eqi(new ComplexFloat(value));
1848         }
1849
1850
1851         public ComplexFloatMatrix nei(ComplexFloatMatrix other, ComplexFloatMatrix result) {
1852            if (other.isScalar())
1853               return nei(other.scalar(), result);
1854               
1855                assertSameLength(other);
1856                ensureResultLength(other, result);
1857                
1858                ComplexFloat c1 = new ComplexFloat(0.0f);
1859                ComplexFloat c2 = new ComplexFloat(0.0f);
1860          
1861                for (int i = 0; i < length; i++)
1862                    result.put(i, get(i, c1).eq(other.get(i, c2)) ? 1.0f : 0.0f);
1863           return result;
1864         }
1865         
1866         public ComplexFloatMatrix nei(ComplexFloatMatrix other) {
1867           return nei(other, this);
1868         }
1869         
1870         public ComplexFloatMatrix ne(ComplexFloatMatrix other) {
1871           return nei(other, new ComplexFloatMatrix(rows, columns));
1872         }
1873         
1874         public ComplexFloatMatrix nei(ComplexFloat value, ComplexFloatMatrix result) {
1875           ensureResultLength(null, result);
1876           ComplexFloat c = new ComplexFloat(0.0f);
1877           for (int i = 0; i < length; i++)
1878             result.put(i, get(i, c).eq(value) ? 1.0f : 0.0f);
1879           return result;
1880         }
1881
1882         public ComplexFloatMatrix nei(float value, ComplexFloatMatrix result) {
1883           return nei(new ComplexFloat(value), result);
1884         }
1885
1886         public ComplexFloatMatrix nei(ComplexFloat value) {
1887           return nei(value, this);
1888         }
1889         
1890         public ComplexFloatMatrix nei(float value) {
1891           return nei(new ComplexFloat(value));
1892         }
1893         
1894         public ComplexFloatMatrix ne(ComplexFloat value) {
1895           return nei(value, new ComplexFloatMatrix(rows, columns));
1896         }
1897         
1898         public ComplexFloatMatrix ne(float value) {
1899           return nei(new ComplexFloat(value));
1900         }
1901
1902
1903         public ComplexFloatMatrix andi(ComplexFloatMatrix other, ComplexFloatMatrix result) {
1904                assertSameLength(other);
1905                ensureResultLength(other, result);
1906                
1907                ComplexFloat t1 = new ComplexFloat(0.0f);
1908                ComplexFloat t2 = new ComplexFloat(0.0f);
1909         
1910               for (int i = 0; i < length; i++)
1911                  result.put(i, (!get(i, t1).isZero()) & (!other.get(i, t2).isZero()) ? 1.0f : 0.0f);
1912           return result;
1913         }
1914         
1915         public ComplexFloatMatrix andi(ComplexFloatMatrix other) {
1916           return andi(other, this);
1917         }
1918         
1919         public ComplexFloatMatrix and(ComplexFloatMatrix other) {
1920           return andi(other, new ComplexFloatMatrix(rows, columns));
1921         }
1922         
1923         public ComplexFloatMatrix andi(ComplexFloat value, ComplexFloatMatrix result) {
1924                ensureResultLength(null, result);
1925                boolean val = !value.isZero();
1926                ComplexFloat t = new ComplexFloat(0.0f);
1927                for (int i = 0; i < length; i++)
1928                     result.put(i, !get(i, t).isZero() & val ? 1.0f : 0.0f);
1929           return result;
1930         }
1931
1932         public ComplexFloatMatrix andi(float value, ComplexFloatMatrix result) {
1933           return andi(new ComplexFloat(value), result);
1934         }
1935
1936         public ComplexFloatMatrix andi(ComplexFloat value) {
1937           return andi(value, this);
1938         }
1939
1940         public ComplexFloatMatrix andi(float value) {
1941           return andi(new ComplexFloat(value), this);
1942         }
1943
1944         public ComplexFloatMatrix and(ComplexFloat value) {
1945           return andi(value, new ComplexFloatMatrix(rows, columns));
1946         }
1947         
1948         public ComplexFloatMatrix and(float value) {
1949           return andi(new ComplexFloat(value));
1950         }
1951
1952         public ComplexFloatMatrix ori(ComplexFloatMatrix other, ComplexFloatMatrix result) {
1953                assertSameLength(other);
1954                ensureResultLength(other, result);
1955                
1956                ComplexFloat t1 = new ComplexFloat(0.0f);
1957                ComplexFloat t2 = new ComplexFloat(0.0f);
1958         
1959               for (int i = 0; i < length; i++)
1960                  result.put(i, (!get(i, t1).isZero()) | (!other.get(i, t2).isZero()) ? 1.0f : 0.0f);
1961           return result;
1962         }
1963         
1964         public ComplexFloatMatrix ori(ComplexFloatMatrix other) {
1965           return ori(other, this);
1966         }
1967         
1968         public ComplexFloatMatrix or(ComplexFloatMatrix other) {
1969           return ori(other, new ComplexFloatMatrix(rows, columns));
1970         }
1971         
1972         public ComplexFloatMatrix ori(ComplexFloat value, ComplexFloatMatrix result) {
1973                ensureResultLength(null, result);
1974                boolean val = !value.isZero();
1975                ComplexFloat t = new ComplexFloat(0.0f);
1976                for (int i = 0; i < length; i++)
1977                     result.put(i, !get(i, t).isZero() | val ? 1.0f : 0.0f);
1978           return result;
1979         }
1980
1981         public ComplexFloatMatrix ori(float value, ComplexFloatMatrix result) {
1982           return ori(new ComplexFloat(value), result);
1983         }
1984
1985         public ComplexFloatMatrix ori(ComplexFloat value) {
1986           return ori(value, this);
1987         }
1988
1989         public ComplexFloatMatrix ori(float value) {
1990           return ori(new ComplexFloat(value), this);
1991         }
1992
1993         public ComplexFloatMatrix or(ComplexFloat value) {
1994           return ori(value, new ComplexFloatMatrix(rows, columns));
1995         }
1996         
1997         public ComplexFloatMatrix or(float value) {
1998           return ori(new ComplexFloat(value));
1999         }
2000
2001         public ComplexFloatMatrix xori(ComplexFloatMatrix other, ComplexFloatMatrix result) {
2002                assertSameLength(other);
2003                ensureResultLength(other, result);
2004                
2005                ComplexFloat t1 = new ComplexFloat(0.0f);
2006                ComplexFloat t2 = new ComplexFloat(0.0f);
2007         
2008               for (int i = 0; i < length; i++)
2009                  result.put(i, (!get(i, t1).isZero()) ^ (!other.get(i, t2).isZero()) ? 1.0f : 0.0f);
2010           return result;
2011         }
2012         
2013         public ComplexFloatMatrix xori(ComplexFloatMatrix other) {
2014           return xori(other, this);
2015         }
2016         
2017         public ComplexFloatMatrix xor(ComplexFloatMatrix other) {
2018           return xori(other, new ComplexFloatMatrix(rows, columns));
2019         }
2020         
2021         public ComplexFloatMatrix xori(ComplexFloat value, ComplexFloatMatrix result) {
2022                ensureResultLength(null, result);
2023                boolean val = !value.isZero();
2024                ComplexFloat t = new ComplexFloat(0.0f);
2025                for (int i = 0; i < length; i++)
2026                     result.put(i, !get(i, t).isZero() ^ val ? 1.0f : 0.0f);
2027           return result;
2028         }
2029
2030         public ComplexFloatMatrix xori(float value, ComplexFloatMatrix result) {
2031           return xori(new ComplexFloat(value), result);
2032         }
2033
2034         public ComplexFloatMatrix xori(ComplexFloat value) {
2035           return xori(value, this);
2036         }
2037
2038         public ComplexFloatMatrix xori(float value) {
2039           return xori(new ComplexFloat(value), this);
2040         }
2041
2042         public ComplexFloatMatrix xor(ComplexFloat value) {
2043           return xori(value, new ComplexFloatMatrix(rows, columns));
2044         }
2045         
2046         public ComplexFloatMatrix xor(float value) {
2047           return xori(new ComplexFloat(value));
2048         }
2049//RJPP-END--------------------------------------------------------------
2050}