View Javadoc
1   package org.opentrafficsim.core.value.vfloat.matrix;
2   
3   import java.io.Serializable;
4   
5   import org.opentrafficsim.core.unit.SICoefficients;
6   import org.opentrafficsim.core.unit.SIUnit;
7   import org.opentrafficsim.core.unit.Unit;
8   import org.opentrafficsim.core.value.Absolute;
9   import org.opentrafficsim.core.value.AbstractValue;
10  import org.opentrafficsim.core.value.DenseData;
11  import org.opentrafficsim.core.value.Format;
12  import org.opentrafficsim.core.value.Relative;
13  import org.opentrafficsim.core.value.SparseData;
14  import org.opentrafficsim.core.value.ValueException;
15  import org.opentrafficsim.core.value.ValueUtil;
16  import org.opentrafficsim.core.value.vfloat.scalar.FloatScalar;
17  import org.opentrafficsim.core.value.vfloat.vector.FloatVector;
18  
19  import cern.colt.matrix.tfloat.FloatMatrix1D;
20  import cern.colt.matrix.tfloat.FloatMatrix2D;
21  import cern.colt.matrix.tfloat.algo.DenseFloatAlgebra;
22  import cern.colt.matrix.tfloat.algo.SparseFloatAlgebra;
23  import cern.colt.matrix.tfloat.impl.DenseFloatMatrix1D;
24  import cern.colt.matrix.tfloat.impl.DenseFloatMatrix2D;
25  import cern.colt.matrix.tfloat.impl.SparseFloatMatrix1D;
26  import cern.colt.matrix.tfloat.impl.SparseFloatMatrix2D;
27  
28  /**
29   * Immutable FloatMatrix.
30   * <p>
31   * This file was generated by the OpenTrafficSim value classes generator, 09 mrt, 2015
32   * <p>
33   * Copyright (c) 2014 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
34   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
35   * <p>
36   * @version 09 mrt, 2015 <br>
37   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
38   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
39   * @param <U> Unit; the unit of this FloatMatrix
40   */
41  public abstract class FloatMatrix<U extends Unit<U>> extends AbstractValue<U> implements
42          Serializable,
43      ReadOnlyFloatMatrixFunctions<U>
44  {
45      /**  */
46      private static final long serialVersionUID = 20150309L;
47  
48      /** 
49       * The internal storage for the matrix; internally the values are stored in standard SI unit; storage can be dense
50       * or sparse.
51       */
52      private FloatMatrix2D matrixSI;
53  
54      /**
55       * Construct a new Immutable FloatMatrix.
56       * @param unit U; the unit of the new FloatMatrix
57       */
58      protected  FloatMatrix(final U unit)
59      {
60          super(unit);
61          // System.out.println("Created FloatMatrix");
62      }
63  
64      /**
65       * @param <U> Unit
66       */
67      public abstract static class Abs<U extends Unit<U>> extends FloatMatrix<U> implements Absolute
68      {
69          /**  */
70          private static final long serialVersionUID = 20150309L;
71  
72          /**
73           * Construct a new Absolute Immutable FloatMatrix.
74           * @param unit U; the unit of the new Absolute Immutable FloatMatrix
75           */
76          protected Abs(final U unit)
77          {
78              super(unit);
79              // System.out.println("Created Abs");
80          }
81  
82          /**
83           * @param <U> Unit
84           */
85          public static class Dense<U extends Unit<U>> extends Abs<U> implements DenseData
86          {
87              /**  */
88              private static final long serialVersionUID = 20150309L;
89  
90              /**
91               * Construct a new Absolute Dense Immutable FloatMatrix.
92               * @param values float[][]; the values of the entries in the new Absolute Dense Immutable FloatMatrix
93               * @param unit U; the unit of the new Absolute Dense Immutable FloatMatrix
94               * @throws ValueException when values is null, or is not rectangular
95               */
96              public Dense(final float[][] values, final U unit) throws ValueException
97              {
98                  super(unit);
99                  // System.out.println("Created Dense");
100                 initialize(values);
101             }
102 
103             /**
104              * Construct a new Absolute Dense Immutable FloatMatrix.
105              * @param values FloatScalar.Abs&lt;U&gt;[][]; the values of the entries in the new Absolute Dense Immutable
106              *            FloatMatrix
107              * @throws ValueException when values has zero entries, or is not rectangular
108              */
109             public Dense(final FloatScalar.Abs<U>[][] values) throws ValueException
110             {
111                 super(checkNonEmpty(values)[0][0].getUnit());
112                 // System.out.println("Created Dense");
113                 initialize(values);
114             }
115 
116             /**
117              * For package internal use only.
118              * @param values FloatMatrix2D; the values of the entries in the new Absolute Dense Immutable FloatMatrix
119              * @param unit U; the unit of the new Absolute Dense Immutable FloatMatrix
120              */
121             protected Dense(final FloatMatrix2D values, final U unit)
122             {
123                 super(unit);
124                 // System.out.println("Created Dense");
125                 initialize(values); // shallow copy
126             }
127 
128             /** {@inheritDoc} */
129             @Override
130             public final MutableFloatMatrix.Abs.Dense<U> mutable()
131             {
132                 return new MutableFloatMatrix.Abs.Dense<U>(getMatrixSI(), getUnit());
133             }
134 
135             /** {@inheritDoc} */
136             @Override
137             protected final FloatMatrix2D createMatrix2D(final int rows, final int columns)
138             {
139                 return new DenseFloatMatrix2D(rows, columns);
140             }
141 
142             /** {@inheritDoc} */
143             @Override
144             public final FloatMatrix.Abs.Dense<U> copy()
145             {
146                 return this; // That was easy...
147             }
148 
149         }
150 
151         /**
152          * @param <U> Unit
153          */
154         public static class Sparse<U extends Unit<U>> extends Abs<U> implements SparseData
155         {
156             /**  */
157             private static final long serialVersionUID = 20150309L;
158 
159             /**
160              * Construct a new Absolute Sparse Immutable FloatMatrix.
161              * @param values float[][]; the values of the entries in the new Absolute Sparse Immutable FloatMatrix
162              * @param unit U; the unit of the new Absolute Sparse Immutable FloatMatrix
163              * @throws ValueException when values is null, or is not rectangular
164              */
165             public Sparse(final float[][] values, final U unit) throws ValueException
166             {
167                 super(unit);
168                 // System.out.println("Created Sparse");
169                 initialize(values);
170             }
171 
172             /**
173              * Construct a new Absolute Sparse Immutable FloatMatrix.
174              * @param values FloatScalar.Abs&lt;U&gt;[][]; the values of the entries in the new Absolute Sparse
175              *            Immutable FloatMatrix
176              * @throws ValueException when values has zero entries, or is not rectangular
177              */
178             public Sparse(final FloatScalar.Abs<U>[][] values) throws ValueException
179             {
180                 super(checkNonEmpty(values)[0][0].getUnit());
181                 // System.out.println("Created Sparse");
182                 initialize(values);
183             }
184 
185             /**
186              * For package internal use only.
187              * @param values FloatMatrix2D; the values of the entries in the new Absolute Sparse Immutable FloatMatrix
188              * @param unit U; the unit of the new Absolute Sparse Immutable FloatMatrix
189              */
190             protected Sparse(final FloatMatrix2D values, final U unit)
191             {
192                 super(unit);
193                 // System.out.println("Created Sparse");
194                 initialize(values); // shallow copy
195             }
196 
197             /** {@inheritDoc} */
198             @Override
199             public final MutableFloatMatrix.Abs.Sparse<U> mutable()
200             {
201                 return new MutableFloatMatrix.Abs.Sparse<U>(getMatrixSI(), getUnit());
202             }
203 
204             /** {@inheritDoc} */
205             @Override
206             protected final FloatMatrix2D createMatrix2D(final int rows, final int columns)
207             {
208                 return new SparseFloatMatrix2D(rows, columns);
209             }
210 
211             /** {@inheritDoc} */
212             @Override
213             public final FloatMatrix.Abs.Sparse<U> copy()
214             {
215                 return this; // That was easy...
216             }
217 
218         }
219 
220         /** {@inheritDoc} */
221         @Override
222         public final FloatScalar.Abs<U> get(final int row, final int column) throws ValueException
223         {
224             return new FloatScalar.Abs<U>(getInUnit(row, column, getUnit()), getUnit());
225         }
226 
227     }
228 
229     /**
230      * @param <U> Unit
231      */
232     public abstract static class Rel<U extends Unit<U>> extends FloatMatrix<U> implements Relative
233     {
234         /**  */
235         private static final long serialVersionUID = 20150309L;
236 
237         /**
238          * Construct a new Relative Immutable FloatMatrix.
239          * @param unit U; the unit of the new Relative Immutable FloatMatrix
240          */
241         protected Rel(final U unit)
242         {
243             super(unit);
244             // System.out.println("Created Rel");
245         }
246 
247         /**
248          * @param <U> Unit
249          */
250         public static class Dense<U extends Unit<U>> extends Rel<U> implements DenseData
251         {
252             /**  */
253             private static final long serialVersionUID = 20150309L;
254 
255             /**
256              * Construct a new Relative Dense Immutable FloatMatrix.
257              * @param values float[][]; the values of the entries in the new Relative Dense Immutable FloatMatrix
258              * @param unit U; the unit of the new Relative Dense Immutable FloatMatrix
259              * @throws ValueException when values is null, or is not rectangular
260              */
261             public Dense(final float[][] values, final U unit) throws ValueException
262             {
263                 super(unit);
264                 // System.out.println("Created Dense");
265                 initialize(values);
266             }
267 
268             /**
269              * Construct a new Relative Dense Immutable FloatMatrix.
270              * @param values FloatScalar.Rel&lt;U&gt;[][]; the values of the entries in the new Relative Dense Immutable
271              *            FloatMatrix
272              * @throws ValueException when values has zero entries, or is not rectangular
273              */
274             public Dense(final FloatScalar.Rel<U>[][] values) throws ValueException
275             {
276                 super(checkNonEmpty(values)[0][0].getUnit());
277                 // System.out.println("Created Dense");
278                 initialize(values);
279             }
280 
281             /**
282              * For package internal use only.
283              * @param values FloatMatrix2D; the values of the entries in the new Relative Dense Immutable FloatMatrix
284              * @param unit U; the unit of the new Relative Dense Immutable FloatMatrix
285              */
286             protected Dense(final FloatMatrix2D values, final U unit)
287             {
288                 super(unit);
289                 // System.out.println("Created Dense");
290                 initialize(values); // shallow copy
291             }
292 
293             /** {@inheritDoc} */
294             @Override
295             public final MutableFloatMatrix.Rel.Dense<U> mutable()
296             {
297                 return new MutableFloatMatrix.Rel.Dense<U>(getMatrixSI(), getUnit());
298             }
299 
300             /** {@inheritDoc} */
301             @Override
302             protected final FloatMatrix2D createMatrix2D(final int rows, final int columns)
303             {
304                 return new DenseFloatMatrix2D(rows, columns);
305             }
306 
307             /** {@inheritDoc} */
308             @Override
309             public final FloatMatrix.Rel.Dense<U> copy()
310             {
311                 return this; // That was easy...
312             }
313 
314         }
315 
316         /**
317          * @param <U> Unit
318          */
319         public static class Sparse<U extends Unit<U>> extends Rel<U> implements SparseData
320         {
321             /**  */
322             private static final long serialVersionUID = 20150309L;
323 
324             /**
325              * Construct a new Relative Sparse Immutable FloatMatrix.
326              * @param values float[][]; the values of the entries in the new Relative Sparse Immutable FloatMatrix
327              * @param unit U; the unit of the new Relative Sparse Immutable FloatMatrix
328              * @throws ValueException when values is null, or is not rectangular
329              */
330             public Sparse(final float[][] values, final U unit) throws ValueException
331             {
332                 super(unit);
333                 // System.out.println("Created Sparse");
334                 initialize(values);
335             }
336 
337             /**
338              * Construct a new Relative Sparse Immutable FloatMatrix.
339              * @param values FloatScalar.Rel&lt;U&gt;[][]; the values of the entries in the new Relative Sparse
340              *            Immutable FloatMatrix
341              * @throws ValueException when values has zero entries, or is not rectangular
342              */
343             public Sparse(final FloatScalar.Rel<U>[][] values) throws ValueException
344             {
345                 super(checkNonEmpty(values)[0][0].getUnit());
346                 // System.out.println("Created Sparse");
347                 initialize(values);
348             }
349 
350             /**
351              * For package internal use only.
352              * @param values FloatMatrix2D; the values of the entries in the new Relative Sparse Immutable FloatMatrix
353              * @param unit U; the unit of the new Relative Sparse Immutable FloatMatrix
354              */
355             protected Sparse(final FloatMatrix2D values, final U unit)
356             {
357                 super(unit);
358                 // System.out.println("Created Sparse");
359                 initialize(values); // shallow copy
360             }
361 
362             /** {@inheritDoc} */
363             @Override
364             public final MutableFloatMatrix.Rel.Sparse<U> mutable()
365             {
366                 return new MutableFloatMatrix.Rel.Sparse<U>(getMatrixSI(), getUnit());
367             }
368 
369             /** {@inheritDoc} */
370             @Override
371             protected final FloatMatrix2D createMatrix2D(final int rows, final int columns)
372             {
373                 return new SparseFloatMatrix2D(rows, columns);
374             }
375 
376             /** {@inheritDoc} */
377             @Override
378             public final FloatMatrix.Rel.Sparse<U> copy()
379             {
380                 return this; // That was easy...
381             }
382 
383         }
384 
385         /** {@inheritDoc} */
386         @Override
387         public final FloatScalar.Rel<U> get(final int row, final int column) throws ValueException
388         {
389             return new FloatScalar.Rel<U>(getInUnit(row, column, getUnit()), getUnit());
390         }
391 
392     }
393 
394     /**
395      * Retrieve the internal data.
396      * @return FloatMatrix2D; the data in the internal format
397      */
398     protected final FloatMatrix2D getMatrixSI()
399     {
400         return this.matrixSI;
401     }
402 
403     /**
404      * Make a deep copy of the data (used ONLY in the MutableFloatMatrix sub class).
405      */
406     protected final void deepCopyData()
407     {
408         this.matrixSI = getMatrixSI().copy(); // makes a deep copy, using multithreading
409     }
410 
411     /**
412      * Create a mutable version of this FloatMatrix. <br>
413      * The mutable version is created with a shallow copy of the data and the internal copyOnWrite flag set. The first
414      * operation in the mutable version that modifies the data shall trigger a deep copy of the data.
415      * @return MutableFloatMatrix&lt;U&gt;; mutable version of this FloatMatrix
416      */
417     public abstract MutableFloatMatrix<U> mutable();
418 
419     /**
420      * Import the values and convert them into the SI standard unit.
421      * @param values float[][]; an array of values
422      * @throws ValueException when values is null, or not rectangular
423      */
424     protected final void initialize(final float[][] values) throws ValueException
425     {
426         ensureRectangular(values);
427         this.matrixSI = createMatrix2D(values.length, 0 == values.length ? 0 : values[0].length);
428         if (getUnit().equals(getUnit().getStandardUnit()))
429         {
430             this.matrixSI.assign(values);
431         }
432         else
433         {
434             for (int row = values.length; --row >= 0;)
435             {
436                 for (int column = values[row].length; --column >= 0;)
437                 {
438                     safeSet(row, column, (float) expressAsSIUnit(values[row][column]));
439                 }
440             }
441         }
442     }
443 
444     /**
445      * Import the values from an existing FloatMatrix2D. This makes a shallow copy.
446      * @param values FloatMatrix2D; the values
447      */
448     protected final void initialize(final FloatMatrix2D values)
449     {
450         this.matrixSI = values;
451     }
452 
453     /**
454      * Construct the matrix and store the values in the standard SI unit.
455      * @param values FloatScalar&lt;U&gt;[][]; a 2D array of values
456      * @throws ValueException when values is null, empty, or is not rectangular
457      */
458     protected final void initialize(final FloatScalar<U>[][] values) throws ValueException
459     {
460         ensureRectangularAndNonEmpty(values);
461         this.matrixSI = createMatrix2D(values.length, values[0].length);
462         for (int row = values.length; --row >= 0;)
463         {
464             for (int column = values[row].length; --column >= 0;)
465             {
466                 safeSet(row, column, values[row][column].getSI());
467             }
468         }
469     }
470 
471     /**
472      * Create storage for the data. <br/>
473      * This method must be implemented by each leaf class.
474      * @param rows int; the number of rows in the matrix
475      * @param columns int; the number of columns in the matrix
476      * @return FloatMatrix2D; an instance of the right type of FloatMatrix2D (absolute/relative, dense/sparse, etc.)
477      */
478     protected abstract FloatMatrix2D createMatrix2D(final int rows, final int columns);
479 
480     /**
481      * Create a float[][] array filled with the values in the standard SI unit.
482      * @return float[][]; array of values in the standard SI unit
483      */
484     public final float[][] getValuesSI()
485     {
486         return this.matrixSI.toArray(); // this makes a deep copy
487     }
488 
489     /**
490      * Create a float[][] array filled with the values in the original unit.
491      * @return float[][]; the values in the original unit
492      */
493     public final float[][] getValuesInUnit()
494     {
495         return getValuesInUnit(getUnit());
496     }
497 
498     /**
499      * Create a float[][] array filled with the values converted into a specified unit.
500      * @param targetUnit U; the unit into which the values are converted for use
501      * @return float[][]; the values converted into the specified unit
502      */
503     public final float[][] getValuesInUnit(final U targetUnit)
504     {
505         float[][] values = this.matrixSI.toArray();
506         for (int row = rows(); --row >= 0;)
507         {
508             for (int column = columns(); --column >= 0;)
509             {
510                 values[row][column] = (float) ValueUtil.expressAsUnit(values[row][column], targetUnit);
511             }
512         }
513         return values;
514     }
515 
516     /** {@inheritDoc} */
517     @Override
518     public final int rows()
519     {
520         return this.matrixSI.rows();
521     }
522 
523     /** {@inheritDoc} */
524     @Override
525     public final int columns()
526     {
527         return this.matrixSI.columns();
528     }
529 
530     /** {@inheritDoc} */
531     @Override
532     public final float getSI(final int row, final int column) throws ValueException
533     {
534         checkIndex(row, column);
535         return safeGet(row, column);
536     }
537 
538     /** {@inheritDoc} */
539     @Override
540     public final float getInUnit(final int row, final int column) throws ValueException
541     {
542         return (float) expressAsSpecifiedUnit(getSI(row, column));
543     }
544 
545     /** {@inheritDoc} */
546     @Override
547     public final float getInUnit(final int row, final int column, final U targetUnit) throws ValueException
548     {
549         return (float) ValueUtil.expressAsUnit(getSI(row, column), targetUnit);
550     }
551 
552     /** {@inheritDoc} */
553     @Override
554     public final float zSum()
555     {
556         return this.matrixSI.zSum();
557     }
558 
559     /** {@inheritDoc} */
560     @Override
561     public final int cardinality()
562     {
563         return this.matrixSI.cardinality();
564     }
565 
566     /** {@inheritDoc} */
567     @Override
568     public final float det() throws ValueException
569     {
570         try
571         {
572             if (this instanceof SparseData)
573             {
574                 return new SparseFloatAlgebra().det(getMatrixSI());
575             }
576             if (this instanceof DenseData)
577             {
578                 return new DenseFloatAlgebra().det(getMatrixSI());
579             }
580         throw new ValueException("FloatMatrix.det -- matrix implements neither Sparse nor Dense");
581         }
582         catch (IllegalArgumentException exception)
583         {
584             if (!exception.getMessage().startsWith("Matrix must be square"))
585             {
586                 exception.printStackTrace();
587             }
588             throw new ValueException(exception.getMessage()); // probably Matrix must be square
589             }
590     }
591 
592     /** {@inheritDoc} */
593     @Override
594     public final String toString()
595     {
596         return toString(getUnit(), false, true);
597     }
598 
599     /**
600      * Print this FloatMatrix with the values expressed in the specified unit.
601      * @param displayUnit U; the unit into which the values are converted for display
602      * @return String; printable string with the matrix contents expressed in the specified unit
603      */
604     public final String toString(final U displayUnit)
605     {
606         return toString(displayUnit, false, true);
607     }
608 
609     /**
610      * Print this FloatMatrix with optional type and unit information.
611      * @param verbose boolean; if true; include type info; if false; exclude type info
612      * @param withUnit boolean; if true; include the unit; of false; exclude the unit
613      * @return String; printable string with the matrix contents
614      */
615     public final String toString(final boolean verbose, final boolean withUnit)
616     {
617         return toString(getUnit(), verbose, withUnit);
618     }
619 
620     /**
621      * Print this FloatMatrix with the values expressed in the specified unit.
622      * @param displayUnit U; the unit into which the values are converted for display
623      * @param verbose boolean; if true; include type info; if false; exclude type info
624      * @param withUnit boolean; if true; include the unit; of false; exclude the unit
625      * @return String; printable string with the matrix contents
626      */
627     public final String toString(final U displayUnit, final boolean verbose, final boolean withUnit)
628     {
629         StringBuffer buf = new StringBuffer();
630         if (verbose)
631         {
632             if (this instanceof MutableFloatMatrix)
633             {
634                 buf.append("Mutable   ");
635                 if (this instanceof MutableFloatMatrix.Abs.Dense)
636                 {
637                     buf.append("Abs Dense  ");
638                 }
639                 else if (this instanceof MutableFloatMatrix.Rel.Dense)
640                 {
641                     buf.append("Rel Dense  ");
642                 }
643                 else if (this instanceof MutableFloatMatrix.Abs.Sparse)
644                 {
645                     buf.append("Abs Sparse ");
646                 }
647                 else if (this instanceof MutableFloatMatrix.Rel.Sparse)
648                 {
649                     buf.append("Rel Sparse ");
650                 }
651                 else
652                 {
653                     buf.append("??? ");
654                 }
655             }
656             else
657             {
658                 buf.append("Immutable ");
659                 if (this instanceof FloatMatrix.Abs.Dense)
660                 {
661                     buf.append("Abs Dense  ");
662                 }
663                 else if (this instanceof FloatMatrix.Rel.Dense)
664                 {
665                     buf.append("Rel Dense  ");
666                 }
667                 else if (this instanceof FloatMatrix.Abs.Sparse)
668                 {
669                     buf.append("Abs Sparse ");
670                 }
671                 else if (this instanceof FloatMatrix.Rel.Sparse)
672                 {
673                     buf.append("Rel Sparse ");
674                 }
675                 else
676                 {
677                     buf.append("??? ");
678                 }
679             }
680         }
681         for (int row = 0; row < rows(); row++)
682         {
683             buf.append("\r\n\t");
684             for (int column = 0; column < columns(); column++)
685             {
686                 float f = (float) ValueUtil.expressAsUnit(safeGet(row, column), displayUnit);
687                 buf.append(" " + Format.format(f));
688             }
689         }
690         if (withUnit)
691         {
692             buf.append(displayUnit.getAbbreviation());
693         }
694         return buf.toString();
695     }
696 
697     /**
698      * Centralized size equality check.
699      * @param other FloatMatrix&lt;?&gt;; other FloatMatrix
700      * @throws ValueException when other is null, or matrices have unequal size
701      */
702     protected final void checkSize(final FloatMatrix<?> other) throws ValueException
703     {
704         if (null == other)
705         {
706             throw new ValueException("other is null");
707         }
708         if (rows() != other.rows() || columns() != other.columns())
709         {
710             throw new ValueException("The matrices have different sizes: " + rows() + "x" + columns() + " != "
711                     + other.rows() + "x" + other.columns());
712         }
713     }
714 
715     /**
716      * Centralized size equality check.
717      * @param other float[][]; array of float
718      * @throws ValueException when matrices have unequal size
719      */
720     protected final void checkSize(final float[][] other) throws ValueException
721     {
722         final int otherColumns = 0 == other.length ? 0 : other[0].length;
723         if (rows() != other.length || columns() != otherColumns)
724         {
725         throw new ValueException("The matrix and the array have different sizes: " + rows() + "x" + columns()
726                     + " != " + other.length + "x" + otherColumns);
727         }
728         ensureRectangular(other);
729     }
730 
731     /**
732      * Check that a 2D array of float is not null and rectangular; i.e. all rows have the same length.
733      * @param values float[][]; the 2D array to check
734      * @throws ValueException when not all rows have the same length
735      */
736     private static void ensureRectangular(final float[][] values) throws ValueException
737     {
738         if (null == values)
739         {
740             throw new ValueException("values is null");
741         }
742         if (values.length > 0 && null == values[0])
743         {
744             throw new ValueException("Row 0 is null");
745         }
746         for (int row = values.length; --row >= 1;)
747         {
748             if (null == values[row] || values[0].length != values[row].length)
749             {
750                 throw new ValueException("Lengths of rows are not all the same");
751             }
752         }
753     }
754 
755     /**
756      * Check that a 2D array of FloatScalar&lt;?&gt; is rectangular; i.e. all rows have the same length and is non
757      * empty.
758      * @param values FloatScalar&lt;?&gt;[][]; the 2D array to check
759      * @throws ValueException when values is not rectangular, or contains no data
760      */
761     private static void ensureRectangularAndNonEmpty(final FloatScalar<?>[][] values) throws ValueException
762     {
763         if (null == values)
764         {
765             throw new ValueException("values is null");
766         }
767         if (0 == values.length || 0 == values[0].length)
768         {
769             throw new ValueException("Cannot determine unit for FloatMatrix from an empty array of FloatScalar");
770         }
771         for (int row = values.length; --row >= 1;)
772         {
773             if (values[0].length != values[row].length)
774             {
775                 throw new ValueException("Lengths of rows are not all the same");
776             }
777         }
778     }
779 
780     /**
781      * Check that provided row and column indices are valid.
782      * @param row int; the row value to check
783      * @param column int; the column value to check
784      * @throws ValueException when row or column is invalid
785      */
786     protected final void checkIndex(final int row, final int column) throws ValueException
787     {
788         if (row < 0 || row >= rows() || column < 0 || column >= columns())
789         {
790             throw new ValueException("index out of range (valid range is 0.." + (rows() - 1) + ", 0.."
791                     + (columns() - 1) + ", got " + row + ", " + column + ")");
792         }
793     }
794 
795     /**
796      * Retrieve a value in matrixSI without checking validity of the indices.
797      * @param row int; the row where the value must be retrieved
798      * @param column int; the column where the value must be retrieved
799      * @return float; the value stored at the indicated row and column
800      */
801     protected final float safeGet(final int row, final int column)
802     {
803         return this.matrixSI.getQuick(row, column);
804     }
805 
806     /**
807      * Modify a value in matrixSI without checking validity of the indices.
808      * @param row int; the row where the value must be stored
809      * @param column int; the column where the value must be stored
810      * @param valueSI float; the new value for the entry in matrixSI
811      */
812     protected final void safeSet(final int row, final int column, final float valueSI)
813     {
814         this.matrixSI.setQuick(row, column, valueSI);
815     }
816 
817     /**
818      * Create a deep copy of the data.
819      * @return FloatMatrix2D; deep copy of the data
820      */
821     protected final FloatMatrix2D deepCopyOfData()
822     {
823         return this.matrixSI.copy();
824     }
825 
826     /**
827      * Check that a provided array can be used to create some descendant of a FloatMatrix.
828      * @param fsArray FloatScalar&lt;U&gt;[][]; the provided array
829      * @param <U> Unit; the unit of the FloatScalar array
830      * @return FloatScalar&lt;U&gt;[][]; the provided array
831      * @throws ValueException when the array has zero entries
832      */
833     protected static <U extends Unit<U>> FloatScalar<U>[][] checkNonEmpty(final FloatScalar<U>[][] fsArray)
834             throws ValueException
835     {
836         if (0 == fsArray.length || 0 == fsArray[0].length)
837         {
838             throw new ValueException(
839                     "Cannot create a FloatMatrix or MutableFloatMatrix from an empty array of FloatScalar");
840         }
841         return fsArray;
842     }
843 
844     /**
845      * Solve x for A*x = b. According to Colt: x; a new independent matrix; solution if A is square, least squares
846      * solution if A.rows() &gt; A.columns(), underdetermined system solution if A.rows() &lt; A.columns().
847      * @param A FloatMatrix&lt;?&gt;; matrix A in A*x = b
848      * @param b FloatVector&lt;?&gt;; vector b in A*x = b
849      * @return FloatVector&lt;SIUnit&gt;; vector x in A*x = b
850      * @throws ValueException when matrix A is neither Sparse nor Dense
851      */
852     public static FloatVector<SIUnit> solve(final FloatMatrix<?> A, final FloatVector<?> b) throws ValueException
853     {
854         // TODO is this correct? Should lookup matrix algebra to find out unit for x when solving A*x = b ?
855         SIUnit targetUnit =
856                 Unit.lookupOrCreateSIUnitWithSICoefficients(SICoefficients.divide(b.getUnit().getSICoefficients(),
857                         A.getUnit().getSICoefficients()).toString());
858         
859         // TODO should the algorithm throw an exception when rows/columns do not match when solving A*x = b ?
860         FloatMatrix2D A2D = A.getMatrixSI();
861         if (A instanceof SparseData)
862         {
863             SparseFloatMatrix1D b1D = new SparseFloatMatrix1D(b.getValuesSI());
864             FloatMatrix1D x1D = new SparseFloatAlgebra().solve(A2D, b1D);
865             FloatVector.Abs.Sparse<SIUnit> x = new FloatVector.Abs.Sparse<SIUnit>(x1D.toArray(), targetUnit);
866         return x;
867         }
868         if (A instanceof DenseData)
869         {
870             DenseFloatMatrix1D b1D = new DenseFloatMatrix1D(b.getValuesSI());
871             FloatMatrix1D x1D = new DenseFloatAlgebra().solve(A2D, b1D);
872             FloatVector.Abs.Dense<SIUnit> x = new FloatVector.Abs.Dense<SIUnit>(x1D.toArray(), targetUnit);
873             return x;
874         }
875         throw new ValueException("FloatMatrix.det -- matrix implements neither Sparse nor Dense");
876     }
877 
878     /** {@inheritDoc} */
879     @Override
880     public final int hashCode()
881     {
882         final int prime = 31;
883         int result = 1;
884         result = prime * result + this.matrixSI.hashCode();
885         return result;
886     }
887 
888     /** {@inheritDoc} */
889     @Override
890     public final boolean equals(final Object obj)
891     {
892         if (this == obj)
893         {
894             return true;
895         }
896         if (obj == null)
897         {
898         return false;
899         }
900         if (!(obj instanceof FloatMatrix))
901         {
902             return false;
903         }
904         FloatMatrix<?> other = (FloatMatrix<?>) obj;
905         // unequal if not both Absolute or both Relative
906         if (this.isAbsolute() != other.isAbsolute() || this.isRelative() != other.isRelative())
907         {
908             return false;
909         }
910         // unequal if the standard SI units differ
911         if (!this.getUnit().getStandardUnit().equals(other.getUnit().getStandardUnit()))
912         {
913             return false;
914         }
915         // Colt's equals also tests the size of the matrix
916         if (!getMatrixSI().equals(other.getMatrixSI()))
917         {
918             return false;
919         }
920         return true;
921     }
922 
923     /**********************************************************************************/
924     /********************************* STATIC METHODS *********************************/
925     /**********************************************************************************/
926 
927     /**
928      * Add two FloatMatrices value by value and store the result in a new MutableFloatMatrix.Abs.Dense&lt;U&gt;.
929      * @param left FloatMatrix.Abs.Dense&lt;U&gt;; the left operand
930      * @param right FloatMatrix.Rel&lt;U&gt;; the right operand
931      * @param <U> Unit; the unit of the parameters and the result
932      * @return MutableFloatMatrix.Abs.Dense&lt;U&gt;
933      * @throws ValueException when the matrices do not have the same size
934      */
935     public static <U extends Unit<U>> MutableFloatMatrix.Abs.Dense<U> plus(final FloatMatrix.Abs.Dense<U> left,
936             final FloatMatrix.Rel<U> right) throws ValueException
937     {
938         return (MutableFloatMatrix.Abs.Dense<U>) left.mutable().incrementBy(right);
939     }
940 
941     /**
942      * Add two FloatMatrices value by value and store the result in a new MutableFloatMatrix.Abs.Dense&lt;U&gt;.
943      * @param left FloatMatrix.Abs.Sparse&lt;U&gt;; the left operand
944      * @param right FloatMatrix.Rel.Dense&lt;U&gt;; the right operand
945      * @param <U> Unit; the unit of the parameters and the result
946      * @return MutableFloatMatrix.Abs.Dense&lt;U&gt;
947      * @throws ValueException when the matrices do not have the same size
948      */
949     public static <U extends Unit<U>> MutableFloatMatrix.Abs.Dense<U> plus(final FloatMatrix.Abs.Sparse<U> left,
950             final FloatMatrix.Rel.Dense<U> right) throws ValueException
951     {
952         return (MutableFloatMatrix.Abs.Dense<U>) sparseToDense(left).incrementBy(right);
953     }
954 
955     /**
956      * Add two FloatMatrices value by value and store the result in a new MutableFloatMatrix.Abs.Sparse&lt;U&gt;.
957      * @param left FloatMatrix.Abs.Sparse&lt;U&gt;; the left operand
958      * @param right FloatMatrix.Rel.Sparse&lt;U&gt;; the right operand
959      * @param <U> Unit; the unit of the parameters and the result
960      * @return MutableFloatMatrix.Abs.Sparse&lt;U&gt;
961      * @throws ValueException when the matrices do not have the same size
962      */
963     public static <U extends Unit<U>> MutableFloatMatrix.Abs.Sparse<U> plus(final FloatMatrix.Abs.Sparse<U> left,
964             final FloatMatrix.Rel.Sparse<U> right) throws ValueException
965     {
966         return (MutableFloatMatrix.Abs.Sparse<U>) left.mutable().incrementBy(right);
967     }
968 
969     /**
970      * Add two FloatMatrices value by value and store the result in a new MutableFloatMatrix.Rel.Dense&lt;U&gt;.
971      * @param left FloatMatrix.Rel.Dense&lt;U&gt;; the left operand
972      * @param right FloatMatrix.Rel&lt;U&gt;; the right operand
973      * @param <U> Unit; the unit of the parameters and the result
974      * @return MutableFloatMatrix.Rel.Dense&lt;U&gt;
975      * @throws ValueException when the matrices do not have the same size
976      */
977     public static <U extends Unit<U>> MutableFloatMatrix.Rel.Dense<U> plus(final FloatMatrix.Rel.Dense<U> left,
978             final FloatMatrix.Rel<U> right) throws ValueException
979     {
980         return (MutableFloatMatrix.Rel.Dense<U>) left.mutable().incrementBy(right);
981     }
982 
983     /**
984      * Add two FloatMatrices value by value and store the result in a new MutableFloatMatrix.Rel.Dense&lt;U&gt;.
985      * @param left FloatMatrix.Rel.Sparse&lt;U&gt;; the left operand
986      * @param right FloatMatrix.Rel.Dense&lt;U&gt;; the right operand
987      * @param <U> Unit; the unit of the parameters and the result
988      * @return MutableFloatMatrix.Rel.Dense&lt;U&gt;
989      * @throws ValueException when the matrices do not have the same size
990      */
991     public static <U extends Unit<U>> MutableFloatMatrix.Rel.Dense<U> plus(final FloatMatrix.Rel.Sparse<U> left,
992             final FloatMatrix.Rel.Dense<U> right) throws ValueException
993     {
994         return (MutableFloatMatrix.Rel.Dense<U>) sparseToDense(left).incrementBy(right);
995     }
996 
997     /**
998      * Add two FloatMatrices value by value and store the result in a new MutableFloatMatrix.Rel.Sparse&lt;U&gt;.
999      * @param left FloatMatrix.Rel.Sparse&lt;U&gt;; the left operand
1000      * @param right FloatMatrix.Rel.Sparse&lt;U&gt;; the right operand
1001      * @param <U> Unit; the unit of the parameters and the result
1002      * @return MutableFloatMatrix.Rel.Sparse&lt;U&gt;
1003      * @throws ValueException when the matrices do not have the same size
1004      */
1005     public static <U extends Unit<U>> MutableFloatMatrix.Rel.Sparse<U> plus(final FloatMatrix.Rel.Sparse<U> left,
1006             final FloatMatrix.Rel.Sparse<U> right) throws ValueException
1007     {
1008         return (MutableFloatMatrix.Rel.Sparse<U>) left.mutable().incrementBy(right);
1009     }
1010 
1011     /**
1012      * Subtract two FloatMatrices value by value and store the result in a new MutableFloatMatrix.Rel.Dense&lt;U&gt;.
1013      * @param left FloatMatrix.Abs.Dense&lt;U&gt;; the left operand
1014      * @param right FloatMatrix.Abs&lt;U&gt;; the right operand
1015      * @param <U> Unit; the unit of the parameters and the result
1016      * @return MutableFloatMatrix.Rel.Dense&lt;U&gt;
1017      * @throws ValueException when the matrices do not have the same size
1018      */
1019     public static <U extends Unit<U>> MutableFloatMatrix.Rel.Dense<U> minus(final FloatMatrix.Abs.Dense<U> left,
1020             final FloatMatrix.Abs<U> right) throws ValueException
1021     {
1022         return (MutableFloatMatrix.Rel.Dense<U>) new MutableFloatMatrix.Rel.Dense<U>(left.deepCopyOfData(),
1023                     left.getUnit()).decrementBy(right);
1024     }
1025 
1026     /**
1027      * Subtract two FloatMatrices value by value and store the result in a new MutableFloatMatrix.Rel.Sparse&lt;U&gt;.
1028      * @param left FloatMatrix.Abs.Sparse&lt;U&gt;; the left operand
1029      * @param right FloatMatrix.Abs.Sparse&lt;U&gt;; the right operand
1030      * @param <U> Unit; the unit of the parameters and the result
1031      * @return MutableFloatMatrix.Rel.Sparse&lt;U&gt;
1032      * @throws ValueException when the matrices do not have the same size
1033      */
1034     public static <U extends Unit<U>> MutableFloatMatrix.Rel.Sparse<U> minus(final FloatMatrix.Abs.Sparse<U> left,
1035             final FloatMatrix.Abs.Sparse<U> right) throws ValueException
1036     {
1037         return (MutableFloatMatrix.Rel.Sparse<U>) new MutableFloatMatrix.Rel.Sparse<U>(left.deepCopyOfData(),
1038                     left.getUnit()).decrementBy(right);
1039     }
1040 
1041     /**
1042      * Subtract two FloatMatrices value by value and store the result in a new MutableFloatMatrix.Rel.Dense&lt;U&gt;.
1043      * @param left FloatMatrix.Abs.Sparse&lt;U&gt;; the left operand
1044      * @param right FloatMatrix.Abs.Dense&lt;U&gt;; the right operand
1045      * @param <U> Unit; the unit of the parameters and the result
1046      * @return MutableFloatMatrix.Rel.Dense&lt;U&gt;
1047      * @throws ValueException when the matrices do not have the same size
1048      */
1049     public static <U extends Unit<U>> MutableFloatMatrix.Rel.Dense<U> minus(final FloatMatrix.Abs.Sparse<U> left,
1050             final FloatMatrix.Abs.Dense<U> right) throws ValueException
1051     {
1052         return (MutableFloatMatrix.Rel.Dense<U>) new MutableFloatMatrix.Rel.Dense<U>(left.deepCopyOfData(),
1053                     left.getUnit()).decrementBy(right);
1054     }
1055 
1056     /**
1057      * Subtract two FloatMatrices value by value and store the result in a new MutableFloatMatrix.Abs.Dense&lt;U&gt;.
1058      * @param left FloatMatrix.Abs.Dense&lt;U&gt;; the left operand
1059      * @param right FloatMatrix.Rel&lt;U&gt;; the right operand
1060      * @param <U> Unit; the unit of the parameters and the result
1061      * @return MutableFloatMatrix.Abs.Dense&lt;U&gt;
1062      * @throws ValueException when the matrices do not have the same size
1063      */
1064     public static <U extends Unit<U>> MutableFloatMatrix.Abs.Dense<U> minus(final FloatMatrix.Abs.Dense<U> left,
1065             final FloatMatrix.Rel<U> right) throws ValueException
1066     {
1067         return (MutableFloatMatrix.Abs.Dense<U>) left.mutable().decrementBy(right);
1068     }
1069 
1070     /**
1071      * Subtract two FloatMatrices value by value and store the result in a new MutableFloatMatrix.Abs.Dense&lt;U&gt;.
1072      * @param left FloatMatrix.Abs.Sparse&lt;U&gt;; the left operand
1073      * @param right FloatMatrix.Rel.Dense&lt;U&gt;; the right operand
1074      * @param <U> Unit; the unit of the parameters and the result
1075      * @return MutableFloatMatrix.Abs.Dense&lt;U&gt;
1076      * @throws ValueException when the matrices do not have the same size
1077      */
1078     public static <U extends Unit<U>> MutableFloatMatrix.Abs.Dense<U> minus(final FloatMatrix.Abs.Sparse<U> left,
1079             final FloatMatrix.Rel.Dense<U> right) throws ValueException
1080     {
1081         return (MutableFloatMatrix.Abs.Dense<U>) sparseToDense(left).decrementBy(right);
1082     }
1083 
1084     /**
1085      * Subtract two FloatMatrices value by value and store the result in a new MutableFloatMatrix.Abs.Sparse&lt;U&gt;.
1086      * @param left FloatMatrix.Abs.Sparse&lt;U&gt;; the left operand
1087      * @param right FloatMatrix.Rel.Sparse&lt;U&gt;; the right operand
1088      * @param <U> Unit; the unit of the parameters and the result
1089      * @return MutableFloatMatrix.Abs.Sparse&lt;U&gt;
1090      * @throws ValueException when the matrices do not have the same size
1091      */
1092     public static <U extends Unit<U>> MutableFloatMatrix.Abs.Sparse<U> minus(final FloatMatrix.Abs.Sparse<U> left,
1093             final FloatMatrix.Rel.Sparse<U> right) throws ValueException
1094     {
1095         return (MutableFloatMatrix.Abs.Sparse<U>) left.mutable().decrementBy(right);
1096     }
1097 
1098     /**
1099      * Subtract two FloatMatrices value by value and store the result in a new MutableFloatMatrix.Rel.Dense&lt;U&gt;.
1100      * @param left FloatMatrix.Rel.Dense&lt;U&gt;; the left operand
1101      * @param right FloatMatrix.Rel&lt;U&gt;; the right operand
1102      * @param <U> Unit; the unit of the parameters and the result
1103      * @return MutableFloatMatrix.Rel.Dense&lt;U&gt;
1104      * @throws ValueException when the matrices do not have the same size
1105      */
1106     public static <U extends Unit<U>> MutableFloatMatrix.Rel.Dense<U> minus(final FloatMatrix.Rel.Dense<U> left,
1107             final FloatMatrix.Rel<U> right) throws ValueException
1108     {
1109         return (MutableFloatMatrix.Rel.Dense<U>) left.mutable().decrementBy(right);
1110     }
1111 
1112     /**
1113      * Subtract two FloatMatrices value by value and store the result in a new MutableFloatMatrix.Rel.Dense&lt;U&gt;.
1114      * @param left FloatMatrix.Rel.Sparse&lt;U&gt;; the left operand
1115      * @param right FloatMatrix.Rel.Dense&lt;U&gt;; the right operand
1116      * @param <U> Unit; the unit of the parameters and the result
1117      * @return MutableFloatMatrix.Rel.Dense&lt;U&gt;
1118      * @throws ValueException when the matrices do not have the same size
1119      */
1120     public static <U extends Unit<U>> MutableFloatMatrix.Rel.Dense<U> minus(final FloatMatrix.Rel.Sparse<U> left,
1121             final FloatMatrix.Rel.Dense<U> right) throws ValueException
1122     {
1123         return (MutableFloatMatrix.Rel.Dense<U>) sparseToDense(left).decrementBy(right);
1124     }
1125 
1126     /**
1127      * Subtract two FloatMatrices value by value and store the result in a new MutableFloatMatrix.Rel.Sparse&lt;U&gt;.
1128      * @param left FloatMatrix.Rel.Sparse&lt;U&gt;; the left operand
1129      * @param right FloatMatrix.Rel.Sparse&lt;U&gt;; the right operand
1130      * @param <U> Unit; the unit of the parameters and the result
1131      * @return MutableFloatMatrix.Rel.Sparse&lt;U&gt;
1132      * @throws ValueException when the matrices do not have the same size
1133      */
1134     public static <U extends Unit<U>> MutableFloatMatrix.Rel.Sparse<U> minus(final FloatMatrix.Rel.Sparse<U> left,
1135             final FloatMatrix.Rel.Sparse<U> right) throws ValueException
1136     {
1137         return (MutableFloatMatrix.Rel.Sparse<U>) left.mutable().decrementBy(right);
1138     }
1139 
1140     // TODO Decide if you ever need multiply an Absolute with anything
1141     /**
1142      * Multiply two FloatMatrices value by value and store the result in a new
1143      * MutableFloatMatrix.Abs.Dense&lt;SIUnit&gt;.
1144      * @param left FloatMatrix.Abs.Dense&lt;?&gt;; the left operand
1145      * @param right FloatMatrix.Abs.Dense&lt;?&gt;; the right operand
1146      * @return MutableFloatMatrix.Abs.Dense&lt;SIUnit&gt;
1147      * @throws ValueException when the matrices do not have the same size
1148      */
1149     public static MutableFloatMatrix.Abs.Dense<SIUnit> times(final FloatMatrix.Abs.Dense<?> left,
1150             final FloatMatrix.Abs.Dense<?> right) throws ValueException
1151     {
1152         SIUnit targetUnit =
1153                 Unit.lookupOrCreateSIUnitWithSICoefficients(SICoefficients.multiply(left.getUnit().getSICoefficients(),
1154                         right.getUnit().getSICoefficients()).toString());
1155         MutableFloatMatrix.Abs.Dense<SIUnit> work =
1156                 new MutableFloatMatrix.Abs.Dense<SIUnit>(left.deepCopyOfData(), targetUnit);
1157         work.scaleValueByValue(right);
1158         return work;
1159     }
1160 
1161     /**
1162      * Multiply two FloatMatrices value by value and store the result in a new
1163      * MutableFloatMatrix.Abs.Sparse&lt;SIUnit&gt;.
1164      * @param left FloatMatrix.Abs.Dense&lt;?&gt;; the left operand
1165      * @param right FloatMatrix.Abs.Sparse&lt;?&gt;; the right operand
1166      * @return MutableFloatMatrix.Abs.Sparse&lt;SIUnit&gt;
1167      * @throws ValueException when the matrices do not have the same size
1168      */
1169     public static MutableFloatMatrix.Abs.Sparse<SIUnit> times(final FloatMatrix.Abs.Dense<?> left,
1170             final FloatMatrix.Abs.Sparse<?> right) throws ValueException
1171     {
1172         SIUnit targetUnit =
1173                 Unit.lookupOrCreateSIUnitWithSICoefficients(SICoefficients.multiply(left.getUnit().getSICoefficients(),
1174                         right.getUnit().getSICoefficients()).toString());
1175         MutableFloatMatrix.Abs.Sparse<SIUnit> work =
1176                 new MutableFloatMatrix.Abs.Sparse<SIUnit>(left.deepCopyOfData(), targetUnit);
1177         work.scaleValueByValue(right);
1178         return work;
1179     }
1180 
1181     /**
1182      * Multiply two FloatMatrices value by value and store the result in a new
1183      * MutableFloatMatrix.Abs.Sparse&lt;SIUnit&gt;.
1184      * @param left FloatMatrix.Abs.Sparse&lt;?&gt;; the left operand
1185      * @param right FloatMatrix.Abs&lt;?&gt;; the right operand
1186      * @return MutableFloatMatrix.Abs.Sparse&lt;SIUnit&gt;
1187      * @throws ValueException when the matrices do not have the same size
1188      */
1189     public static MutableFloatMatrix.Abs.Sparse<SIUnit> times(final FloatMatrix.Abs.Sparse<?> left,
1190             final FloatMatrix.Abs<?> right) throws ValueException
1191     {
1192         SIUnit targetUnit =
1193                 Unit.lookupOrCreateSIUnitWithSICoefficients(SICoefficients.multiply(left.getUnit().getSICoefficients(),
1194                         right.getUnit().getSICoefficients()).toString());
1195         MutableFloatMatrix.Abs.Sparse<SIUnit> work =
1196                 new MutableFloatMatrix.Abs.Sparse<SIUnit>(left.deepCopyOfData(), targetUnit);
1197         work.scaleValueByValue(right);
1198         return work;
1199     }
1200 
1201     /**
1202      * Multiply two FloatMatrices value by value and store the result in a new
1203      * MutableFloatMatrix.Rel.Dense&lt;SIUnit&gt;.
1204      * @param left FloatMatrix.Rel.Dense&lt;?&gt;; the left operand
1205      * @param right FloatMatrix.Rel.Dense&lt;?&gt;; the right operand
1206      * @return MutableFloatMatrix.Rel.Dense&lt;SIUnit&gt;
1207      * @throws ValueException when the matrices do not have the same size
1208      */
1209     public static MutableFloatMatrix.Rel.Dense<SIUnit> times(final FloatMatrix.Rel.Dense<?> left,
1210             final FloatMatrix.Rel.Dense<?> right) throws ValueException
1211     {
1212         SIUnit targetUnit =
1213                 Unit.lookupOrCreateSIUnitWithSICoefficients(SICoefficients.multiply(left.getUnit().getSICoefficients(),
1214                         right.getUnit().getSICoefficients()).toString());
1215         MutableFloatMatrix.Rel.Dense<SIUnit> work =
1216                 new MutableFloatMatrix.Rel.Dense<SIUnit>(left.deepCopyOfData(), targetUnit);
1217         work.scaleValueByValue(right);
1218         return work;
1219     }
1220 
1221     /**
1222      * Multiply two FloatMatrices value by value and store the result in a new
1223      * MutableFloatMatrix.Rel.Sparse&lt;SIUnit&gt;.
1224      * @param left FloatMatrix.Rel.Dense&lt;?&gt;; the left operand
1225      * @param right FloatMatrix.Rel.Sparse&lt;?&gt;; the right operand
1226      * @return MutableFloatMatrix.Rel.Sparse&lt;SIUnit&gt;
1227      * @throws ValueException when the matrices do not have the same size
1228      */
1229     public static MutableFloatMatrix.Rel.Sparse<SIUnit> times(final FloatMatrix.Rel.Dense<?> left,
1230             final FloatMatrix.Rel.Sparse<?> right) throws ValueException
1231     {
1232         SIUnit targetUnit =
1233                 Unit.lookupOrCreateSIUnitWithSICoefficients(SICoefficients.multiply(left.getUnit().getSICoefficients(),
1234                         right.getUnit().getSICoefficients()).toString());
1235         MutableFloatMatrix.Rel.Sparse<SIUnit> work =
1236                 new MutableFloatMatrix.Rel.Sparse<SIUnit>(left.deepCopyOfData(), targetUnit);
1237         work.scaleValueByValue(right);
1238         return work;
1239     }
1240 
1241     /**
1242      * Multiply two FloatMatrices value by value and store the result in a new
1243      * MutableFloatMatrix.Rel.Sparse&lt;SIUnit&gt;.
1244      * @param left FloatMatrix.Rel.Sparse&lt;?&gt;; the left operand
1245      * @param right FloatMatrix.Rel&lt;?&gt;; the right operand
1246      * @return MutableFloatMatrix.Rel.Sparse&lt;SIUnit&gt;
1247      * @throws ValueException when the matrices do not have the same size
1248      */
1249     public static MutableFloatMatrix.Rel.Sparse<SIUnit> times(final FloatMatrix.Rel.Sparse<?> left,
1250             final FloatMatrix.Rel<?> right) throws ValueException
1251     {
1252         SIUnit targetUnit =
1253                 Unit.lookupOrCreateSIUnitWithSICoefficients(SICoefficients.multiply(left.getUnit().getSICoefficients(),
1254                         right.getUnit().getSICoefficients()).toString());
1255         MutableFloatMatrix.Rel.Sparse<SIUnit> work =
1256                 new MutableFloatMatrix.Rel.Sparse<SIUnit>(left.deepCopyOfData(), targetUnit);
1257         work.scaleValueByValue(right);
1258         return work;
1259     }
1260 
1261     /**
1262      * Multiply the values in a FloatMatrix and a float array value by value and store the result in a new
1263      * MutableFloatMatrix.Abs.Dense&lt;U&gt;.
1264      * @param left FloatMatrix.Abs.Dense&lt;U&gt;; the FloatMatrix
1265      * @param right float[][]; the float array
1266      * @param <U> Unit; the unit of the left parameter and the result
1267      * @return MutableFloatMatrix.Abs.Dense&lt;U&gt;
1268      * @throws ValueException when the FloatMatrix and the array do not have the same size
1269      */
1270     public static <U extends Unit<U>> MutableFloatMatrix.Abs.Dense<U> times(final FloatMatrix.Abs.Dense<U> left,
1271             final float[][] right) throws ValueException
1272     {
1273         return (MutableFloatMatrix.Abs.Dense<U>) left.mutable().scaleValueByValue(right);
1274     }
1275 
1276     /**
1277      * Multiply the values in a FloatMatrix and a float array value by value and store the result in a new
1278      * MutableFloatMatrix.Abs.Sparse&lt;U&gt;.
1279      * @param left FloatMatrix.Abs.Sparse&lt;U&gt;; the FloatMatrix
1280      * @param right float[][]; the float array
1281      * @param <U> Unit; the unit of the left parameter and the result
1282      * @return MutableFloatMatrix.Abs.Sparse&lt;U&gt;
1283      * @throws ValueException when the FloatMatrix and the array do not have the same size
1284      */
1285     public static <U extends Unit<U>> MutableFloatMatrix.Abs.Sparse<U> times(final FloatMatrix.Abs.Sparse<U> left,
1286             final float[][] right) throws ValueException
1287     {
1288         return (MutableFloatMatrix.Abs.Sparse<U>) left.mutable().scaleValueByValue(right);
1289     }
1290 
1291     /**
1292      * Multiply the values in a FloatMatrix and a float array value by value and store the result in a new
1293      * MutableFloatMatrix.Rel.Dense&lt;U&gt;.
1294      * @param left FloatMatrix.Rel.Dense&lt;U&gt;; the FloatMatrix
1295      * @param right float[][]; the float array
1296      * @param <U> Unit; the unit of the left parameter and the result
1297      * @return MutableFloatMatrix.Rel.Dense&lt;U&gt;
1298      * @throws ValueException when the FloatMatrix and the array do not have the same size
1299      */
1300     public static <U extends Unit<U>> MutableFloatMatrix.Rel.Dense<U> times(final FloatMatrix.Rel.Dense<U> left,
1301             final float[][] right) throws ValueException
1302     {
1303         return (MutableFloatMatrix.Rel.Dense<U>) left.mutable().scaleValueByValue(right);
1304     }
1305 
1306     /**
1307      * Multiply the values in a FloatMatrix and a float array value by value and store the result in a new
1308      * MutableFloatMatrix.Rel.Sparse&lt;U&gt;.
1309      * @param left FloatMatrix.Rel.Sparse&lt;U&gt;; the FloatMatrix
1310      * @param right float[][]; the float array
1311      * @param <U> Unit; the unit of the left parameter and the result
1312      * @return MutableFloatMatrix.Rel.Sparse&lt;U&gt;
1313      * @throws ValueException when the FloatMatrix and the array do not have the same size
1314      */
1315     public static <U extends Unit<U>> MutableFloatMatrix.Rel.Sparse<U> times(final FloatMatrix.Rel.Sparse<U> left,
1316             final float[][] right) throws ValueException
1317     {
1318         return (MutableFloatMatrix.Rel.Sparse<U>) left.mutable().scaleValueByValue(right);
1319     }
1320 
1321     /**
1322      * Make the Sparse equivalent of a DenseFloatMatrix2D.
1323      * @param dense FloatMatrix2D; the Dense FloatMatrix2D
1324      * @return SparseFloatMatrix2D
1325      */
1326     private static SparseFloatMatrix2D makeSparse(final FloatMatrix2D dense)
1327     {
1328         SparseFloatMatrix2D result = new SparseFloatMatrix2D(dense.rows(), dense.columns());
1329         result.assign(dense);
1330         return result;
1331     }
1332 
1333     /**
1334      * Create a Sparse version of a Dense FloatMatrix.
1335      * @param in FloatMatrix.Abs.Dense&lt;U&gt;; the Dense FloatMatrix
1336      * @param <U> Unit; the unit of the parameter and the result
1337      * @return MutableFloatMatrix.Abs.Sparse&lt;U&gt;
1338      */
1339     public static <U extends Unit<U>> MutableFloatMatrix.Abs.Sparse<U> denseToSparse(final FloatMatrix.Abs.Dense<U> in)
1340     {
1341         return new MutableFloatMatrix.Abs.Sparse<U>(makeSparse(in.getMatrixSI()), in.getUnit());
1342     }
1343 
1344     /**
1345      * Create a Sparse version of a Dense FloatMatrix.
1346      * @param in FloatMatrix.Rel.Dense&lt;U&gt;; the Dense FloatMatrix
1347      * @param <U> Unit; the unit of the parameter and the result
1348      * @return MutableFloatMatrix.Rel.Sparse&lt;U&gt;
1349      */
1350     public static <U extends Unit<U>> MutableFloatMatrix.Rel.Sparse<U> denseToSparse(final FloatMatrix.Rel.Dense<U> in)
1351     {
1352         return new MutableFloatMatrix.Rel.Sparse<U>(makeSparse(in.getMatrixSI()), in.getUnit());
1353     }
1354 
1355     /**
1356      * Make the Dense equivalent of a SparseFloatMatrix2D.
1357      * @param sparse FloatMatrix2D; the Sparse FloatMatrix2D
1358      * @return DenseFloatMatrix2D
1359      */
1360     private static DenseFloatMatrix2D makeDense(final FloatMatrix2D sparse)
1361     {
1362         DenseFloatMatrix2D result = new DenseFloatMatrix2D(sparse.rows(), sparse.columns());
1363         result.assign(sparse);
1364         return result;
1365     }
1366 
1367     /**
1368      * Create a Dense version of a Sparse FloatMatrix.
1369      * @param in FloatMatrix.Abs.Sparse&lt;U&gt;; the Sparse FloatMatrix
1370      * @param <U> Unit; the unit of the parameter and the result
1371      * @return MutableFloatMatrix.Abs.Dense&lt;U&gt;
1372      */
1373     public static <U extends Unit<U>> MutableFloatMatrix.Abs.Dense<U> sparseToDense(final FloatMatrix.Abs.Sparse<U> in)
1374     {
1375         return new MutableFloatMatrix.Abs.Dense<U>(makeDense(in.getMatrixSI()), in.getUnit());
1376     }
1377 
1378     /**
1379      * Create a Dense version of a Sparse FloatMatrix.
1380      * @param in FloatMatrix.Rel.Sparse&lt;U&gt;; the Sparse FloatMatrix
1381      * @param <U> Unit; the unit of the parameter and the result
1382      * @return MutableFloatMatrix.Rel.Dense&lt;U&gt;
1383      */
1384     public static <U extends Unit<U>> MutableFloatMatrix.Rel.Dense<U> sparseToDense(final FloatMatrix.Rel.Sparse<U> in)
1385     {
1386         return new MutableFloatMatrix.Rel.Dense<U>(makeDense(in.getMatrixSI()), in.getUnit());
1387     }
1388 
1389     /**
1390      * Interpolate between or extrapolate over two values.
1391      * @param zero FloatMatrix.Abs.Dense&lt;U&gt;; zero reference (returned when ratio == 0)
1392      * @param one FloatMatrix.Abs.Dense&lt;U&gt;; one reference (returned when ratio == 1)
1393      * @param ratio float; the ratio that determines where between (or outside) zero and one the result lies
1394      * @param <U> Unit; the unit of the parameters and the result
1395      * @return MutableFloatMatrix.Abs.Dense&lt;U&gt;
1396      * @throws ValueException when zero and one do not have the same size
1397      */
1398     public static <U extends Unit<U>> MutableFloatMatrix.Abs.Dense<U> interpolate(final FloatMatrix.Abs.Dense<U> zero,
1399             final FloatMatrix.Abs.Dense<U> one, final float ratio) throws ValueException
1400     {
1401         MutableFloatMatrix.Abs.Dense<U> result = zero.mutable();
1402         for (int row = result.rows(); --row >= 0;)
1403         {
1404             for (int column = result.columns(); --column >= 0;)
1405             {
1406                 result.setSI(row, column, result.getSI(row, column) * (1 - ratio) + one.getSI(row, column) * ratio);
1407             }
1408         }
1409         return result;
1410     }
1411 
1412     /**
1413      * Interpolate between or extrapolate over two values.
1414      * @param zero FloatMatrix.Rel.Dense&lt;U&gt;; zero reference (returned when ratio == 0)
1415      * @param one FloatMatrix.Rel.Dense&lt;U&gt;; one reference (returned when ratio == 1)
1416      * @param ratio float; the ratio that determines where between (or outside) zero and one the result lies
1417      * @param <U> Unit; the unit of the parameters and the result
1418      * @return MutableFloatMatrix.Rel.Dense&lt;U&gt;
1419      * @throws ValueException when zero and one do not have the same size
1420      */
1421     public static <U extends Unit<U>> MutableFloatMatrix.Rel.Dense<U> interpolate(final FloatMatrix.Rel.Dense<U> zero,
1422             final FloatMatrix.Rel.Dense<U> one, final float ratio) throws ValueException
1423     {
1424         MutableFloatMatrix.Rel.Dense<U> result = zero.mutable();
1425         for (int row = result.rows(); --row >= 0;)
1426         {
1427             for (int column = result.columns(); --column >= 0;)
1428             {
1429                 result.setSI(row, column, result.getSI(row, column) * (1 - ratio) + one.getSI(row, column) * ratio);
1430             }
1431         }
1432         return result;
1433     }
1434 
1435     /**
1436      * Interpolate between or extrapolate over two values.
1437      * @param zero FloatMatrix.Abs.Sparse&lt;U&gt;; zero reference (returned when ratio == 0)
1438      * @param one FloatMatrix.Abs.Sparse&lt;U&gt;; one reference (returned when ratio == 1)
1439      * @param ratio float; the ratio that determines where between (or outside) zero and one the result lies
1440      * @param <U> Unit; the unit of the parameters and the result
1441      * @return MutableFloatMatrix.Abs.Sparse&lt;U&gt;
1442      * @throws ValueException when zero and one do not have the same size
1443      */
1444     public static <U extends Unit<U>> MutableFloatMatrix.Abs.Sparse<U> interpolate(final FloatMatrix.Abs.Sparse<U> zero,
1445             final FloatMatrix.Abs.Sparse<U> one, final float ratio) throws ValueException
1446     {
1447         MutableFloatMatrix.Abs.Sparse<U> result = zero.mutable();
1448         for (int row = result.rows(); --row >= 0;)
1449         {
1450             for (int column = result.columns(); --column >= 0;)
1451             {
1452                 result.setSI(row, column, result.getSI(row, column) * (1 - ratio) + one.getSI(row, column) * ratio);
1453             }
1454         }
1455         return result;
1456     }
1457 
1458     /**
1459      * Interpolate between or extrapolate over two values.
1460      * @param zero FloatMatrix.Rel.Sparse&lt;U&gt;; zero reference (returned when ratio == 0)
1461      * @param one FloatMatrix.Rel.Sparse&lt;U&gt;; one reference (returned when ratio == 1)
1462      * @param ratio float; the ratio that determines where between (or outside) zero and one the result lies
1463      * @param <U> Unit; the unit of the parameters and the result
1464      * @return MutableFloatMatrix.Rel.Sparse&lt;U&gt;
1465      * @throws ValueException when zero and one do not have the same size
1466      */
1467     public static <U extends Unit<U>> MutableFloatMatrix.Rel.Sparse<U> interpolate(final FloatMatrix.Rel.Sparse<U> zero,
1468             final FloatMatrix.Rel.Sparse<U> one, final float ratio) throws ValueException
1469     {
1470         MutableFloatMatrix.Rel.Sparse<U> result = zero.mutable();
1471         for (int row = result.rows(); --row >= 0;)
1472         {
1473             for (int column = result.columns(); --column >= 0;)
1474             {
1475                 result.setSI(row, column, result.getSI(row, column) * (1 - ratio) + one.getSI(row, column) * ratio);
1476             }
1477         }
1478         return result;
1479     }
1480 
1481 }