001    // --- BEGIN LICENSE BLOCK ---
002    /* 
003     * Copyright (c) 2009, Mikio L. Braun
004     * Copyright (c) 2008, Johannes Schaback
005     * Copyright (c) 2009, Jan Saputra M??ller
006     * All rights reserved.
007     * 
008     * Redistribution and use in source and binary forms, with or without
009     * modification, are permitted provided that the following conditions are
010     * met:
011     * 
012     *     * Redistributions of source code must retain the above copyright
013     *       notice, this list of conditions and the following disclaimer.
014     * 
015     *     * Redistributions in binary form must reproduce the above
016     *       copyright notice, this list of conditions and the following
017     *       disclaimer in the documentation and/or other materials provided
018     *       with the distribution.
019     * 
020     *     * Neither the name of the Technische Universit??t Berlin nor the
021     *       names of its contributors may be used to endorse or promote
022     *       products derived from this software without specific prior
023     *       written permission.
024     * 
025     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
026     * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
027     * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
028     * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
029     * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
030     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
031     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
032     * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
033     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
034     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
035     * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
036     */
037    // --- END LICENSE BLOCK ---
038    package org.jblas;
039    
040    import org.jblas.exceptions.SizeException;
041    import org.jblas.ranges.Range;
042    import java.io.BufferedReader;
043    import java.io.DataInputStream;
044    import java.io.DataOutputStream;
045    import java.io.FileInputStream;
046    import java.io.FileOutputStream;
047    import java.io.IOException;
048    import java.io.InputStreamReader;
049    
050    import java.io.ObjectInputStream;
051    import java.io.ObjectOutputStream;
052    import java.io.PrintWriter;
053    import java.io.Serializable;
054    import java.io.StringWriter;
055    import java.util.AbstractList;
056    import java.util.Arrays;
057    import java.util.Comparator;
058    import java.util.Iterator;
059    import java.util.LinkedList;
060    import java.util.List;
061    
062    /**
063     * A general matrix class for <tt>float</tt> typed values.
064     * 
065     * Don't be intimidated by the large number of methods this function defines. Most
066     * are overloads provided for ease of use. For example, for each arithmetic operation,
067     * up to six overloaded versions exist to handle in-place computations, and
068     * scalar arguments.
069     * 
070     * <h3>Construction</h3>
071     * 
072     * <p>To construct a two-dimensional matrices, you can use the following constructors
073     * and static methods.</p>
074     * 
075     * <table class="my">
076     * <tr><th>Method<th>Description
077     * <tr><td>FloatMatrix(m,n, [value1, value2, value3...])<td>Values are filled in row by row.
078     * <tr><td>FloatMatrix(new float[][] {{value1, value2, ...}, ...}<td>Inner arrays are columns.
079     * <tr><td>FloatMatrix.zeros(m,n) <td>Initial values set to 0.0f.
080     * <tr><td>FloatMatrix.ones(m,n) <td>Initial values set to 1.0f.
081     * <tr><td>FloatMatrix.rand(m,n) <td>Values drawn at random between 0.0f and 1.0f.
082     * <tr><td>FloatMatrix.randn(m,n) <td>Values drawn from normal distribution.
083     * <tr><td>FloatMatrix.eye(n) <td>Unit matrix (values 0.0f except for 1.0f on the diagonal).
084     * <tr><td>FloatMatrix.diag(array) <td>Diagonal matrix with given diagonal elements.
085     * </table>
086     * 
087     * <p>Alternatively, you can construct (column) vectors, if you just supply the length
088     * using the following constructors and static methods.</p>
089     * 
090     * <table class="my">
091     * <tr><th>Method<th>Description
092     * <tr><td>FloatMatrix(m)<td>Constructs a column vector.
093     * <tr><td>FloatMatrix(new float[] {value1, value2, ...})<td>Constructs a column vector.
094     * <tr><td>FloatMatrix.zeros(m) <td>Initial values set to 1.0f.
095     * <tr><td>FloatMatrix.ones(m) <td>Initial values set to 0.0f.
096     * <tr><td>FloatMatrix.rand(m) <td>Values drawn at random between 0.0f and 1.0f.
097     * <tr><td>FloatMatrix.randn(m) <td>Values drawn from normal distribution.
098     * </table>
099     * 
100     * <p>You can also construct new matrices by concatenating matrices either horziontally
101     * or vertically:</p>
102     * 
103     * <table class="my">
104     * <tr><th>Method<th>Description
105     * <tr><td>x.concatHorizontally(y)<td>New matrix will be x next to y.
106     * <tr><td>x.concatVertically(y)<td>New matrix will be x atop y.
107     * </table>
108     * 
109     * <h3>Element Access, Copying and Duplication</h3>
110     * 
111     * <p>To access individual elements, or whole rows and columns, use the following
112     * methods:<p>
113     * 
114     * <table class="my">
115     * <tr><th>x.Method<th>Description
116     * <tr><td>x.get(i,j)<td>Get element in row i and column j.
117     * <tr><td>x.put(i, j, v)<td>Set element in row i and column j to value v
118     * <tr><td>x.get(i)<td>Get the ith element of the matrix (traversing rows first).
119     * <tr><td>x.put(i, v)<td>Set the ith element of the matrix (traversing rows first).
120     * <tr><td>x.getColumn(i)<td>Get a copy of column i.
121     * <tr><td>x.putColumn(i, c)<td>Put matrix c into column i.
122     * <tr><td>x.getRow(i)<td>Get a copy of row i.
123     * <tr><td>x.putRow(i, c)<td>Put matrix c into row i.
124     * <tr><td>x.swapColumns(i, j)<td>Swap the contents of columns i and j.
125     * <tr><td>x.swapRows(i, j)<td>Swap the contents of columns i and j.
126     * </table>
127     * 
128     * <p>For <tt>get</tt> and <tt>put</tt>, you can also pass integer arrays,
129     * FloatMatrix objects, or Range objects, which then specify the indices used 
130     * as follows:
131     * 
132     * <ul>
133     * <li><em>integer array:</em> the elements will be used as indices.
134     * <li><em>FloatMatrix object:</em> non-zero entries specify the indices.
135     * <li><em>Range object:</em> see below.
136     * </ul>
137     * 
138     * <p>When using <tt>put</tt> with multiple indices, the assigned object must
139     * have the correct size or be a scalar.</p>
140     *
141     * <p>There exist the following Range objects. The Class <tt>RangeUtils</tt> also
142     * contains the a number of handy helper methods for constructing these ranges.</p>
143     * <table class="my">
144     * <tr><th>Class <th>RangeUtils method <th>Indices
145     * <tr><td>AllRange <td>all() <td>All legal indices.
146     * <tr><td>PointRange <td>point(i) <td> A single point.
147     * <tr><td>IntervalRange <td>interval(a, b)<td> All indices from a to b (inclusive)
148     * <tr><td rowspan=3>IndicesRange <td>indices(int[])<td> The specified indices.
149     * <tr><td>indices(FloatMatrix)<td>The specified indices.
150     * <tr><td>find(FloatMatrix)<td>The non-zero entries of the matrix.
151     * </table>
152     * 
153     * <p>The following methods can be used for duplicating and copying matrices.</p>
154     * 
155     * <table class="my">
156     * <tr><th>Method<th>Description
157     * <tr><td>x.dup()<td>Get a copy of x.
158     * <tr><td>x.copy(y)<td>Copy the contents of y to x (possible resizing x).
159     * </table>
160     *    
161     * <h3>Size and Shape</h3>
162     * 
163     * <p>The following methods permit to acces the size of a matrix and change its size or shape.</p>
164     * 
165     * <table class="my">
166     * <tr><th>x.Method<th>Description
167     * <tr><td>x.rows<td>Number of rows.
168     * <tr><td>x.columns<td>Number of columns.
169     * <tr><td>x.length<td>Total number of elements.
170     * <tr><td>x.isEmpty()<td>Checks whether rows == 0 and columns == 0.
171     * <tr><td>x.isRowVector()<td>Checks whether rows == 1.
172     * <tr><td>x.isColumnVector()<td>Checks whether columns == 1.
173     * <tr><td>x.isVector()<td>Checks whether rows == 1 or columns == 1.
174     * <tr><td>x.isSquare()<td>Checks whether rows == columns.
175     * <tr><td>x.isScalar()<td>Checks whether length == 1.
176     * <tr><td>x.resize(r, c)<td>Resize the matrix to r rows and c columns, discarding the content.
177     * <tr><td>x.reshape(r, c)<td>Resize the matrix to r rows and c columns.<br> Number of elements must not change.
178     * </table>
179     * 
180     * <p>The size is stored in the <tt>rows</tt> and <tt>columns</tt> member variables.
181     * The total number of elements is stored in <tt>length</tt>. Do not change these
182     * values unless you know what you're doing!</p>
183     * 
184     * <h3>Arithmetics</h3>
185     * 
186     * <p>The usual arithmetic operations are implemented. Each operation exists in a
187     * in-place version, recognizable by the suffix <tt>"i"</tt>, to which you can supply
188     * the result matrix (or <tt>this</tt> is used, if missing). Using in-place operations
189     * can also lead to a smaller memory footprint, as the number of temporary objects
190     * which are directly garbage collected again is reduced.</p>
191     * 
192     * <p>Whenever you specify a result vector, the result vector must already have the
193     * correct dimensions.</p>
194     * 
195     * <p>For example, you can add two matrices using the <tt>add</tt> method. If you want
196     * to store the result in of <tt>x + y</tt> in <tt>z</tt>, type
197     * <span class=code>
198     * x.addi(y, z)   // computes x = y + z.
199     * </span>
200     * Even in-place methods return the result, such that you can easily chain in-place methods,
201     * for example:
202     * <span class=code>
203     * x.addi(y).addi(z) // computes x += y; x += z
204     * </span></p> 
205     *
206     * <p>Methods which operate element-wise only make sure that the length of the matrices
207     * is correct. Therefore, you can add a 3 * 3 matrix to a 1 * 9 matrix, for example.</p>
208     * 
209     * <p>Finally, there exist versions which take floats instead of FloatMatrix Objects
210     * as arguments. These then compute the operation with the same value as the
211     * right-hand-side. The same effect can be achieved by passing a FloatMatrix with
212     * exactly one element.</p>
213     * 
214     * <table class="my">
215     * <tr><th>Operation <th>Method <th>Comment
216     * <tr><td>x + y <td>x.add(y)                 <td>
217     * <tr><td>x - y <td>x.sub(y), y.rsub(x) <td>rsub subtracts left from right hand side
218     * <tr><td rowspan=3>x * y  <td>x.mul(y) <td>element-wise multiplication 
219     * <tr>                                           <td>x.mmul(y)<td>matrix-matrix multiplication
220     * <tr>                                           <td>x.dot(y) <td>scalar-product
221     * <tr><td>x / y <td>x.div(y), y.rdiv(x) <td>rdiv divides right hand side by left hand side.
222     * <tr><td>- x      <td>x.neg()                               <td>
223     * </table>
224     * 
225     * <p>There also exist operations which work on whole columns or rows.</p>
226     * 
227     * <table class="my">
228     * <tr><th>Method <th>Description
229     * <tr><td>x.addRowVector<td>adds a vector to each row (addiRowVector works in-place)
230     * <tr><td>x.addColumnVector<td>adds a vector to each column
231     * <tr><td>x.subRowVector<td>subtracts a vector from each row
232     * <tr><td>x.subColumnVector<td>subtracts a vector from each column
233     * <tr><td>x.mulRow<td>Multiplies a row by a scalar
234     * <tr><td>x.mulColumn<td>multiplies a row by a column
235     * </table>
236     * 
237     * <p>In principle, you could achieve the same result by first calling getColumn(), 
238     * adding, and then calling putColumn, but these methods are much faster.</p>
239     * 
240     * <p>The following comparison operations are available</p>
241     *  
242     * <table class="my">
243     * <tr><th>Operation <th>Method
244     * <tr><td>x &lt; y             <td>x.lt(y)
245     * <tr><td>x &lt;= y    <td>x.le(y)
246     * <tr><td>x &gt; y             <td>x.gt(y)
247     * <tr><td>x &gt;= y    <td>x.ge(y)
248     * <tr><td>x == y           <td>x.eq(y)
249     * <tr><td>x != y           <td>x.ne(y)
250     * </table>
251     *
252     * <p> Logical operations are also supported. For these operations, a value different from
253     * zero is treated as "true" and zero is treated as "false". All operations are carried
254     * out elementwise.</p>
255     * 
256     * <table class="my">
257     * <tr><th>Operation <th>Method
258     * <tr><td>x & y        <td>x.and(y)
259     * <tr><td>x | y    <td>x.or(y)
260     * <tr><td>x ^ y    <td>x.xor(y)
261     * <tr><td>! x              <td>x.not()
262     * </table>
263     * 
264     * <p>Finally, there are a few more methods to compute various things:</p>
265     * 
266     * <table class="my">
267     * <tr><th>Method <th>Description
268     * <tr><td>x.max() <td>Return maximal element
269     * <tr><td>x.argmax() <td>Return index of largest element
270     * <tr><td>x.min() <td>Return minimal element
271     * <tr><td>x.argmin() <td>Return index of largest element
272     * <tr><td>x.columnMins() <td>Return column-wise minima
273     * <tr><td>x.columnArgmins() <td>Return column-wise index of minima
274     * <tr><td>x.columnMaxs() <td>Return column-wise maxima
275     * <tr><td>x.columnArgmaxs() <td>Return column-wise index of maxima
276     * </table>
277     * 
278     * @author Mikio Braun, Johannes Schaback
279     */
280    public class FloatMatrix implements Serializable {
281    
282        /** Number of rows. */
283        public int rows;
284        /** Number of columns. */
285        public int columns;
286        /** Total number of elements (for convenience). */
287        public int length;
288        /** The actual data stored by rows (that is, row 0, row 1...). */
289        public float[] data = null; // rows are contiguous
290        public static final FloatMatrix EMPTY = new FloatMatrix();
291    
292         static final long serialVersionUID = -1249281332731183060L;
293    
294        /**************************************************************************
295         *
296         * Constructors and factory functions
297         *
298         **************************************************************************/
299        /** Create a new matrix with <i>newRows</i> rows, <i>newColumns</i> columns
300         * using <i>newData></i> as the data. The length of the data is not checked!
301         */
302        public FloatMatrix(int newRows, int newColumns, float... newData) {
303            rows = newRows;
304            columns = newColumns;
305            length = rows * columns;
306    
307            if (newData != null && newData.length != newRows * newColumns) {
308                throw new IllegalArgumentException(
309                        "Passed data must match matrix dimensions.");
310            }
311    
312            data = newData;
313            //System.err.printf("%d * %d matrix created\n", rows, columns);
314        }
315    
316        /**
317         * Creates a new <i>n</i> times <i>m</i> <tt>FloatMatrix</tt>.
318         * @param newRows the number of rows (<i>n</i>) of the new matrix.
319         * @param newColumns the number of columns (<i>m</i>) of the new matrix.
320         */
321        public FloatMatrix(int newRows, int newColumns) {
322            this(newRows, newColumns, new float[newRows * newColumns]);
323        }
324    
325        /**
326         * Creates a new <tt>FloatMatrix</tt> of size 0 times 0.
327         */
328        public FloatMatrix() {
329            this(0, 0, (float[]) null);
330        }
331    
332        /**
333         * Create a Matrix of length <tt>len</tt>. By default, this creates a row vector.
334         * @param len
335         */
336        public FloatMatrix(int len) {
337            this(len, 1, new float[len]);
338        }
339    
340        public FloatMatrix(float[] newData) {
341            this(newData.length);
342            data = newData;
343        }
344    
345        /**
346         * Creates a new matrix by reading it from a file.
347         * @param filename the path and name of the file to read the matrix from
348         * @throws IOException
349         */
350        public FloatMatrix(String filename) throws IOException {
351            load(filename);
352        }
353    
354        /**
355         * Creates a new <i>n</i> times <i>m</i> <tt>FloatMatrix</tt> from
356         * the given <i>n</i> times <i>m</i> 2D data array. The first dimension of the array makes the
357         * rows (<i>n</i>) and the second dimension the columns (<i>m</i>). For example, the
358         * given code <br/><br/>
359         * <code>new FloatMatrix(new float[][]{{1d, 2d, 3d}, {4d, 5d, 6d}, {7d, 8d, 9d}}).print();</code><br/><br/>
360         * will constructs the following matrix:
361         * <pre>
362         * 1.0f     2.0f    3.0f
363         * 4.0f     5.0f    6.0f
364         * 7.0f     8.0f    9.0f
365         * </pre>.
366         * @param data <i>n</i> times <i>m</i> data array
367         */
368        public FloatMatrix(float[][] data) {
369            this(data.length, data[0].length);
370    
371            for (int r = 0; r < rows; r++) {
372                assert (data[r].length == columns);
373            }
374    
375            for (int r = 0; r < rows; r++) {
376                for (int c = 0; c < columns; c++) {
377                    put(r, c, data[r][c]);
378                }
379            }
380        }
381    
382        public FloatMatrix(List<Float> data) {
383            this(data.size());
384    
385            int c = 0;
386            for (java.lang.Float d : data) {
387                put(c++, d);
388            }
389        }
390    
391        /**
392         * Construct FloatMatrix from ASCII representation.
393         *
394         * This is not very fast, but can be quiet useful when
395         * you want to "just" construct a matrix, for example
396         * when testing.
397         *
398         * The format is semicolon separated rows of space separated values,
399         * for example "1 2 3; 4 5 6; 7 8 9".
400         */
401        public static FloatMatrix valueOf(String text) {
402            String[] rowValues = text.split(";");
403    
404            // process first line
405            String[] columnValues = rowValues[0].trim().split("\\s+");
406    
407            FloatMatrix result = null;
408    
409            // process rest
410            for (int r = 0; r < rowValues.length; r++) {
411                columnValues = rowValues[r].trim().split("\\s+");
412    
413                if (r == 0) {
414                    result = new FloatMatrix(rowValues.length, columnValues.length);
415                }
416    
417                for (int c = 0; c < columnValues.length; c++) {
418                    result.put(r, c, Float.valueOf(columnValues[c]));
419                }
420            }
421    
422            return result;
423        }
424    
425        /**
426         * Serialization
427         */
428        private void writeObject(ObjectOutputStream s) throws IOException {
429            s.defaultWriteObject();
430        }
431    
432        private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
433            s.defaultReadObject();
434        }
435    
436        /** Create matrix with random values uniformly in 0..1. */
437        public static FloatMatrix rand(int rows, int columns) {
438            FloatMatrix m = new FloatMatrix(rows, columns);
439    
440            java.util.Random r = new java.util.Random();
441            for (int i = 0; i < rows * columns; i++) {
442                m.data[i] = r.nextFloat();
443            }
444    
445            return m;
446        }
447    
448        /** Creates a row vector with random values uniformly in 0..1. */
449        public static FloatMatrix rand(int len) {
450            return rand(len, 1);
451        }
452    
453        /** Create matrix with normally distributed random values. */
454        public static FloatMatrix randn(int rows, int columns) {
455            FloatMatrix m = new FloatMatrix(rows, columns);
456    
457            java.util.Random r = new java.util.Random();
458            for (int i = 0; i < rows * columns; i++) {
459                m.data[i] = (float) r.nextGaussian();
460            }
461    
462            return m;
463        }
464    
465        /** Create row vector with normally distributed random values. */
466        public static FloatMatrix randn(int len) {
467            return randn(len, 1);
468        }
469    
470        /** Creates a new matrix in which all values are equal 0. */
471        public static FloatMatrix zeros(int rows, int columns) {
472            return new FloatMatrix(rows, columns);
473        }
474    
475        /** Creates a row vector of given length. */
476        public static FloatMatrix zeros(int length) {
477            return zeros(length, 1);
478        }
479    
480        /** Creates a new matrix in which all values are equal 1. */
481        public static FloatMatrix ones(int rows, int columns) {
482            FloatMatrix m = new FloatMatrix(rows, columns);
483    
484            for (int i = 0; i < rows * columns; i++) {
485                m.put(i, 1.0f);
486            }
487    
488            return m;
489        }
490    
491        /** Creates a row vector with all elements equal to 1. */
492        public static FloatMatrix ones(int length) {
493            return ones(length, 1);
494        }
495    
496        /** Construct a new n-by-n identity matrix. */
497        public static FloatMatrix eye(int n) {
498            FloatMatrix m = new FloatMatrix(n, n);
499    
500            for (int i = 0; i < n; i++) {
501                m.put(i, i, 1.0f);
502            }
503    
504            return m;
505        }
506    
507        /**
508         * Creates a new matrix where the values of the given vector are the diagonal values of
509         * the matrix.
510         */
511        public static FloatMatrix diag(FloatMatrix x) {
512            FloatMatrix m = new FloatMatrix(x.length, x.length);
513    
514            for (int i = 0; i < x.length; i++) {
515                m.put(i, i, x.get(i));
516            }
517    
518            return m;
519        }
520    
521        /**
522         * Create a 1-by-1 matrix. For many operations, this matrix functions like a
523         * normal float.
524         */
525        public static FloatMatrix scalar(float s) {
526            FloatMatrix m = new FloatMatrix(1, 1);
527            m.put(0, 0, s);
528            return m;
529        }
530    
531        /** Test whether a matrix is scalar. */
532        public boolean isScalar() {
533            return length == 1;
534        }
535    
536        /** Return the first element of the matrix. */
537        public float scalar() {
538            return get(0);
539        }
540    
541        public static FloatMatrix logspace(float lower, float upper, int size) {
542            FloatMatrix result = new FloatMatrix(size);
543            for (int i = 0; i < size; i++) {
544                float t = (float) i / (size - 1);
545                float e = lower * (1 - t) + t * upper;
546                result.put(i, (float) Math.pow(10.0f, e));
547            }
548            return result;
549        }
550    
551        public static FloatMatrix linspace(int lower, int upper, int size) {
552            FloatMatrix result = new FloatMatrix(size);
553            for (int i = 0; i < size; i++) {
554                float t = (float) i / (size - 1);
555                result.put(i, lower * (1 - t) + t * upper);
556            }
557            return result;
558        }
559    
560        /**
561         * Concatenates two matrices horizontally. Matrices must have identical
562         * numbers of rows.
563         */
564        public static FloatMatrix concatHorizontally(FloatMatrix A, FloatMatrix B) {
565            if (A.rows != B.rows) {
566                throw new SizeException("Matrices don't have same number of rows.");
567            }
568    
569            FloatMatrix result = new FloatMatrix(A.rows, A.columns + B.columns);
570            SimpleBlas.copy(A, result);
571            JavaBlas.rcopy(B.length, B.data, 0, 1, result.data, A.length, 1);
572            return result;
573        }
574    
575        /**
576         * Concatenates two matrices vertically. Matrices must have identical
577         * numbers of columns.
578         */
579        public static FloatMatrix concatVertically(FloatMatrix A, FloatMatrix B) {
580            if (A.columns != B.columns) {
581                throw new SizeException("Matrices don't have same number of columns (" + A.columns + " != " + B.columns + ".");
582            }
583    
584            FloatMatrix result = new FloatMatrix(A.rows + B.rows, A.columns);
585    
586            for (int i = 0; i < A.columns; i++) {
587                JavaBlas.rcopy(A.rows, A.data, A.index(0, i), 1, result.data, result.index(0, i), 1);
588                JavaBlas.rcopy(B.rows, B.data, B.index(0, i), 1, result.data, result.index(A.rows, i), 1);
589            }
590    
591            return result;
592        }
593    
594        /**************************************************************************
595         * Working with slices (Man! 30+ methods just to make this a bit flexible...)
596         */
597        /** Get all elements specified by the linear indices. */
598        public FloatMatrix get(int[] indices) {
599            FloatMatrix result = new FloatMatrix(indices.length);
600    
601            for (int i = 0; i < indices.length; i++) {
602                result.put(i, get(indices[i]));
603            }
604    
605            return result;
606        }
607    
608        /** Get all elements for a given row and the specified columns. */
609        public FloatMatrix get(int r, int[] indices) {
610            FloatMatrix result = new FloatMatrix(1, indices.length);
611    
612            for (int i = 0; i < indices.length; i++) {
613                result.put(i, get(r, indices[i]));
614            }
615    
616            return result;
617        }
618    
619        /** Get all elements for a given column and the specified rows. */
620        public FloatMatrix get(int[] indices, int c) {
621            FloatMatrix result = new FloatMatrix(indices.length, c);
622    
623            for (int i = 0; i < indices.length; i++) {
624                result.put(i, get(indices[i], c));
625            }
626    
627            return result;
628        }
629    
630        /** Get all elements from the specified rows and columns. */
631        public FloatMatrix get(int[] rindices, int[] cindices) {
632            FloatMatrix result = new FloatMatrix(rindices.length, cindices.length);
633    
634            for (int i = 0; i < rindices.length; i++) {
635                for (int j = 0; j < cindices.length; j++) {
636                    result.put(i, j, get(rindices[i], cindices[j]));
637                }
638            }
639    
640            return result;
641        }
642    
643        /** Get elements from specified rows and columns. */
644        public FloatMatrix get(Range rs, Range cs) {
645            rs.init(0, rows);
646            cs.init(0, columns);
647            FloatMatrix result = new FloatMatrix(rs.length(), cs.length());
648    
649            for (; !rs.hasMore(); rs.next()) {
650                for (; !cs.hasMore(); cs.next()) {
651                    result.put(rs.index(), cs.index(), get(rs.value(), cs.value()));
652                }
653            }
654    
655            return result;
656        }
657    
658        /** Get elements specified by the non-zero entries of the passed matrix. */
659        public FloatMatrix get(FloatMatrix indices) {
660            return get(indices.findIndices());
661        }
662    
663        /**
664         * Get elements from a row and columns as specified by the non-zero entries of
665         * a matrix.
666         */
667        public FloatMatrix get(int r, FloatMatrix indices) {
668            return get(r, indices.findIndices());
669        }
670    
671        /**
672         * Get elements from a column and rows as specified by the non-zero entries of
673         * a matrix.
674         */
675        public FloatMatrix get(FloatMatrix indices, int c) {
676            return get(indices.findIndices(), c);
677        }
678    
679        /**
680         * Get elements from columns and rows as specified by the non-zero entries of
681         * the passed matrices.
682         */
683        public FloatMatrix get(FloatMatrix rindices, FloatMatrix cindices) {
684            return get(rindices.findIndices(), cindices.findIndices());
685        }
686    
687        /** Return all elements with linear index a, a + 1, ..., b - 1.*/
688        public FloatMatrix getRange(int a, int b) {
689            FloatMatrix result = new FloatMatrix(b - a);
690    
691            for (int k = 0; k < b - a; k++) {
692                result.put(k, get(a + k));
693            }
694    
695            return result;
696        }
697    
698        /** Get elements from a row and columns <tt>a</tt> to <tt>b</tt>. */
699        public FloatMatrix getColumnRange(int r, int a, int b) {
700            FloatMatrix result = new FloatMatrix(1, b - a);
701    
702            for (int k = 0; k < b - a; k++) {
703                result.put(k, get(r, a + k));
704            }
705    
706            return result;
707        }
708    
709        /** Get elements from a column and rows <tt>a/tt> to <tt>b</tt>. */
710        public FloatMatrix getRowRange(int a, int b, int c) {
711            FloatMatrix result = new FloatMatrix(b - a);
712    
713            for (int k = 0; k < b - a; k++) {
714                result.put(k, get(a + k, c));
715            }
716    
717            return result;
718        }
719    
720        /**
721         * Get elements from rows <tt>ra</tt> to <tt>rb</tt> and
722         * columns <tt>ca</tt> to <tt>cb</tt>.
723         */
724        public FloatMatrix getRange(int ra, int rb, int ca, int cb) {
725            FloatMatrix result = new FloatMatrix(rb - ra, cb - ca);
726    
727            for (int i = 0; i < rb - ra; i++) {
728                for (int j = 0; j < cb - ca; j++) {
729                    result.put(i, j, get(ra + i, ca + j));
730                }
731            }
732    
733            return result;
734        }
735    
736        /** Get whole rows from the passed indices. */
737        public FloatMatrix getRows(int[] rindices) {
738            FloatMatrix result = new FloatMatrix(rindices.length, columns);
739            for (int i = 0; i < rindices.length; i++) {
740                JavaBlas.rcopy(columns, data, index(rindices[i], 0), rows, result.data, result.index(i, 0), result.rows);
741            }
742            return result;
743        }
744    
745        /** Get whole rows as specified by the non-zero entries of a matrix. */
746        public FloatMatrix getRows(FloatMatrix rindices) {
747            return getRows(rindices.findIndices());
748        }
749    
750        public FloatMatrix getRows(Range indices, FloatMatrix result) {
751            indices.init(0, rows);
752            if (result.rows < indices.length()) {
753                throw new SizeException("Result matrix does not have enough rows (" + result.rows + " < " + indices.length() + ")");
754            }
755            result.checkColumns(columns);
756    
757            for (int c = 0; c < columns; c++) {
758                indices.init(0, rows);
759                for (int r = 0; indices.hasMore(); indices.next(), r++) {
760                    result.put(r, c, get(indices.index(), c));
761                }
762            }
763            return result;
764        }
765    
766        public FloatMatrix getRows(Range indices) {
767            indices.init(0, rows);
768            FloatMatrix result = new FloatMatrix(indices.length(), columns);
769            return getRows(indices, result);
770        }
771    
772        /** Get whole columns from the passed indices. */
773        public FloatMatrix getColumns(int[] cindices) {
774            FloatMatrix result = new FloatMatrix(rows, cindices.length);
775            for (int i = 0; i < cindices.length; i++) {
776                JavaBlas.rcopy(rows, data, index(0, cindices[i]), 1, result.data, result.index(0, i), 1);
777            }
778            return result;
779        }
780    
781        /** Get whole columns as specified by the non-zero entries of a matrix. */
782        public FloatMatrix getColumns(FloatMatrix cindices) {
783            return getColumns(cindices.findIndices());
784        }
785    
786        /**
787         * Assert that the matrix has a certain length.
788         * @throws SizeException
789         */
790        public void checkLength(int l) {
791            if (length != l) {
792                throw new SizeException("Matrix does not have the necessary length (" + length + " != " + l + ").");
793            }
794        }
795    
796        /**
797         * Asserts that the matrix has a certain number of rows.
798         * @throws SizeException
799         */
800        public void checkRows(int r) {
801            if (rows != r) {
802                throw new SizeException("Matrix does not have the necessary number of rows (" + rows + " != " + r + ").");
803            }
804        }
805    
806        /**
807         * Asserts that the amtrix has a certain number of columns.
808         * @throws SizeException
809         */
810        public void checkColumns(int c) {
811            if (columns != c) {
812                throw new SizeException("Matrix does not have the necessary number of columns (" + columns + " != " + c + ").");
813            }
814        }
815    
816        /** Set elements in linear ordering in the specified indices. */
817        public FloatMatrix put(int[] indices, FloatMatrix x) {
818            if (x.isScalar()) {
819                return put(indices, x.scalar());
820            }
821            x.checkLength(indices.length);
822    
823            for (int i = 0; i < indices.length; i++) {
824                put(indices[i], x.get(i));
825            }
826    
827            return this;
828        }
829    
830        /** Set multiple elements in a row. */
831        public FloatMatrix put(int r, int[] indices, FloatMatrix x) {
832            if (x.isScalar()) {
833                return put(r, indices, x.scalar());
834            }
835            x.checkColumns(indices.length);
836    
837            for (int i = 0; i < indices.length; i++) {
838                put(r, indices[i], x.get(i));
839            }
840    
841            return this;
842        }
843    
844        /** Set multiple elements in a row. */
845        public FloatMatrix put(int[] indices, int c, FloatMatrix x) {
846            if (x.isScalar()) {
847                return put(indices, c, x.scalar());
848            }
849            x.checkRows(indices.length);
850    
851            for (int i = 0; i < indices.length; i++) {
852                put(indices[i], c, x.get(i));
853            }
854    
855            return this;
856        }
857    
858        /** Put a sub-matrix as specified by the indices. */
859        public FloatMatrix put(int[] rindices, int[] cindices, FloatMatrix x) {
860            if (x.isScalar()) {
861                return put(rindices, cindices, x.scalar());
862            }
863            x.checkRows(rindices.length);
864            x.checkColumns(cindices.length);
865    
866            for (int i = 0; i < rindices.length; i++) {
867                for (int j = 0; j < cindices.length; j++) {
868                    put(rindices[i], cindices[j], x.get(i, j));
869                }
870            }
871    
872            return this;
873        }
874    
875        /** Put a matrix into specified indices. */
876        public FloatMatrix put(Range rs, Range cs, FloatMatrix x) {
877            rs.init(0, rows);
878            cs.init(0, columns);
879    
880            x.checkRows(rs.length());
881            x.checkColumns(cs.length());
882    
883            for (; rs.hasMore(); rs.next()) {
884                for (; cs.hasMore(); cs.next()) {
885                    put(rs.value(), cs.value(), x.get(rs.index(), cs.index()));
886                }
887            }
888    
889            return this;
890        }
891    
892        /** Put a single value into the specified indices (linear adressing). */
893        public FloatMatrix put(int[] indices, float v) {
894            for (int i = 0; i < indices.length; i++) {
895                put(indices[i], v);
896            }
897    
898            return this;
899        }
900    
901        /** Put a single value into a row and the specified columns. */
902        public FloatMatrix put(int r, int[] indices, float v) {
903            for (int i = 0; i < indices.length; i++) {
904                put(r, indices[i], v);
905            }
906    
907            return this;
908        }
909    
910        /** Put a single value into the specified rows of a column. */
911        public FloatMatrix put(int[] indices, int c, float v) {
912            for (int i = 0; i < indices.length; i++) {
913                put(indices[i], c, v);
914            }
915    
916            return this;
917        }
918    
919        /** Put a single value into the specified rows and columns. */
920        public FloatMatrix put(int[] rindices, int[] cindices, float v) {
921            for (int i = 0; i < rindices.length; i++) {
922                for (int j = 0; j < cindices.length; j++) {
923                    put(rindices[i], cindices[j], v);
924                }
925            }
926    
927            return this;
928        }
929    
930        /**
931         * Put a sub-matrix into the indices specified by the non-zero entries
932         * of <tt>indices</tt> (linear adressing).
933         */
934        public FloatMatrix put(FloatMatrix indices, FloatMatrix v) {
935            return put(indices.findIndices(), v);
936        }
937    
938        /** Put a sub-vector into the specified columns (non-zero entries of <tt>indices</tt>) of a row. */
939        public FloatMatrix put(int r, FloatMatrix indices, FloatMatrix v) {
940            return put(r, indices.findIndices(), v);
941        }
942    
943        /** Put a sub-vector into the specified rows (non-zero entries of <tt>indices</tt>) of a column. */
944        public FloatMatrix put(FloatMatrix indices, int c, FloatMatrix v) {
945            return put(indices.findIndices(), c, v);
946        }
947    
948        /**
949         * Put a sub-matrix into the specified rows and columns (non-zero entries of
950         * <tt>rindices</tt> and <tt>cindices</tt>.
951         */
952        public FloatMatrix put(FloatMatrix rindices, FloatMatrix cindices, FloatMatrix v) {
953            return put(rindices.findIndices(), cindices.findIndices(), v);
954        }
955    
956        /**
957         * Put a single value into the elements specified by the non-zero
958         * entries of <tt>indices</tt> (linear adressing).
959         */
960        public FloatMatrix put(FloatMatrix indices, float v) {
961            return put(indices.findIndices(), v);
962        }
963    
964        /**
965         * Put a single value into the specified columns (non-zero entries of
966         * <tt>indices</tt>) of a row.
967         */
968        public FloatMatrix put(int r, FloatMatrix indices, float v) {
969            return put(r, indices.findIndices(), v);
970        }
971    
972        /**
973         * Put a single value into the specified rows (non-zero entries of
974         * <tt>indices</tt>) of a column.
975         */
976        public FloatMatrix put(FloatMatrix indices, int c, float v) {
977            return put(indices.findIndices(), c, v);
978        }
979    
980        /**
981         * Put a single value in the specified rows and columns (non-zero entries
982         * of <tt>rindices</tt> and <tt>cindices</tt>.
983         */
984        public FloatMatrix put(FloatMatrix rindices, FloatMatrix cindices, float v) {
985            return put(rindices.findIndices(), cindices.findIndices(), v);
986        }
987    
988        /** Find the linear indices of all non-zero elements. */
989        public int[] findIndices() {
990            int len = 0;
991            for (int i = 0; i < length; i++) {
992                if (get(i) != 0.0f) {
993                    len++;
994                }
995            }
996    
997            int[] indices = new int[len];
998            int c = 0;
999    
1000            for (int i = 0; i < length; i++) {
1001                if (get(i) != 0.0f) {
1002                    indices[c++] = i;
1003                }
1004            }
1005    
1006            return indices;
1007        }
1008    
1009        /**************************************************************************
1010         * Basic operations (copying, resizing, element access)
1011         */
1012        /** Return transposed copy of this matrix. */
1013        public FloatMatrix transpose() {
1014            FloatMatrix result = new FloatMatrix(columns, rows);
1015    
1016            for (int i = 0; i < rows; i++) {
1017                for (int j = 0; j < columns; j++) {
1018                    result.put(j, i, get(i, j));
1019                }
1020            }
1021    
1022            return result;
1023        }
1024    
1025        /**
1026         * Compare two matrices. Returns true if and only if other is also a
1027         * FloatMatrix which has the same size and the maximal absolute
1028         * difference in matrix elements is smaller thatn 1e-6.
1029         */
1030        public boolean equals(Object o) {
1031            if (!(o instanceof FloatMatrix)) {
1032                return false;
1033            }
1034    
1035            FloatMatrix other = (FloatMatrix) o;
1036    
1037            if (!sameSize(other)) {
1038                return false;
1039            }
1040    
1041            FloatMatrix diff = MatrixFunctions.absi(sub(other));
1042    
1043            return diff.max() / (rows * columns) < 1e-6;
1044        }
1045    
1046        /** Resize the matrix. All elements will be set to zero. */
1047        public void resize(int newRows, int newColumns) {
1048            rows = newRows;
1049            columns = newColumns;
1050            length = newRows * newColumns;
1051            data = new float[rows * columns];
1052        }
1053    
1054        /** Reshape the matrix. Number of elements must not change. */
1055        public FloatMatrix reshape(int newRows, int newColumns) {
1056            if (length != newRows * newColumns) {
1057                throw new IllegalArgumentException(
1058                        "Number of elements must not change.");
1059            }
1060    
1061            rows = newRows;
1062            columns = newColumns;
1063    
1064            return this;
1065        }
1066    
1067        /** Generate a new matrix which has the given number of replications of this. */
1068        public FloatMatrix repmat(int rowMult, int columnMult) {
1069            FloatMatrix result = new FloatMatrix(rows * rowMult, columns * columnMult);
1070    
1071            for (int c = 0; c < columnMult; c++) {
1072                for (int r = 0; r < rowMult; r++) {
1073                    for (int i = 0; i < rows; i++) {
1074                        for (int j = 0; j < columns; j++) {
1075                            result.put(r * rows + i, c * columns + j, get(i, j));
1076                        }
1077                    }
1078                }
1079            }
1080            return result;
1081        }
1082    
1083        /** Checks whether two matrices have the same size. */
1084        public boolean sameSize(FloatMatrix a) {
1085            return rows == a.rows && columns == a.columns;
1086        }
1087    
1088        /** Throws SizeException unless two matrices have the same size. */
1089        public void assertSameSize(FloatMatrix a) {
1090            if (!sameSize(a)) {
1091                throw new SizeException("Matrices must have the same size.");
1092            }
1093        }
1094    
1095        /** Checks whether two matrices can be multiplied (that is, number of columns of
1096         * this must equal number of rows of a. */
1097        public boolean multipliesWith(FloatMatrix a) {
1098            return columns == a.rows;
1099        }
1100    
1101        /** Throws SizeException unless matrices can be multiplied with one another. */
1102        public void assertMultipliesWith(FloatMatrix a) {
1103            if (!multipliesWith(a)) {
1104                throw new SizeException("Number of columns of left matrix must be equal to number of rows of right matrix.");
1105            }
1106        }
1107    
1108        /** Checks whether two matrices have the same length. */
1109        public boolean sameLength(FloatMatrix a) {
1110            return length == a.length;
1111        }
1112    
1113        /** Throws SizeException unless matrices have the same length. */
1114        public void assertSameLength(FloatMatrix a) {
1115            if (!sameLength(a)) {
1116                throw new SizeException("Matrices must have same length (is: " + length + " and " + a.length + ")");
1117            }
1118        }
1119    
1120        /** Copy FloatMatrix a to this. this a is resized if necessary. */
1121        public FloatMatrix copy(FloatMatrix a) {
1122            if (!sameSize(a)) {
1123                resize(a.rows, a.columns);
1124            }
1125    
1126            System.arraycopy(a.data, 0, data, 0, length);
1127            return a;
1128        }
1129    
1130        /**
1131         * Returns a duplicate of this matrix. Geometry is the same (including offsets, transpose, etc.),
1132         * but the buffer is not shared.
1133         */
1134        public FloatMatrix dup() {
1135            FloatMatrix out = new FloatMatrix(rows, columns);
1136    
1137            JavaBlas.rcopy(length, data, 0, 1, out.data, 0, 1);
1138    
1139            return out;
1140        }
1141    
1142        /** Swap two columns of a matrix. */
1143        public FloatMatrix swapColumns(int i, int j) {
1144            NativeBlas.sswap(rows, data, index(0, i), 1, data, index(0, j), 1);
1145            return this;
1146        }
1147    
1148        /** Swap two rows of a matrix. */
1149        public FloatMatrix swapRows(int i, int j) {
1150            NativeBlas.sswap(columns, data, index(i, 0), rows, data, index(j, 0), rows);
1151            return this;
1152        }
1153    
1154        /** Set matrix element */
1155        public FloatMatrix put(int rowIndex, int columnIndex, float value) {
1156            data[index(rowIndex, columnIndex)] = value;
1157            return this;
1158        }
1159    
1160        /** Retrieve matrix element */
1161        public float get(int rowIndex, int columnIndex) {
1162            return data[index(rowIndex, columnIndex)];
1163        }
1164    
1165        /** Get index of an element */
1166        public int index(int rowIndex, int columnIndex) {
1167            return rowIndex + rows * columnIndex;
1168        }
1169    
1170        /** Compute the row index of a linear index. */
1171        public int indexRows(int i) {
1172            return i / rows;
1173        }
1174    
1175        /** Compute the column index of a linear index. */
1176        public int indexColumns(int i) {
1177            return i - indexRows(i) * rows;
1178        }
1179    
1180        /** Get a matrix element (linear indexing). */
1181        public float get(int i) {
1182            return data[i];
1183        }
1184    
1185        /** Set a matrix element (linear indexing). */
1186        public FloatMatrix put(int i, float v) {
1187            data[i] = v;
1188            return this;
1189        }
1190    
1191        /** Set all elements to a value. */
1192        public FloatMatrix fill(float value) {
1193            for (int i = 0; i < length; i++) {
1194                put(i, value);
1195            }
1196            return this;
1197        }
1198    
1199        /** Get number of rows. */
1200        public int getRows() {
1201            return rows;
1202        }
1203    
1204        /** Get number of columns. */
1205        public int getColumns() {
1206            return columns;
1207        }
1208    
1209        /** Get total number of elements. */
1210        public int getLength() {
1211            return length;
1212        }
1213    
1214        /** Checks whether the matrix is empty. */
1215        public boolean isEmpty() {
1216            return columns == 0 || rows == 0;
1217        }
1218    
1219        /** Checks whether the matrix is square. */
1220        public boolean isSquare() {
1221            return columns == rows;
1222        }
1223    
1224        /** Throw SizeException unless matrix is square. */
1225        public void assertSquare() {
1226            if (!isSquare()) {
1227                throw new SizeException("Matrix must be square!");
1228            }
1229        }
1230    
1231        /** Checks whether the matrix is a vector. */
1232        public boolean isVector() {
1233            return columns == 1 || rows == 1;
1234        }
1235    
1236        /** Checks whether the matrix is a row vector. */
1237        public boolean isRowVector() {
1238            return rows == 1;
1239        }
1240    
1241        /** Checks whether the matrix is a column vector. */
1242        public boolean isColumnVector() {
1243            return columns == 1;
1244        }
1245    
1246        /** Returns the diagonal of the matrix. */
1247        public FloatMatrix diag() {
1248            assertSquare();
1249            FloatMatrix d = new FloatMatrix(rows);
1250            JavaBlas.rcopy(rows, data, 0, rows + 1, d.data, 0, 1);
1251            return d;
1252        }
1253    
1254        /** Pretty-print this matrix to <tt>System.out</tt>. */
1255        public void print() {
1256            System.out.println(toString());
1257        }
1258    
1259        /** Generate string representation of the matrix. */
1260        @Override
1261        public String toString() {
1262            StringBuilder s = new StringBuilder();
1263    
1264            s.append("[");
1265    
1266            for (int i = 0; i < rows; i++) {
1267                for (int j = 0; j < columns; j++) {
1268                    s.append(get(i, j));
1269                    if (j < columns - 1) {
1270                        s.append(", ");
1271                    }
1272                }
1273                if (i < rows - 1) {
1274                    s.append("; ");
1275                }
1276            }
1277    
1278            s.append("]");
1279    
1280            return s.toString();
1281        }
1282    
1283        /**
1284         * Generate string representation of the matrix, with specified
1285         * format for the entries. For example, <code>x.toString("%.1f")</code>
1286         * generates a string representations having only one position after the
1287         * decimal point.
1288         */
1289        public String toString(String fmt) {
1290            StringWriter s = new StringWriter();
1291            PrintWriter p = new PrintWriter(s);
1292    
1293            p.print("[");
1294    
1295            for (int r = 0; r < rows; r++) {
1296                for (int c = 0; c < columns; c++) {
1297                    p.printf(fmt, get(r, c));
1298                    if (c < columns - 1) {
1299                        p.print(", ");
1300                    }
1301                }
1302                if (r < rows - 1) {
1303                    p.print("; ");
1304                }
1305            }
1306    
1307            p.print("]");
1308    
1309            return s.toString();
1310        }
1311    
1312        /** Converts the matrix to a one-dimensional array of floats. */
1313        public float[] toArray() {
1314            float[] array = new float[length];
1315    
1316            System.arraycopy(data, 0, array, 0, length);
1317    
1318            return array;
1319        }
1320    
1321        /** Converts the matrix to a two-dimensional array of floats. */
1322        public float[][] toArray2() {
1323            float[][] array = new float[rows][columns];
1324    
1325            for (int r = 0; r < rows; r++) {
1326                for (int c = 0; c < columns; c++) {
1327                    array[r][c] = get(r, c);
1328                }
1329            }
1330    
1331            return array;
1332        }
1333    
1334        /** Converts the matrix to a one-dimensional array of integers. */
1335        public int[] toIntArray() {
1336            int[] array = new int[length];
1337    
1338            for (int i = 0; i < length; i++) {
1339                array[i] = (int) Math.rint(get(i));
1340            }
1341    
1342            return array;
1343        }
1344    
1345        /** Convert the matrix to a two-dimensional array of integers. */
1346        public int[][] toIntArray2() {
1347            int[][] array = new int[rows][columns];
1348    
1349            for (int r = 0; r < rows; r++) {
1350                for (int c = 0; c < columns; c++) {
1351                    array[r][c] = (int) Math.rint(get(r, c));
1352                }
1353            }
1354    
1355            return array;
1356        }
1357    
1358        /** Convert the matrix to a one-dimensional array of boolean values. */
1359        public boolean[] toBooleanArray() {
1360            boolean[] array = new boolean[length];
1361    
1362            for (int i = 0; i < length; i++) {
1363                array[i] = get(i) != 0.0f ? true : false;
1364            }
1365    
1366            return array;
1367        }
1368    
1369        /** Convert the matrix to a two-dimensional array of boolean values. */
1370        public boolean[][] toBooleanArray2() {
1371            boolean[][] array = new boolean[rows][columns];
1372    
1373            for (int r = 0; r < rows; r++) {
1374                for (int c = 0; c < columns; c++) {
1375                    array[r][c] = get(r, c) != 0.0f ? true : false;
1376                }
1377            }
1378    
1379            return array;
1380        }
1381    
1382        /** Convert matrix to FloatMatrix. */
1383        public FloatMatrix toFloatMatrix() {
1384            FloatMatrix result = new FloatMatrix(rows, columns);
1385    
1386            for (int c = 0; c < columns; c++) {
1387                for (int r = 0; r < rows; r++) {
1388                    result.put(r, c, (float) get(r, c));
1389                }
1390            }
1391    
1392            return result;
1393        }
1394    
1395        /**
1396         * A wrapper which allows to view a matrix as a List of Doubles (read-only!).
1397         * Also implements the {@link ConvertsToFloatMatrix} interface.
1398         */
1399        public class ElementsAsListView extends AbstractList<Float> implements ConvertsToFloatMatrix {
1400    
1401            private FloatMatrix me;
1402    
1403            public ElementsAsListView(FloatMatrix me) {
1404                this.me = me;
1405            }
1406    
1407            @Override
1408            public Float get(int index) {
1409                return me.get(index);
1410            }
1411    
1412            @Override
1413            public int size() {
1414                return me.length;
1415            }
1416    
1417            public FloatMatrix convertToFloatMatrix() {
1418                return me;
1419            }
1420        }
1421    
1422        public class RowsAsListView extends AbstractList<FloatMatrix> implements ConvertsToFloatMatrix {
1423    
1424            private FloatMatrix me;
1425    
1426            public RowsAsListView(FloatMatrix me) {
1427                this.me = me;
1428            }
1429    
1430            @Override
1431            public FloatMatrix get(int index) {
1432                return getRow(index);
1433            }
1434    
1435            @Override
1436            public int size() {
1437                return rows;
1438            }
1439    
1440            public FloatMatrix convertToFloatMatrix() {
1441                return me;
1442            }
1443        }
1444    
1445        public class ColumnsAsListView extends AbstractList<FloatMatrix> implements ConvertsToFloatMatrix {
1446    
1447            private FloatMatrix me;
1448    
1449            public ColumnsAsListView(FloatMatrix me) {
1450                this.me = me;
1451            }
1452    
1453            @Override
1454            public FloatMatrix get(int index) {
1455                return getColumn(index);
1456            }
1457    
1458            @Override
1459            public int size() {
1460                return columns;
1461            }
1462    
1463            public FloatMatrix convertToFloatMatrix() {
1464                return me;
1465            }
1466        }
1467    
1468        public List<Float> elementsAsList() {
1469            return new ElementsAsListView(this);
1470        }
1471    
1472        public List<FloatMatrix> rowsAsList() {
1473            return new RowsAsListView(this);
1474        }
1475    
1476        public List<FloatMatrix> columnsAsList() {
1477            return new ColumnsAsListView(this);
1478        }
1479    
1480        /**************************************************************************
1481         * Arithmetic Operations
1482         */
1483        /**
1484         * Ensures that the result vector has the same length as this. If not,
1485         * resizing result is tried, which fails if result == this or result == other.
1486         */
1487        private void ensureResultLength(FloatMatrix other, FloatMatrix result) {
1488            if (!sameLength(result)) {
1489                if (result == this || result == other) {
1490                    throw new SizeException("Cannot resize result matrix because it is used in-place.");
1491                }
1492                result.resize(rows, columns);
1493            }
1494        }
1495    
1496        /** Add two matrices (in-place). */
1497        public FloatMatrix addi(FloatMatrix other, FloatMatrix result) {
1498            if (other.isScalar()) {
1499                return addi(other.scalar(), result);
1500            }
1501            if (isScalar()) {
1502                return other.addi(scalar(), result);
1503            }
1504    
1505            assertSameLength(other);
1506            ensureResultLength(other, result);
1507    
1508            if (result == this) {
1509                SimpleBlas.axpy(1.0f, other, result);
1510            } else if (result == other) {
1511                SimpleBlas.axpy(1.0f, this, result);
1512            } else {
1513                /*SimpleBlas.copy(this, result);
1514                SimpleBlas.axpy(1.0f, other, result);*/
1515                JavaBlas.rzgxpy(length, result.data, data, other.data);
1516            }
1517    
1518            return result;
1519        }
1520    
1521        /** Add a scalar to a matrix (in-place). */
1522        public FloatMatrix addi(float v, FloatMatrix result) {
1523            ensureResultLength(null, result);
1524    
1525            for (int i = 0; i < length; i++) {
1526                result.put(i, get(i) + v);
1527            }
1528            return result;
1529        }
1530    
1531        /** Subtract two matrices (in-place). */
1532        public FloatMatrix subi(FloatMatrix other, FloatMatrix result) {
1533            if (other.isScalar()) {
1534                return subi(other.scalar(), result);
1535            }
1536            if (isScalar()) {
1537                return other.rsubi(scalar(), result);
1538            }
1539    
1540            assertSameLength(other);
1541            ensureResultLength(other, result);
1542    
1543            if (result == this) {
1544                SimpleBlas.axpy(-1.0f, other, result);
1545            } else if (result == other) {
1546                SimpleBlas.scal(-1.0f, result);
1547                SimpleBlas.axpy(1.0f, this, result);
1548            } else {
1549                SimpleBlas.copy(this, result);
1550                SimpleBlas.axpy(-1.0f, other, result);
1551            }
1552            return result;
1553        }
1554    
1555        /** Subtract a scalar from a matrix (in-place). */
1556        public FloatMatrix subi(float v, FloatMatrix result) {
1557            ensureResultLength(null, result);
1558    
1559            for (int i = 0; i < length; i++) {
1560                result.put(i, get(i) - v);
1561            }
1562            return result;
1563        }
1564    
1565        /**
1566         * Subtract two matrices, but subtract first from second matrix, that is,
1567         * compute <em>result = other - this</em> (in-place).
1568         * */
1569        public FloatMatrix rsubi(FloatMatrix other, FloatMatrix result) {
1570            return other.subi(this, result);
1571        }
1572    
1573        /** Subtract a matrix from a scalar (in-place). */
1574        public FloatMatrix rsubi(float a, FloatMatrix result) {
1575            ensureResultLength(null, result);
1576    
1577            for (int i = 0; i < length; i++) {
1578                result.put(i, a - get(i));
1579            }
1580            return result;
1581        }
1582    
1583        /** Elementwise multiplication (in-place). */
1584        public FloatMatrix muli(FloatMatrix other, FloatMatrix result) {
1585            if (other.isScalar()) {
1586                return muli(other.scalar(), result);
1587            }
1588            if (isScalar()) {
1589                return other.muli(scalar(), result);
1590            }
1591    
1592            assertSameLength(other);
1593            ensureResultLength(other, result);
1594    
1595            for (int i = 0; i < length; i++) {
1596                result.put(i, get(i) * other.get(i));
1597            }
1598            return result;
1599        }
1600    
1601        /** Elementwise multiplication with a scalar (in-place). */
1602        public FloatMatrix muli(float v, FloatMatrix result) {
1603            ensureResultLength(null, result);
1604    
1605            for (int i = 0; i < length; i++) {
1606                result.put(i, get(i) * v);
1607            }
1608            return result;
1609        }
1610    
1611        /** Matrix-matrix multiplication (in-place). */
1612        public FloatMatrix mmuli(FloatMatrix other, FloatMatrix result) {
1613            if (other.isScalar()) {
1614                return muli(other.scalar(), result);
1615            }
1616            if (isScalar()) {
1617                return other.muli(scalar(), result);
1618            }
1619    
1620            /* check sizes and resize if necessary */
1621            assertMultipliesWith(other);
1622            if (result.rows != rows || result.columns != other.columns) {
1623                if (result != this && result != other) {
1624                    result.resize(rows, other.columns);
1625                } else {
1626                    throw new SizeException("Cannot resize result matrix because it is used in-place.");
1627                }
1628            }
1629    
1630            if (result == this || result == other) {
1631                /* actually, blas cannot do multiplications in-place. Therefore, we will fake by
1632                 * allocating a temporary object on the side and copy the result later.
1633                 */
1634                FloatMatrix temp = new FloatMatrix(result.rows, result.columns);
1635                if (other.columns == 1) {
1636                    SimpleBlas.gemv(1.0f, this, other, 0.0f, temp);
1637                } else {
1638                    SimpleBlas.gemm(1.0f, this, other, 0.0f, temp);
1639                }
1640                SimpleBlas.copy(temp, result);
1641            } else {
1642                if (other.columns == 1) {
1643                    SimpleBlas.gemv(1.0f, this, other, 0.0f, result);
1644                } else {
1645                    SimpleBlas.gemm(1.0f, this, other, 0.0f, result);
1646                }
1647            }
1648            return result;
1649        }
1650    
1651        /** Matrix-matrix multiplication with a scalar (for symmetry, does the
1652         * same as <code>muli(scalar)</code> (in-place).
1653         */
1654        public FloatMatrix mmuli(float v, FloatMatrix result) {
1655            return muli(v, result);
1656        }
1657    
1658        /** Elementwise division (in-place). */
1659        public FloatMatrix divi(FloatMatrix other, FloatMatrix result) {
1660            if (other.isScalar()) {
1661                return divi(other.scalar(), result);
1662            }
1663            if (isScalar()) {
1664                return other.rdivi(scalar(), result);
1665            }
1666    
1667            assertSameLength(other);
1668            ensureResultLength(other, result);
1669    
1670            for (int i = 0; i < length; i++) {
1671                result.put(i, get(i) / other.get(i));
1672            }
1673            return result;
1674        }
1675    
1676        /** Elementwise division with a scalar (in-place). */
1677        public FloatMatrix divi(float a, FloatMatrix result) {
1678            ensureResultLength(null, result);
1679    
1680            for (int i = 0; i < length; i++) {
1681                result.put(i, get(i) / a);
1682            }
1683            return result;
1684        }
1685    
1686        /**
1687         * Elementwise division, with operands switched. Computes
1688         * <code>result = other / this</code> (in-place). */
1689        public FloatMatrix rdivi(FloatMatrix other, FloatMatrix result) {
1690            return other.divi(this, result);
1691        }
1692    
1693        /** (Elementwise) division with a scalar, with operands switched. Computes
1694         * <code>result = a / this</code> (in-place). */
1695        public FloatMatrix rdivi(float a, FloatMatrix result) {
1696            ensureResultLength(null, result);
1697    
1698            for (int i = 0; i < length; i++) {
1699                result.put(i, a / get(i));
1700            }
1701            return result;
1702        }
1703    
1704        /** Negate each element (in-place). */
1705        public FloatMatrix negi() {
1706            for (int i = 0; i < length; i++) {
1707                put(i, -get(i));
1708            }
1709            return this;
1710        }
1711    
1712        /** Negate each element. */
1713        public FloatMatrix neg() {
1714            return dup().negi();
1715        }
1716    
1717        /** Maps zero to 1.0f and all non-zero values to 0.0f (in-place). */
1718        public FloatMatrix noti() {
1719            for (int i = 0; i < length; i++) {
1720                put(i, get(i) == 0.0f ? 1.0f : 0.0f);
1721            }
1722            return this;
1723        }
1724    
1725        /** Maps zero to 1.0f and all non-zero values to 0.0f. */
1726        public FloatMatrix not() {
1727            return dup().noti();
1728        }
1729    
1730        /** Maps zero to 0.0f and all non-zero values to 1.0f (in-place). */
1731        public FloatMatrix truthi() {
1732            for (int i = 0; i < length; i++) {
1733                put(i, get(i) == 0.0f ? 0.0f : 1.0f);
1734            }
1735            return this;
1736        }
1737    
1738        /** Maps zero to 0.0f and all non-zero values to 1.0f. */
1739        public FloatMatrix truth() {
1740            return dup().truthi();
1741        }
1742    
1743        public FloatMatrix isNaNi() {
1744            for (int i = 0; i < length; i++) {
1745                put(i, Float.isNaN(get(i)) ? 1.0f : 0.0f);
1746            }
1747            return this;
1748        }
1749    
1750        public FloatMatrix isNaN() {
1751            return dup().isNaNi();
1752        }
1753    
1754        public FloatMatrix isInfinitei() {
1755            for (int i = 0; i < length; i++) {
1756                put(i, Float.isInfinite(get(i)) ? 1.0f : 0.0f);
1757            }
1758            return this;
1759        }
1760    
1761        public FloatMatrix isInfinite() {
1762            return dup().isInfinitei();
1763        }
1764    
1765        public FloatMatrix selecti(FloatMatrix where) {
1766            checkLength(where.length);
1767            for (int i = 0; i < length; i++) {
1768                if (where.get(i) == 0.0f) {
1769                    put(i, 0.0f);
1770                }
1771            }
1772            return this;
1773        }
1774    
1775        public FloatMatrix select(FloatMatrix where) {
1776            return dup().selecti(where);
1777        }
1778    
1779        /****************************************************************
1780         * Rank one-updates
1781         */
1782        /** Computes a rank-1-update A = A + alpha * x * y'. */
1783        public FloatMatrix rankOneUpdate(float alpha, FloatMatrix x, FloatMatrix y) {
1784            if (rows != x.length) {
1785                throw new SizeException("Vector x has wrong length (" + x.length + " != " + rows + ").");
1786            }
1787            if (columns != y.length) {
1788                throw new SizeException("Vector y has wrong length (" + x.length + " != " + columns + ").");
1789            }
1790    
1791            SimpleBlas.ger(alpha, x, y, this);
1792            return this;
1793        }
1794    
1795        /** Computes a rank-1-update A = A + alpha * x * x'. */
1796        public FloatMatrix rankOneUpdate(float alpha, FloatMatrix x) {
1797            return rankOneUpdate(alpha, x, x);
1798        }
1799    
1800        /** Computes a rank-1-update A = A + x * x'. */
1801        public FloatMatrix rankOneUpdate(FloatMatrix x) {
1802            return rankOneUpdate(1.0f, x, x);
1803        }
1804    
1805        /** Computes a rank-1-update A = A + x * y'. */
1806        public FloatMatrix rankOneUpdate(FloatMatrix x, FloatMatrix y) {
1807            return rankOneUpdate(1.0f, x, y);
1808        }
1809    
1810        /****************************************************************
1811         * Logical operations
1812         */
1813        /** Returns the minimal element of the matrix. */
1814        public float min() {
1815            if (isEmpty()) {
1816                return Float.POSITIVE_INFINITY;
1817            }
1818            float v = Float.POSITIVE_INFINITY;
1819            for (int i = 0; i < length; i++) {
1820                if (!Float.isNaN(get(i)) && get(i) < v) {
1821                    v = get(i);
1822                }
1823            }
1824    
1825            return v;
1826        }
1827    
1828        /**
1829         * Returns the linear index of the minimal element. If there are
1830         * more than one elements with this value, the first one is returned.
1831         */
1832        public int argmin() {
1833            if (isEmpty()) {
1834                return -1;
1835            }
1836            float v = Float.POSITIVE_INFINITY;
1837            int a = -1;
1838            for (int i = 0; i < length; i++) {
1839                if (!Float.isNaN(get(i)) && get(i) < v) {
1840                    v = get(i);
1841                    a = i;
1842                }
1843            }
1844    
1845            return a;
1846        }
1847    
1848        /**
1849         * Computes the minimum between two matrices. Returns the smaller of the
1850         * corresponding elements in the matrix (in-place).
1851         */
1852        public FloatMatrix mini(FloatMatrix other, FloatMatrix result) {
1853            if (result == this) {
1854                for (int i = 0; i < length; i++) {
1855                    if (get(i) > other.get(i)) {
1856                        put(i, other.get(i));
1857                    }
1858                }
1859            } else {
1860                for (int i = 0; i < length; i++) {
1861                    if (get(i) > other.get(i)) {
1862                        result.put(i, other.get(i));
1863                    } else {
1864                        result.put(i, get(i));
1865                    }
1866                }
1867            }
1868            return this;
1869        }
1870    
1871        /**
1872         * Computes the minimum between two matrices. Returns the smaller of the
1873         * corresponding elements in the matrix (in-place on this).
1874         */
1875        public FloatMatrix mini(FloatMatrix other) {
1876            return mini(other, this);
1877        }
1878    
1879        /**
1880         * Computes the minimum between two matrices. Returns the smaller of the
1881         * corresponding elements in the matrix (in-place on this).
1882         */
1883        public FloatMatrix min(FloatMatrix other) {
1884            return mini(other, new FloatMatrix(rows, columns));
1885        }
1886    
1887        public FloatMatrix mini(float v, FloatMatrix result) {
1888            if (result == this) {
1889                for (int i = 0; i < length; i++) {
1890                    if (get(i) > v) {
1891                        result.put(i, v);
1892                    }
1893                }
1894            } else {
1895                for (int i = 0; i < length; i++) {
1896                    if (get(i) > v) {
1897                        result.put(i, v);
1898                    } else {
1899                        result.put(i, get(i));
1900                    }
1901                }
1902    
1903            }
1904            return this;
1905        }
1906    
1907        public FloatMatrix mini(float v) {
1908            return mini(v, this);
1909        }
1910    
1911        public FloatMatrix min(float v) {
1912            return mini(v, new FloatMatrix(rows, columns));
1913        }
1914    
1915        /** Returns the maximal element of the matrix. */
1916        public float max() {
1917            if (isEmpty()) {
1918                return Float.NEGATIVE_INFINITY;
1919            }
1920            float v = Float.NEGATIVE_INFINITY;
1921            for (int i = 0; i < length; i++) {
1922                if (!Float.isNaN(get(i)) && get(i) > v) {
1923                    v = get(i);
1924                }
1925            }
1926            return v;
1927        }
1928    
1929        /**
1930         * Returns the linear index of the maximal element of the matrix. If
1931         * there are more than one elements with this value, the first one
1932         * is returned.
1933         */
1934        public int argmax() {
1935            if (isEmpty()) {
1936                return -1;
1937            }
1938            float v = Float.NEGATIVE_INFINITY;
1939            int a = -1;
1940            for (int i = 0; i < length; i++) {
1941                if (!Float.isNaN(get(i)) && get(i) > v) {
1942                    v = get(i);
1943                    a = i;
1944                }
1945            }
1946    
1947            return a;
1948        }
1949    
1950        /**
1951         * Computes the maximum between two matrices. Returns the larger of the
1952         * corresponding elements in the matrix (in-place).
1953         */
1954        public FloatMatrix maxi(FloatMatrix other, FloatMatrix result) {
1955            if (result == this) {
1956                for (int i = 0; i < length; i++) {
1957                    if (get(i) < other.get(i)) {
1958                        put(i, other.get(i));
1959                    }
1960                }
1961            } else {
1962                for (int i = 0; i < length; i++) {
1963                    if (get(i) < other.get(i)) {
1964                        result.put(i, other.get(i));
1965                    } else {
1966                        result.put(i, get(i));
1967                    }
1968                }
1969            }
1970            return this;
1971        }
1972    
1973        /**
1974         * Computes the maximum between two matrices. Returns the smaller of the
1975         * corresponding elements in the matrix (in-place on this).
1976         */
1977        public FloatMatrix maxi(FloatMatrix other) {
1978            return maxi(other, this);
1979        }
1980    
1981        /**
1982         * Computes the maximum between two matrices. Returns the larger of the
1983         * corresponding elements in the matrix (in-place on this).
1984         */
1985        public FloatMatrix max(FloatMatrix other) {
1986            return maxi(other, new FloatMatrix(rows, columns));
1987        }
1988    
1989        public FloatMatrix maxi(float v, FloatMatrix result) {
1990            if (result == this) {
1991                for (int i = 0; i < length; i++) {
1992                    if (get(i) < v) {
1993                        result.put(i, v);
1994                    }
1995                }
1996            } else {
1997                for (int i = 0; i < length; i++) {
1998                    if (get(i) < v) {
1999                        result.put(i, v);
2000                    } else {
2001                        result.put(i, get(i));
2002                    }
2003                }
2004    
2005            }
2006            return this;
2007        }
2008    
2009        public FloatMatrix maxi(float v) {
2010            return maxi(v, this);
2011        }
2012    
2013        public FloatMatrix max(float v) {
2014            return maxi(v, new FloatMatrix(rows, columns));
2015        }
2016    
2017        /** Computes the sum of all elements of the matrix. */
2018        public float sum() {
2019            float s = 0.0f;
2020            for (int i = 0; i < length; i++) {
2021                s += get(i);
2022            }
2023            return s;
2024        }
2025    
2026        /** Computes the product of all elements of the matrix */
2027        public float prod() {
2028            float p = 1.0f;
2029            for (int i = 0; i < length; i++) {
2030                p *= get(i);
2031            }
2032            return p;
2033        }
2034    
2035        /**
2036         * Computes the mean value of all elements in the matrix,
2037         * that is, <code>x.sum() / x.length</code>.
2038         */
2039        public float mean() {
2040            return sum() / length;
2041        }
2042    
2043        /**
2044         * Computes the cumulative sum, that is, the sum of all elements
2045         * of the matrix up to a given index in linear addressing (in-place).
2046         */
2047        public FloatMatrix cumulativeSumi() {
2048            float s = 0.0f;
2049            for (int i = 0; i < length; i++) {
2050                s += get(i);
2051                put(i, s);
2052            }
2053            return this;
2054        }
2055    
2056        /**
2057         * Computes the cumulative sum, that is, the sum of all elements
2058         * of the matrix up to a given index in linear addressing.
2059         */
2060        public FloatMatrix cumulativeSum() {
2061            return dup().cumulativeSumi();
2062        }
2063    
2064        /** The scalar product of this with other. */
2065        public float dot(FloatMatrix other) {
2066            return SimpleBlas.dot(this, other);
2067        }
2068    
2069        /** 
2070         * Computes the projection coefficient of other on this.
2071         *
2072         * The returned scalar times <tt>this</tt> is the orthogonal projection
2073         * of <tt>other</tt> on <tt>this</tt>.
2074         */
2075        public float project(FloatMatrix other) {
2076            other.checkLength(length);
2077            float norm = 0, dot = 0;
2078            for (int i = 0; i < this.length; i++) {
2079                float x = get(i);
2080                norm += x * x;
2081                dot += x * other.get(i);
2082            }
2083            return dot / norm;
2084        }
2085    
2086        /**
2087         * The Euclidean norm of the matrix as vector, also the Frobenius
2088         * norm of the matrix.
2089         */
2090        public float norm2() {
2091            float norm = 0.0f;
2092            for (int i = 0; i < length; i++) {
2093                norm += get(i) * get(i);
2094            }
2095            return (float) Math.sqrt(norm);
2096        }
2097    
2098        /**
2099         * The maximum norm of the matrix (maximal absolute value of the elements).
2100         */
2101        public float normmax() {
2102            float max = 0.0f;
2103            for (int i = 0; i < length; i++) {
2104                float a = Math.abs(get(i));
2105                if (a > max) {
2106                    max = a;
2107                }
2108            }
2109            return max;
2110        }
2111    
2112        /**
2113         * The 1-norm of the matrix as vector (sum of absolute values of elements).
2114         */
2115        public float norm1() {
2116            float norm = 0.0f;
2117            for (int i = 0; i < length; i++) {
2118                norm += Math.abs(get(i));
2119            }
2120            return norm;
2121        }
2122    
2123        /**
2124         * Returns the squared (Euclidean) distance.
2125         */
2126        public float squaredDistance(FloatMatrix other) {
2127            other.checkLength(length);
2128            float sd = 0.0f;
2129            for (int i = 0; i < length; i++) {
2130                float d = get(i) - other.get(i);
2131                sd += d * d;
2132            }
2133            return sd;
2134        }
2135    
2136        /**
2137         * Returns the (euclidean) distance.
2138         */
2139        public float distance2(FloatMatrix other) {
2140            return (float) Math.sqrt(squaredDistance(other));
2141        }
2142    
2143        /**
2144         * Returns the (1-norm) distance.
2145         */
2146        public float distance1(FloatMatrix other) {
2147            other.checkLength(length);
2148            float d = 0.0f;
2149            for (int i = 0; i < length; i++) {
2150                d += Math.abs(get(i) - other.get(i));
2151            }
2152            return d;
2153        }
2154    
2155        /**
2156         * Return a new matrix with all elements sorted.
2157         */
2158        public FloatMatrix sort() {
2159            float array[] = toArray();
2160            java.util.Arrays.sort(array);
2161            return new FloatMatrix(rows, columns, array);
2162        }
2163    
2164        /**
2165         * Sort elements in-place.
2166         */
2167        public FloatMatrix sorti() {
2168            Arrays.sort(data);
2169            return this;
2170        }
2171    
2172        /**
2173         * Get the sorting permutation.
2174         *
2175         * @return an int[] array such that which indexes the elements in sorted
2176         * order.
2177         */
2178        public int[] sortingPermutation() {
2179            Integer[] indices = new Integer[length];
2180    
2181            for (int i = 0; i < length; i++) {
2182                indices[i] = i;
2183            }
2184    
2185            final float[] array = data;
2186    
2187            Arrays.sort(indices, new Comparator() {
2188    
2189                public int compare(Object o1, Object o2) {
2190                    int i = (Integer) o1;
2191                    int j = (Integer) o2;
2192                    if (array[i] < array[j]) {
2193                        return -1;
2194                    } else if (array[i] == array[j]) {
2195                        return 0;
2196                    } else {
2197                        return 1;
2198                    }
2199                }
2200            });
2201    
2202            int[] result = new int[length];
2203    
2204            for (int i = 0; i < length; i++) {
2205                result[i] = indices[i];
2206            }
2207    
2208            return result;
2209        }
2210    
2211        /**
2212         * Sort columns (in-place).
2213         */
2214        public FloatMatrix sortColumnsi() {
2215            for (int i = 0; i < length; i += rows) {
2216                Arrays.sort(data, i, i + rows);
2217            }
2218            return this;
2219        }
2220    
2221        /** Sort columns. */
2222        public FloatMatrix sortColumns() {
2223            return dup().sortColumnsi();
2224        }
2225    
2226        /** Return matrix of indices which sort all columns. */
2227        public int[][] columnSortingPermutations() {
2228            int[][] result = new int[columns][];
2229    
2230            FloatMatrix temp = new FloatMatrix(rows);
2231            for (int c = 0; c < columns; c++) {
2232                result[c] = getColumn(c, temp).sortingPermutation();
2233            }
2234    
2235            return result;
2236        }
2237    
2238        /** Sort rows (in-place). */
2239        public FloatMatrix sortRowsi() {
2240            // actually, this is much harder because the data is not consecutive
2241            // in memory...
2242            FloatMatrix temp = new FloatMatrix(columns);
2243            for (int r = 0; r < rows; r++) {
2244                putRow(r, getRow(r, temp).sorti());
2245            }
2246            return this;
2247        }
2248    
2249        /** Sort rows. */
2250        public FloatMatrix sortRows() {
2251            return dup().sortRowsi();
2252        }
2253    
2254        /** Return matrix of indices which sort all columns. */
2255        public int[][] rowSortingPermutations() {
2256            int[][] result = new int[rows][];
2257    
2258            FloatMatrix temp = new FloatMatrix(columns);
2259            for (int r = 0; r < rows; r++) {
2260                result[r] = getRow(r, temp).sortingPermutation();
2261            }
2262    
2263            return result;
2264        }
2265    
2266        /** Return a vector containing the sums of the columns (having number of columns many entries) */
2267        public FloatMatrix columnSums() {
2268            if (rows == 1) {
2269                return dup();
2270            } else {
2271                FloatMatrix v = new FloatMatrix(1, columns);
2272    
2273                for (int c = 0; c < columns; c++) {
2274                    for (int r = 0; r < rows; r++) {
2275                        v.put(c, v.get(c) + get(r, c));
2276                    }
2277                }
2278    
2279                return v;
2280            }
2281        }
2282    
2283        /** Return a vector containing the means of all columns. */
2284        public FloatMatrix columnMeans() {
2285            return columnSums().divi(rows);
2286        }
2287    
2288        /** Return a vector containing the sum of the rows. */
2289        public FloatMatrix rowSums() {
2290            if (columns == 1) {
2291                return dup();
2292            } else {
2293                FloatMatrix v = new FloatMatrix(rows);
2294    
2295                for (int c = 0; c < columns; c++) {
2296                    for (int r = 0; r < rows; r++) {
2297                        v.put(r, v.get(r) + get(r, c));
2298                    }
2299                }
2300    
2301                return v;
2302            }
2303        }
2304    
2305        /** Return a vector containing the means of the rows. */
2306        public FloatMatrix rowMeans() {
2307            return rowSums().divi(columns);
2308        }
2309    
2310        /** Get a copy of a column. */
2311        public FloatMatrix getColumn(int c) {
2312            return getColumn(c, new FloatMatrix(rows, 1));
2313        }
2314    
2315        /** Copy a column to the given vector. */
2316        public FloatMatrix getColumn(int c, FloatMatrix result) {
2317            result.checkLength(rows);
2318            JavaBlas.rcopy(rows, data, index(0, c), 1, result.data, 0, 1);
2319            return result;
2320        }
2321    
2322        /** Copy a column back into the matrix. */
2323        public void putColumn(int c, FloatMatrix v) {
2324            JavaBlas.rcopy(rows, v.data, 0, 1, data, index(0, c), 1);
2325        }
2326    
2327        /** Get a copy of a row. */
2328        public FloatMatrix getRow(int r) {
2329            return getRow(r, new FloatMatrix(1, columns));
2330        }
2331    
2332        /** Copy a row to a given vector. */
2333        public FloatMatrix getRow(int r, FloatMatrix result) {
2334            result.checkLength(columns);
2335            JavaBlas.rcopy(columns, data, index(r, 0), rows, result.data, 0, 1);
2336            return result;
2337        }
2338    
2339        /** Copy a row back into the matrix. */
2340        public void putRow(int r, FloatMatrix v) {
2341            JavaBlas.rcopy(columns, v.data, 0, 1, data, index(r, 0), rows);
2342        }
2343    
2344        /** Return column-wise minimums. */
2345        public FloatMatrix columnMins() {
2346            FloatMatrix mins = new FloatMatrix(1, columns);
2347            for (int c = 0; c < columns; c++) {
2348                mins.put(c, getColumn(c).min());
2349            }
2350            return mins;
2351        }
2352    
2353        /** Return index of minimal element per column. */
2354        public int[] columnArgmins() {
2355            int[] argmins = new int[columns];
2356            for (int c = 0; c < columns; c++) {
2357                argmins[c] = getColumn(c).argmin();
2358            }
2359            return argmins;
2360        }
2361    
2362        /** Return column-wise maximums. */
2363        public FloatMatrix columnMaxs() {
2364            FloatMatrix maxs = new FloatMatrix(1, columns);
2365            for (int c = 0; c < columns; c++) {
2366                maxs.put(c, getColumn(c).max());
2367            }
2368            return maxs;
2369        }
2370    
2371        /** Return index of minimal element per column. */
2372        public int[] columnArgmaxs() {
2373            int[] argmaxs = new int[columns];
2374            for (int c = 0; c < columns; c++) {
2375                argmaxs[c] = getColumn(c).argmax();
2376            }
2377            return argmaxs;
2378        }
2379    
2380        /** Return row-wise minimums. */
2381        public FloatMatrix rowMins() {
2382            FloatMatrix mins = new FloatMatrix(rows);
2383            for (int c = 0; c < rows; c++) {
2384                mins.put(c, getRow(c).min());
2385            }
2386            return mins;
2387        }
2388    
2389        /** Return index of minimal element per row. */
2390        public int[] rowArgmins() {
2391            int[] argmins = new int[rows];
2392            for (int c = 0; c < rows; c++) {
2393                argmins[c] = getRow(c).argmin();
2394            }
2395            return argmins;
2396        }
2397    
2398        /** Return row-wise maximums. */
2399        public FloatMatrix rowMaxs() {
2400            FloatMatrix maxs = new FloatMatrix(rows);
2401            for (int c = 0; c < rows; c++) {
2402                maxs.put(c, getRow(c).max());
2403            }
2404            return maxs;
2405        }
2406    
2407        /** Return index of minimal element per row. */
2408        public int[] rowArgmaxs() {
2409            int[] argmaxs = new int[rows];
2410            for (int c = 0; c < rows; c++) {
2411                argmaxs[c] = getRow(c).argmax();
2412            }
2413            return argmaxs;
2414        }
2415    
2416        /**************************************************************************
2417         * Elementwise Functions
2418         */
2419        /** Add a row vector to all rows of the matrix (in place). */
2420        public FloatMatrix addiRowVector(FloatMatrix x) {
2421            x.checkLength(columns);
2422            for (int c = 0; c < columns; c++) {
2423                for (int r = 0; r < rows; r++) {
2424                    put(r, c, get(r, c) + x.get(c));
2425                }
2426            }
2427            return this;
2428        }
2429    
2430        /** Add a row to all rows of the matrix. */
2431        public FloatMatrix addRowVector(FloatMatrix x) {
2432            return dup().addiRowVector(x);
2433        }
2434    
2435        /** Add a vector to all columns of the matrix (in-place). */
2436        public FloatMatrix addiColumnVector(FloatMatrix x) {
2437            x.checkLength(rows);
2438            for (int c = 0; c < columns; c++) {
2439                for (int r = 0; r < rows; r++) {
2440                    put(r, c, get(r, c) + x.get(r));
2441                }
2442            }
2443            return this;
2444        }
2445    
2446        /** Add a vector to all columns of the matrix. */
2447        public FloatMatrix addColumnVector(FloatMatrix x) {
2448            return dup().addiColumnVector(x);
2449        }
2450    
2451        /** Subtract a row vector from all rows of the matrix (in-place). */
2452        public FloatMatrix subiRowVector(FloatMatrix x) {
2453            // This is a bit crazy, but a row vector must have as length as the columns of the matrix.
2454            x.checkLength(columns);
2455            for (int c = 0; c < columns; c++) {
2456                for (int r = 0; r < rows; r++) {
2457                    put(r, c, get(r, c) - x.get(c));
2458                }
2459            }
2460            return this;
2461        }
2462    
2463        /** Subtract a row vector from all rows of the matrix. */
2464        public FloatMatrix subRowVector(FloatMatrix x) {
2465            return dup().subiRowVector(x);
2466        }
2467    
2468        /** Subtract a column vector from all columns of the matrix (in-place). */
2469        public FloatMatrix subiColumnVector(FloatMatrix x) {
2470            x.checkLength(rows);
2471            for (int c = 0; c < columns; c++) {
2472                for (int r = 0; r < rows; r++) {
2473                    put(r, c, get(r, c) - x.get(r));
2474                }
2475            }
2476            return this;
2477        }
2478    
2479        /** Subtract a vector from all columns of the matrix. */
2480        public FloatMatrix subColumnVector(FloatMatrix x) {
2481            return dup().subiColumnVector(x);
2482        }
2483    
2484        /** Multiply a row by a scalar. */
2485        public FloatMatrix mulRow(int r, float scale) {
2486            NativeBlas.sscal(columns, scale, data, index(r, 0), rows);
2487            return this;
2488        }
2489    
2490        /** Multiply a column by a scalar. */
2491        public FloatMatrix mulColumn(int c, float scale) {
2492            NativeBlas.sscal(rows, scale, data, index(0, c), 1);
2493            return this;
2494        }
2495    
2496        /** Multiply all columns with a column vector (in-place). */
2497        public FloatMatrix muliColumnVector(FloatMatrix x) {
2498            x.checkLength(rows);
2499            for (int c = 0; c < columns; c++) {
2500                for (int r = 0; r < rows; r++) {
2501                    put(r, c, get(r, c) * x.get(r));
2502                }
2503            }
2504            return this;
2505        }
2506    
2507        /** Multiply all columns with a column vector. */
2508        public FloatMatrix mulColumnVector(FloatMatrix x) {
2509            return dup().muliColumnVector(x);
2510        }
2511    
2512        /** Multiply all rows with a row vector (in-place). */
2513        public FloatMatrix muliRowVector(FloatMatrix x) {
2514            x.checkLength(columns);
2515            for (int c = 0; c < columns; c++) {
2516                for (int r = 0; r < rows; r++) {
2517                    put(r, c, get(r, c) * x.get(c));
2518                }
2519            }
2520            return this;
2521        }
2522    
2523        /** Multiply all rows with a row vector. */
2524        public FloatMatrix mulRowVector(FloatMatrix x) {
2525            return dup().muliRowVector(x);
2526        }
2527    
2528        public FloatMatrix diviRowVector(FloatMatrix x) {
2529            x.checkLength(columns);
2530            for (int c = 0; c < columns; c++) {
2531                for (int r = 0; r < rows; r++) {
2532                    put(r, c, get(r, c) / x.get(c));
2533                }
2534            }
2535            return this;
2536        }
2537    
2538        public FloatMatrix divRowVector(FloatMatrix x) {
2539            return dup().diviRowVector(x);
2540        }
2541    
2542        public FloatMatrix diviColumnVector(FloatMatrix x) {
2543            x.checkLength(rows);
2544            for (int c = 0; c < columns; c++) {
2545                for (int r = 0; r < rows; r++) {
2546                    put(r, c, get(r, c) / x.get(r));
2547                }
2548            }
2549            return this;
2550        }
2551    
2552        public FloatMatrix divColumnVector(FloatMatrix x) {
2553            return dup().diviColumnVector(x);
2554        }
2555    
2556        /**
2557         * Writes out this matrix to the given data stream.
2558         * @param dos the data output stream to write to.
2559         * @throws IOException
2560         */
2561        public void out(DataOutputStream dos) throws IOException {
2562            dos.writeUTF("float");
2563            dos.writeInt(columns);
2564            dos.writeInt(rows);
2565    
2566            dos.writeInt(data.length);
2567            for (int i = 0; i < data.length; i++) {
2568                dos.writeDouble(data[i]);
2569            }
2570        }
2571    
2572        /**
2573         * Reads in a matrix from the given data stream. Note
2574         * that the old data of this matrix will be discarded.
2575         * @param dis the data input stream to read from.
2576         * @throws IOException
2577         */
2578        public void in(DataInputStream dis) throws IOException {
2579            if (!dis.readUTF().equals("float")) {
2580                throw new IllegalStateException("The matrix in the specified file is not of the correct type!");
2581            }
2582    
2583            this.columns = dis.readInt();
2584            this.rows = dis.readInt();
2585    
2586            final int MAX = dis.readInt();
2587            data = new float[MAX];
2588            for (int i = 0; i < MAX; i++) {
2589                data[i] = dis.readFloat();
2590            }
2591        }
2592    
2593        /**
2594         * Saves this matrix to the specified file.
2595         * @param filename the file to write the matrix in.
2596         * @throws IOException thrown on errors while writing the matrix to the file
2597         */
2598        public void save(String filename) throws IOException {
2599            DataOutputStream dos = new DataOutputStream(new FileOutputStream(filename, false));
2600            this.out(dos);
2601        }
2602    
2603        /**
2604         * Loads a matrix from a file into this matrix. Note that the old data
2605         * of this matrix will be discarded.
2606         * @param filename the file to read the matrix from
2607         * @throws IOException thrown on errors while reading the matrix
2608         */
2609        public void load(String filename) throws IOException {
2610            DataInputStream dis = new DataInputStream(new FileInputStream(filename));
2611            this.in(dis);
2612        }
2613    
2614        public static FloatMatrix loadAsciiFile(String filename) throws IOException {
2615            BufferedReader is = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
2616    
2617            // Go through file and count columns and rows. What makes this endeavour a bit difficult is
2618            // that files can have leading or trailing spaces leading to spurious fields
2619            // after String.split().
2620            String line;
2621            int rows = 0;
2622            int columns = -1;
2623            while ((line = is.readLine()) != null) {
2624                String[] elements = line.split("\\s+");
2625                int numElements = elements.length;
2626                if (elements[0].length() == 0) {
2627                    numElements--;
2628                }
2629                if (elements[elements.length - 1].length() == 0) {
2630                    numElements--;
2631                }
2632    
2633                if (columns == -1) {
2634                    columns = numElements;
2635                } else {
2636                    if (columns != numElements) {
2637                        throw new IOException("Number of elements changes in line " + line + ".");
2638                    }
2639                }
2640    
2641                rows++;
2642            }
2643            is.close();
2644    
2645            // Go through file a second time process the actual data.
2646            is = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
2647            FloatMatrix result = new FloatMatrix(rows, columns);
2648            int r = 0;
2649            while ((line = is.readLine()) != null) {
2650                String[] elements = line.split("\\s+");
2651                int firstElement = (elements[0].length() == 0) ? 1 : 0;
2652                for (int c = 0, cc = firstElement; c < columns; c++, cc++) {
2653                    result.put(r, c, Float.valueOf(elements[cc]));
2654                }
2655                r++;
2656            }
2657            return result;
2658        }
2659    
2660        public static FloatMatrix loadCSVFile(String filename) throws IOException {
2661            BufferedReader is = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
2662    
2663            List<FloatMatrix> rows = new LinkedList<FloatMatrix>();
2664            String line;
2665            int columns = -1;
2666            while ((line = is.readLine()) != null) {
2667                String[] elements = line.split(",");
2668                int numElements = elements.length;
2669                if (elements[0].length() == 0) {
2670                    numElements--;
2671                }
2672                if (elements[elements.length - 1].length() == 0) {
2673                    numElements--;
2674                }
2675    
2676                if (columns == -1) {
2677                    columns = numElements;
2678                } else {
2679                    if (columns != numElements) {
2680                        throw new IOException("Number of elements changes in line " + line + ".");
2681                    }
2682                }
2683    
2684                FloatMatrix row = new FloatMatrix(columns);
2685                for (int c = 0; c < columns; c++) {
2686                    row.put(c, Float.valueOf(elements[c]));
2687                }
2688                rows.add(row);
2689            }
2690            is.close();
2691    
2692            System.out.println("Done reading file");
2693    
2694            FloatMatrix result = new FloatMatrix(rows.size(), columns);
2695            int r = 0;
2696            Iterator<FloatMatrix> ri = rows.iterator();
2697            while (ri.hasNext()) {
2698                result.putRow(r, ri.next());
2699                r++;
2700            }
2701            return result;
2702        }
2703    
2704        /****************************************************************
2705         * Autogenerated code
2706         */
2707        /***** Code for operators ***************************************/
2708    
2709        /* Overloads for the usual arithmetic operations */
2710        /*#
2711        def gen_overloads(base, result_rows, result_cols, verb=''); <<-EOS
2712        #{doc verb.capitalize + " a matrix (in place)."}
2713        public FloatMatrix #{base}i(FloatMatrix other) {
2714        return #{base}i(other, this);
2715        }
2716    
2717        #{doc verb.capitalize + " a matrix (in place)."}
2718        public FloatMatrix #{base}(FloatMatrix other) {
2719        return #{base}i(other, new FloatMatrix(#{result_rows}, #{result_cols}));
2720        }
2721    
2722        #{doc verb.capitalize + " a scalar (in place)."}
2723        public FloatMatrix #{base}i(float v) {
2724        return #{base}i(v, this);
2725        }
2726    
2727        #{doc verb.capitalize + " a scalar."}
2728        public FloatMatrix #{base}(float v) {
2729        return #{base}i(v, new FloatMatrix(rows, columns));
2730        }
2731        EOS
2732        end
2733        #*/
2734    
2735        /* Generating code for logical operators. This not only generates the stubs
2736         * but really all of the code.
2737         */
2738        /*#
2739        def gen_compare(name, op, cmp); <<-EOS
2740        #{doc 'Test for ' + cmp + ' (in-place).'}
2741        public FloatMatrix #{name}i(FloatMatrix other, FloatMatrix result) {
2742        if (other.isScalar())
2743        return #{name}i(other.scalar(), result);
2744    
2745        assertSameLength(other);
2746        ensureResultLength(other, result);
2747    
2748        for (int i = 0; i < length; i++)
2749        result.put(i, get(i) #{op} other.get(i) ? 1.0f : 0.0f);
2750        return result;
2751        }
2752    
2753        #{doc 'Test for ' + cmp + ' (in-place).'}
2754        public FloatMatrix #{name}i(FloatMatrix other) {
2755        return #{name}i(other, this);
2756        }
2757    
2758        #{doc 'Test for ' + cmp + '.'}
2759        public FloatMatrix #{name}(FloatMatrix other) {
2760        return #{name}i(other, new FloatMatrix(rows, columns));
2761        }
2762    
2763        #{doc 'Test for ' + cmp + ' against a scalar (in-place).'}
2764        public FloatMatrix #{name}i(float value, FloatMatrix result) {
2765        ensureResultLength(null, result);
2766        for (int i = 0; i < length; i++)
2767        result.put(i, get(i) #{op} value ? 1.0f : 0.0f);
2768        return result;
2769        }
2770    
2771        #{doc 'Test for ' + cmp + ' against a scalar (in-place).'}
2772        public FloatMatrix #{name}i(float value) {
2773        return #{name}i(value, this);
2774        }
2775    
2776        #{doc 'test for ' + cmp + ' against a scalar.'}
2777        public FloatMatrix #{name}(float value) {
2778        return #{name}i(value, new FloatMatrix(rows, columns));
2779        }
2780        EOS
2781        end
2782        #*/
2783        /*#
2784        def gen_logical(name, op, cmp); <<-EOS
2785        #{doc 'Compute elementwise ' + cmp + ' (in-place).'}
2786        public FloatMatrix #{name}i(FloatMatrix other, FloatMatrix result) {
2787        assertSameLength(other);
2788        ensureResultLength(other, result);
2789    
2790        for (int i = 0; i < length; i++)
2791        result.put(i, (get(i) != 0.0f) #{op} (other.get(i) != 0.0f) ? 1.0f : 0.0f);
2792        return result;
2793        }
2794    
2795        #{doc 'Compute elementwise ' + cmp + ' (in-place).'}
2796        public FloatMatrix #{name}i(FloatMatrix other) {
2797        return #{name}i(other, this);
2798        }
2799    
2800        #{doc 'Compute elementwise ' + cmp + '.'}
2801        public FloatMatrix #{name}(FloatMatrix other) {
2802        return #{name}i(other, new FloatMatrix(rows, columns));
2803        }
2804    
2805        #{doc 'Compute elementwise ' + cmp + ' against a scalar (in-place).'}
2806        public FloatMatrix #{name}i(float value, FloatMatrix result) {
2807        ensureResultLength(null, result);
2808        boolean val = (value != 0.0f);
2809        for (int i = 0; i < length; i++)
2810        result.put(i, (get(i) != 0.0f) #{op} val ? 1.0f : 0.0f);
2811        return result;
2812        }
2813    
2814        #{doc 'Compute elementwise ' + cmp + ' against a scalar (in-place).'}
2815        public FloatMatrix #{name}i(float value) {
2816        return #{name}i(value, this);
2817        }
2818    
2819        #{doc 'Compute elementwise ' + cmp + ' against a scalar.'}
2820        public FloatMatrix #{name}(float value) {
2821        return #{name}i(value, new FloatMatrix(rows, columns));
2822        }
2823        EOS
2824        end
2825        #*/
2826    
2827        /*# collect(gen_overloads('add', 'rows', 'columns', 'add'),
2828        gen_overloads('sub', 'rows', 'columns', 'subtract'),
2829        gen_overloads('rsub', 'rows', 'columns', '(right-)subtract'),
2830        gen_overloads('div', 'rows', 'columns', 'elementwise divide by'),
2831        gen_overloads('rdiv', 'rows', 'columns', '(right-)elementwise divide by'),
2832        gen_overloads('mul', 'rows', 'columns', 'elementwise multiply by'),
2833        gen_overloads('mmul', 'rows', 'other.columns', 'matrix-multiply by'),
2834        gen_compare('lt', '<', '"less than"'),
2835        gen_compare('gt', '>', '"greater than"'),
2836        gen_compare('le', '<=', '"less than or equal"'),
2837        gen_compare('ge', '>=', '"greater than or equal"'),
2838        gen_compare('eq', '==', 'equality'),
2839        gen_compare('ne', '!=', 'inequality'),
2840        gen_logical('and', '&', 'logical and'),
2841        gen_logical('or', '|', 'logical or'),
2842        gen_logical('xor', '^', 'logical xor'))
2843        #*/
2844    //RJPP-BEGIN------------------------------------------------------------
2845        /** Add a matrix (in place). */
2846        public FloatMatrix addi(FloatMatrix other) {
2847        return addi(other, this);
2848        }
2849    
2850        /** Add a matrix (in place). */
2851        public FloatMatrix add(FloatMatrix other) {
2852        return addi(other, new FloatMatrix(rows, columns));
2853        }
2854    
2855        /** Add a scalar (in place). */
2856        public FloatMatrix addi(float v) {
2857        return addi(v, this);
2858        }
2859    
2860        /** Add a scalar. */
2861        public FloatMatrix add(float v) {
2862        return addi(v, new FloatMatrix(rows, columns));
2863        }
2864    
2865        /** Subtract a matrix (in place). */
2866        public FloatMatrix subi(FloatMatrix other) {
2867        return subi(other, this);
2868        }
2869    
2870        /** Subtract a matrix (in place). */
2871        public FloatMatrix sub(FloatMatrix other) {
2872        return subi(other, new FloatMatrix(rows, columns));
2873        }
2874    
2875        /** Subtract a scalar (in place). */
2876        public FloatMatrix subi(float v) {
2877        return subi(v, this);
2878        }
2879    
2880        /** Subtract a scalar. */
2881        public FloatMatrix sub(float v) {
2882        return subi(v, new FloatMatrix(rows, columns));
2883        }
2884    
2885        /** (right-)subtract a matrix (in place). */
2886        public FloatMatrix rsubi(FloatMatrix other) {
2887        return rsubi(other, this);
2888        }
2889    
2890        /** (right-)subtract a matrix (in place). */
2891        public FloatMatrix rsub(FloatMatrix other) {
2892        return rsubi(other, new FloatMatrix(rows, columns));
2893        }
2894    
2895        /** (right-)subtract a scalar (in place). */
2896        public FloatMatrix rsubi(float v) {
2897        return rsubi(v, this);
2898        }
2899    
2900        /** (right-)subtract a scalar. */
2901        public FloatMatrix rsub(float v) {
2902        return rsubi(v, new FloatMatrix(rows, columns));
2903        }
2904    
2905        /** Elementwise divide by a matrix (in place). */
2906        public FloatMatrix divi(FloatMatrix other) {
2907        return divi(other, this);
2908        }
2909    
2910        /** Elementwise divide by a matrix (in place). */
2911        public FloatMatrix div(FloatMatrix other) {
2912        return divi(other, new FloatMatrix(rows, columns));
2913        }
2914    
2915        /** Elementwise divide by a scalar (in place). */
2916        public FloatMatrix divi(float v) {
2917        return divi(v, this);
2918        }
2919    
2920        /** Elementwise divide by a scalar. */
2921        public FloatMatrix div(float v) {
2922        return divi(v, new FloatMatrix(rows, columns));
2923        }
2924    
2925        /** (right-)elementwise divide by a matrix (in place). */
2926        public FloatMatrix rdivi(FloatMatrix other) {
2927        return rdivi(other, this);
2928        }
2929    
2930        /** (right-)elementwise divide by a matrix (in place). */
2931        public FloatMatrix rdiv(FloatMatrix other) {
2932        return rdivi(other, new FloatMatrix(rows, columns));
2933        }
2934    
2935        /** (right-)elementwise divide by a scalar (in place). */
2936        public FloatMatrix rdivi(float v) {
2937        return rdivi(v, this);
2938        }
2939    
2940        /** (right-)elementwise divide by a scalar. */
2941        public FloatMatrix rdiv(float v) {
2942        return rdivi(v, new FloatMatrix(rows, columns));
2943        }
2944    
2945        /** Elementwise multiply by a matrix (in place). */
2946        public FloatMatrix muli(FloatMatrix other) {
2947        return muli(other, this);
2948        }
2949    
2950        /** Elementwise multiply by a matrix (in place). */
2951        public FloatMatrix mul(FloatMatrix other) {
2952        return muli(other, new FloatMatrix(rows, columns));
2953        }
2954    
2955        /** Elementwise multiply by a scalar (in place). */
2956        public FloatMatrix muli(float v) {
2957        return muli(v, this);
2958        }
2959    
2960        /** Elementwise multiply by a scalar. */
2961        public FloatMatrix mul(float v) {
2962        return muli(v, new FloatMatrix(rows, columns));
2963        }
2964    
2965        /** Matrix-multiply by a matrix (in place). */
2966        public FloatMatrix mmuli(FloatMatrix other) {
2967        return mmuli(other, this);
2968        }
2969    
2970        /** Matrix-multiply by a matrix (in place). */
2971        public FloatMatrix mmul(FloatMatrix other) {
2972        return mmuli(other, new FloatMatrix(rows, other.columns));
2973        }
2974    
2975        /** Matrix-multiply by a scalar (in place). */
2976        public FloatMatrix mmuli(float v) {
2977        return mmuli(v, this);
2978        }
2979    
2980        /** Matrix-multiply by a scalar. */
2981        public FloatMatrix mmul(float v) {
2982        return mmuli(v, new FloatMatrix(rows, columns));
2983        }
2984    
2985        /** Test for "less than" (in-place). */
2986        public FloatMatrix lti(FloatMatrix other, FloatMatrix result) {
2987        if (other.isScalar())
2988        return lti(other.scalar(), result);
2989    
2990        assertSameLength(other);
2991        ensureResultLength(other, result);
2992    
2993        for (int i = 0; i < length; i++)
2994        result.put(i, get(i) < other.get(i) ? 1.0f : 0.0f);
2995        return result;
2996        }
2997    
2998        /** Test for "less than" (in-place). */
2999        public FloatMatrix lti(FloatMatrix other) {
3000        return lti(other, this);
3001        }
3002    
3003        /** Test for "less than". */
3004        public FloatMatrix lt(FloatMatrix other) {
3005        return lti(other, new FloatMatrix(rows, columns));
3006        }
3007    
3008        /** Test for "less than" against a scalar (in-place). */
3009        public FloatMatrix lti(float value, FloatMatrix result) {
3010        ensureResultLength(null, result);
3011        for (int i = 0; i < length; i++)
3012        result.put(i, get(i) < value ? 1.0f : 0.0f);
3013        return result;
3014        }
3015    
3016        /** Test for "less than" against a scalar (in-place). */
3017        public FloatMatrix lti(float value) {
3018        return lti(value, this);
3019        }
3020    
3021        /** test for "less than" against a scalar. */
3022        public FloatMatrix lt(float value) {
3023        return lti(value, new FloatMatrix(rows, columns));
3024        }
3025    
3026        /** Test for "greater than" (in-place). */
3027        public FloatMatrix gti(FloatMatrix other, FloatMatrix result) {
3028        if (other.isScalar())
3029        return gti(other.scalar(), result);
3030    
3031        assertSameLength(other);
3032        ensureResultLength(other, result);
3033    
3034        for (int i = 0; i < length; i++)
3035        result.put(i, get(i) > other.get(i) ? 1.0f : 0.0f);
3036        return result;
3037        }
3038    
3039        /** Test for "greater than" (in-place). */
3040        public FloatMatrix gti(FloatMatrix other) {
3041        return gti(other, this);
3042        }
3043    
3044        /** Test for "greater than". */
3045        public FloatMatrix gt(FloatMatrix other) {
3046        return gti(other, new FloatMatrix(rows, columns));
3047        }
3048    
3049        /** Test for "greater than" against a scalar (in-place). */
3050        public FloatMatrix gti(float value, FloatMatrix result) {
3051        ensureResultLength(null, result);
3052        for (int i = 0; i < length; i++)
3053        result.put(i, get(i) > value ? 1.0f : 0.0f);
3054        return result;
3055        }
3056    
3057        /** Test for "greater than" against a scalar (in-place). */
3058        public FloatMatrix gti(float value) {
3059        return gti(value, this);
3060        }
3061    
3062        /** test for "greater than" against a scalar. */
3063        public FloatMatrix gt(float value) {
3064        return gti(value, new FloatMatrix(rows, columns));
3065        }
3066    
3067        /** Test for "less than or equal" (in-place). */
3068        public FloatMatrix lei(FloatMatrix other, FloatMatrix result) {
3069        if (other.isScalar())
3070        return lei(other.scalar(), result);
3071    
3072        assertSameLength(other);
3073        ensureResultLength(other, result);
3074    
3075        for (int i = 0; i < length; i++)
3076        result.put(i, get(i) <= other.get(i) ? 1.0f : 0.0f);
3077        return result;
3078        }
3079    
3080        /** Test for "less than or equal" (in-place). */
3081        public FloatMatrix lei(FloatMatrix other) {
3082        return lei(other, this);
3083        }
3084    
3085        /** Test for "less than or equal". */
3086        public FloatMatrix le(FloatMatrix other) {
3087        return lei(other, new FloatMatrix(rows, columns));
3088        }
3089    
3090        /** Test for "less than or equal" against a scalar (in-place). */
3091        public FloatMatrix lei(float value, FloatMatrix result) {
3092        ensureResultLength(null, result);
3093        for (int i = 0; i < length; i++)
3094        result.put(i, get(i) <= value ? 1.0f : 0.0f);
3095        return result;
3096        }
3097    
3098        /** Test for "less than or equal" against a scalar (in-place). */
3099        public FloatMatrix lei(float value) {
3100        return lei(value, this);
3101        }
3102    
3103        /** test for "less than or equal" against a scalar. */
3104        public FloatMatrix le(float value) {
3105        return lei(value, new FloatMatrix(rows, columns));
3106        }
3107    
3108        /** Test for "greater than or equal" (in-place). */
3109        public FloatMatrix gei(FloatMatrix other, FloatMatrix result) {
3110        if (other.isScalar())
3111        return gei(other.scalar(), result);
3112    
3113        assertSameLength(other);
3114        ensureResultLength(other, result);
3115    
3116        for (int i = 0; i < length; i++)
3117        result.put(i, get(i) >= other.get(i) ? 1.0f : 0.0f);
3118        return result;
3119        }
3120    
3121        /** Test for "greater than or equal" (in-place). */
3122        public FloatMatrix gei(FloatMatrix other) {
3123        return gei(other, this);
3124        }
3125    
3126        /** Test for "greater than or equal". */
3127        public FloatMatrix ge(FloatMatrix other) {
3128        return gei(other, new FloatMatrix(rows, columns));
3129        }
3130    
3131        /** Test for "greater than or equal" against a scalar (in-place). */
3132        public FloatMatrix gei(float value, FloatMatrix result) {
3133        ensureResultLength(null, result);
3134        for (int i = 0; i < length; i++)
3135        result.put(i, get(i) >= value ? 1.0f : 0.0f);
3136        return result;
3137        }
3138    
3139        /** Test for "greater than or equal" against a scalar (in-place). */
3140        public FloatMatrix gei(float value) {
3141        return gei(value, this);
3142        }
3143    
3144        /** test for "greater than or equal" against a scalar. */
3145        public FloatMatrix ge(float value) {
3146        return gei(value, new FloatMatrix(rows, columns));
3147        }
3148    
3149        /** Test for equality (in-place). */
3150        public FloatMatrix eqi(FloatMatrix other, FloatMatrix result) {
3151        if (other.isScalar())
3152        return eqi(other.scalar(), result);
3153    
3154        assertSameLength(other);
3155        ensureResultLength(other, result);
3156    
3157        for (int i = 0; i < length; i++)
3158        result.put(i, get(i) == other.get(i) ? 1.0f : 0.0f);
3159        return result;
3160        }
3161    
3162        /** Test for equality (in-place). */
3163        public FloatMatrix eqi(FloatMatrix other) {
3164        return eqi(other, this);
3165        }
3166    
3167        /** Test for equality. */
3168        public FloatMatrix eq(FloatMatrix other) {
3169        return eqi(other, new FloatMatrix(rows, columns));
3170        }
3171    
3172        /** Test for equality against a scalar (in-place). */
3173        public FloatMatrix eqi(float value, FloatMatrix result) {
3174        ensureResultLength(null, result);
3175        for (int i = 0; i < length; i++)
3176        result.put(i, get(i) == value ? 1.0f : 0.0f);
3177        return result;
3178        }
3179    
3180        /** Test for equality against a scalar (in-place). */
3181        public FloatMatrix eqi(float value) {
3182        return eqi(value, this);
3183        }
3184    
3185        /** test for equality against a scalar. */
3186        public FloatMatrix eq(float value) {
3187        return eqi(value, new FloatMatrix(rows, columns));
3188        }
3189    
3190        /** Test for inequality (in-place). */
3191        public FloatMatrix nei(FloatMatrix other, FloatMatrix result) {
3192        if (other.isScalar())
3193        return nei(other.scalar(), result);
3194    
3195        assertSameLength(other);
3196        ensureResultLength(other, result);
3197    
3198        for (int i = 0; i < length; i++)
3199        result.put(i, get(i) != other.get(i) ? 1.0f : 0.0f);
3200        return result;
3201        }
3202    
3203        /** Test for inequality (in-place). */
3204        public FloatMatrix nei(FloatMatrix other) {
3205        return nei(other, this);
3206        }
3207    
3208        /** Test for inequality. */
3209        public FloatMatrix ne(FloatMatrix other) {
3210        return nei(other, new FloatMatrix(rows, columns));
3211        }
3212    
3213        /** Test for inequality against a scalar (in-place). */
3214        public FloatMatrix nei(float value, FloatMatrix result) {
3215        ensureResultLength(null, result);
3216        for (int i = 0; i < length; i++)
3217        result.put(i, get(i) != value ? 1.0f : 0.0f);
3218        return result;
3219        }
3220    
3221        /** Test for inequality against a scalar (in-place). */
3222        public FloatMatrix nei(float value) {
3223        return nei(value, this);
3224        }
3225    
3226        /** test for inequality against a scalar. */
3227        public FloatMatrix ne(float value) {
3228        return nei(value, new FloatMatrix(rows, columns));
3229        }
3230    
3231        /** Compute elementwise logical and (in-place). */
3232        public FloatMatrix andi(FloatMatrix other, FloatMatrix result) {
3233        assertSameLength(other);
3234        ensureResultLength(other, result);
3235    
3236        for (int i = 0; i < length; i++)
3237        result.put(i, (get(i) != 0.0f) & (other.get(i) != 0.0f) ? 1.0f : 0.0f);
3238        return result;
3239        }
3240    
3241        /** Compute elementwise logical and (in-place). */
3242        public FloatMatrix andi(FloatMatrix other) {
3243        return andi(other, this);
3244        }
3245    
3246        /** Compute elementwise logical and. */
3247        public FloatMatrix and(FloatMatrix other) {
3248        return andi(other, new FloatMatrix(rows, columns));
3249        }
3250    
3251        /** Compute elementwise logical and against a scalar (in-place). */
3252        public FloatMatrix andi(float value, FloatMatrix result) {
3253        ensureResultLength(null, result);
3254        boolean val = (value != 0.0f);
3255        for (int i = 0; i < length; i++)
3256        result.put(i, (get(i) != 0.0f) & val ? 1.0f : 0.0f);
3257        return result;
3258        }
3259    
3260        /** Compute elementwise logical and against a scalar (in-place). */
3261        public FloatMatrix andi(float value) {
3262        return andi(value, this);
3263        }
3264    
3265        /** Compute elementwise logical and against a scalar. */
3266        public FloatMatrix and(float value) {
3267        return andi(value, new FloatMatrix(rows, columns));
3268        }
3269    
3270        /** Compute elementwise logical or (in-place). */
3271        public FloatMatrix ori(FloatMatrix other, FloatMatrix result) {
3272        assertSameLength(other);
3273        ensureResultLength(other, result);
3274    
3275        for (int i = 0; i < length; i++)
3276        result.put(i, (get(i) != 0.0f) | (other.get(i) != 0.0f) ? 1.0f : 0.0f);
3277        return result;
3278        }
3279    
3280        /** Compute elementwise logical or (in-place). */
3281        public FloatMatrix ori(FloatMatrix other) {
3282        return ori(other, this);
3283        }
3284    
3285        /** Compute elementwise logical or. */
3286        public FloatMatrix or(FloatMatrix other) {
3287        return ori(other, new FloatMatrix(rows, columns));
3288        }
3289    
3290        /** Compute elementwise logical or against a scalar (in-place). */
3291        public FloatMatrix ori(float value, FloatMatrix result) {
3292        ensureResultLength(null, result);
3293        boolean val = (value != 0.0f);
3294        for (int i = 0; i < length; i++)
3295        result.put(i, (get(i) != 0.0f) | val ? 1.0f : 0.0f);
3296        return result;
3297        }
3298    
3299        /** Compute elementwise logical or against a scalar (in-place). */
3300        public FloatMatrix ori(float value) {
3301        return ori(value, this);
3302        }
3303    
3304        /** Compute elementwise logical or against a scalar. */
3305        public FloatMatrix or(float value) {
3306        return ori(value, new FloatMatrix(rows, columns));
3307        }
3308    
3309        /** Compute elementwise logical xor (in-place). */
3310        public FloatMatrix xori(FloatMatrix other, FloatMatrix result) {
3311        assertSameLength(other);
3312        ensureResultLength(other, result);
3313    
3314        for (int i = 0; i < length; i++)
3315        result.put(i, (get(i) != 0.0f) ^ (other.get(i) != 0.0f) ? 1.0f : 0.0f);
3316        return result;
3317        }
3318    
3319        /** Compute elementwise logical xor (in-place). */
3320        public FloatMatrix xori(FloatMatrix other) {
3321        return xori(other, this);
3322        }
3323    
3324        /** Compute elementwise logical xor. */
3325        public FloatMatrix xor(FloatMatrix other) {
3326        return xori(other, new FloatMatrix(rows, columns));
3327        }
3328    
3329        /** Compute elementwise logical xor against a scalar (in-place). */
3330        public FloatMatrix xori(float value, FloatMatrix result) {
3331        ensureResultLength(null, result);
3332        boolean val = (value != 0.0f);
3333        for (int i = 0; i < length; i++)
3334        result.put(i, (get(i) != 0.0f) ^ val ? 1.0f : 0.0f);
3335        return result;
3336        }
3337    
3338        /** Compute elementwise logical xor against a scalar (in-place). */
3339        public FloatMatrix xori(float value) {
3340        return xori(value, this);
3341        }
3342    
3343        /** Compute elementwise logical xor against a scalar. */
3344        public FloatMatrix xor(float value) {
3345        return xori(value, new FloatMatrix(rows, columns));
3346        }
3347    //RJPP-END--------------------------------------------------------------
3348    }