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