View Javadoc
1   package org.djunits.value.vfloat.matrix;
2   
3   import org.djunits.unit.Unit;
4   import org.djunits.value.Absolute;
5   import org.djunits.value.AbstractValue;
6   import org.djunits.value.Mutable;
7   import org.djunits.value.StorageType;
8   import org.djunits.value.ValueException;
9   import org.djunits.value.ValueUtil;
10  import org.djunits.value.formatter.Format;
11  import org.ojalgo.access.Access2D.Factory;
12  import org.ojalgo.matrix.BasicMatrix;
13  import org.ojalgo.matrix.PrimitiveMatrix;
14  
15  /**
16   * The most basic abstract class for the FloatMatrix.
17   * <p>
18   * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
19   * BSD-style license. See <a href="http://djunits.org/docs/license.html">DJUNITS License</a>.
20   * </p>
21   * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
22   * initial version Oct 16, 2016 <br>
23   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
24   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
25   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
26   * @param <U> the unit
27   * @param <T> the type
28   */
29  public abstract class AbstractFloatMatrix<U extends Unit<U>, T extends AbstractFloatMatrix<U, T>> extends AbstractValue<U>
30          implements FloatMatrixInterface<U>
31  {
32      /** */
33      private static final long serialVersionUID = 20161015L;
34  
35      /** The stored data as an object, can be sparse or dense. */
36      @SuppressWarnings("checkstyle:visibilitymodifier")
37      protected FloatMatrixData data;
38  
39      /**
40       * Construct a new FloatMatrix.
41       * @param unit the unit
42       * @param data an internal data object
43       */
44      AbstractFloatMatrix(final U unit, final FloatMatrixData data)
45      {
46          super(unit);
47          this.data = data;
48      }
49  
50      /**
51       * @return the internal data -- can only be used within package and by subclasses.
52       */
53      protected final FloatMatrixData getData()
54      {
55          return this.data;
56      }
57  
58      /**
59       * Return the StorageType (DENSE, SPARSE, etc.) for the stored Matrix.
60       * @return the StorageType (DENSE, SPARSE, etc.) for the stored Matrix
61       */
62      public final StorageType getStorageType()
63      {
64          return this.data.getStorageType();
65      }
66  
67      /** {@inheritDoc} */
68      @Override
69      public final float[][] getValuesSI()
70      {
71          return this.data.getDenseMatrixSI();
72      }
73  
74      /** {@inheritDoc} */
75      @Override
76      public final float[][] getValuesInUnit()
77      {
78          return getValuesInUnit(getUnit());
79      }
80  
81      /** {@inheritDoc} */
82      @Override
83      public final float[][] getValuesInUnit(final U targetUnit)
84      {
85          float[][] values = getValuesSI();
86          for (int row = rows(); --row >= 0;)
87          {
88              for (int column = columns(); --column >= 0;)
89              {
90                  values[row][column] = (float) ValueUtil.expressAsUnit(values[row][column], targetUnit);
91              }
92          }
93          return values;
94      }
95  
96      /** {@inheritDoc} */
97      @Override
98      public final int rows()
99      {
100         return this.data.rows();
101     }
102 
103     /** {@inheritDoc} */
104     @Override
105     public final int columns()
106     {
107         return this.data.cols();
108     }
109 
110     /** {@inheritDoc} */
111     @Override
112     public final float getSI(final int row, final int column) throws ValueException
113     {
114         checkIndex(row, column);
115         return this.data.getSI(row, column);
116     }
117 
118     /** {@inheritDoc} */
119     @Override
120     public final float getInUnit(final int row, final int column) throws ValueException
121     {
122         return (float) expressAsSpecifiedUnit(getSI(row, column));
123     }
124 
125     /** {@inheritDoc} */
126     @Override
127     public final float getInUnit(final int row, final int column, final U targetUnit) throws ValueException
128     {
129         return (float) ValueUtil.expressAsUnit(getSI(row, column), targetUnit);
130     }
131 
132     /** {@inheritDoc} */
133     @Override
134     public final float zSum()
135     {
136         return this.data.zSum();
137     }
138 
139     /** {@inheritDoc} */
140     @Override
141     public final int cardinality()
142     {
143         return this.data.cardinality();
144     }
145 
146     /** {@inheritDoc} */
147     @Override
148     public final String toString()
149     {
150         return toString(getUnit(), false, true);
151     }
152 
153     /** {@inheritDoc} */
154     @Override
155     public final String toString(final U displayUnit)
156     {
157         return toString(displayUnit, false, true);
158     }
159 
160     /** {@inheritDoc} */
161     @Override
162     public final String toString(final boolean verbose, final boolean withUnit)
163     {
164         return toString(getUnit(), verbose, withUnit);
165     }
166 
167     /** {@inheritDoc} */
168     @Override
169     public final String toString(final U displayUnit, final boolean verbose, final boolean withUnit)
170     {
171         StringBuffer buf = new StringBuffer();
172         if (verbose)
173         {
174             String ab = this instanceof Absolute ? "Abs " : "Rel ";
175             String ds = this.data.isDense() ? "Dense  " : this.data.isSparse() ? "Sparse " : "?????? ";
176             if (this instanceof Mutable)
177             {
178                 buf.append("Mutable   " + ab + ds);
179             }
180             else
181             {
182                 buf.append("Immutable " + ab + ds);
183             }
184         }
185         for (int row = 0; row < rows(); row++)
186         {
187             buf.append("\r\n\t");
188             for (int column = 0; column < columns(); column++)
189             {
190                 try
191                 {
192                     float d = (float) ValueUtil.expressAsUnit(getSI(row, column), displayUnit);
193                     buf.append(" " + Format.format(d));
194                 }
195                 catch (ValueException ve)
196                 {
197                     buf.append(" " + "********************".substring(0, Format.DEFAULTSIZE));
198                 }
199             }
200         }
201         buf.append("\n");
202         if (withUnit)
203         {
204             buf.append(displayUnit.getAbbreviation());
205         }
206         return buf.toString();
207     }
208 
209     /**
210      * Check that a 2D array of float is not null and rectangular; i.e. all rows have the same length.
211      * @param values float[][]; the 2D array to check
212      * @return the values in case the method is used in a constructor
213      * @throws ValueException when not all rows have the same length
214      */
215     protected static float[][] ensureRectangularAndNonEmpty(final float[][] values) throws ValueException
216     {
217         if (null == values)
218         {
219             throw new ValueException("Cannot create a FloatVector or MutableFloatVector from a null array of float[][]");
220         }
221         if (values.length > 0 && null == values[0])
222         {
223             throw new ValueException("Creating FloatVector or MutableFloatVector: Row 0 is null");
224         }
225         for (int row = values.length; --row >= 1;)
226         {
227             if (null == values[row] || values[0].length != values[row].length)
228             {
229                 throw new ValueException("Creating FloatVector or MutableFloatVector: Lengths of rows are not all the same");
230             }
231         }
232         return values;
233     }
234 
235     /**
236      * Centralized size equality check.
237      * @param other FloatMatrix&lt;?&gt;; other FloatMatrix
238      * @throws ValueException when other is null, or matrices have unequal size
239      */
240     protected final void checkSize(final AbstractFloatMatrixRel<?, ?, ?, ?> other) throws ValueException
241     {
242         if (null == other)
243         {
244             throw new ValueException("other is null");
245         }
246         if (rows() != other.rows() || columns() != other.columns())
247         {
248             throw new ValueException("The matrices have different sizes: " + rows() + "x" + columns() + " != " + other.rows()
249                     + "x" + other.columns());
250         }
251     }
252 
253     /**
254      * Centralized size equality check.
255      * @param other float[][]; array of float
256      * @throws ValueException when matrices have unequal size
257      */
258     protected final void checkSize(final float[][] other) throws ValueException
259     {
260         ensureRectangularAndNonEmpty(other);
261         final int otherColumns = other[0].length;
262         if (rows() != other.length || columns() != otherColumns)
263         {
264             throw new ValueException("The matrix and the array have different sizes: " + rows() + "x" + columns() + " != "
265                     + other.length + "x" + otherColumns);
266         }
267     }
268 
269     /**
270      * Check that provided row and column indices are valid.
271      * @param row int; the row value to check
272      * @param column int; the column value to check
273      * @throws ValueException when row or column is invalid
274      */
275     protected final void checkIndex(final int row, final int column) throws ValueException
276     {
277         if (row < 0 || row >= rows() || column < 0 || column >= columns())
278         {
279             throw new ValueException("index out of range (valid range is 0.." + (rows() - 1) + ", 0.." + (columns() - 1)
280                     + ", got " + row + ", " + column + ")");
281         }
282     }
283 
284     /** {@inheritDoc} */
285     @Override
286     public final float determinant() throws ValueException
287     {
288         try
289         {
290             final Factory<PrimitiveMatrix> matrixFactory = PrimitiveMatrix.FACTORY;
291             final BasicMatrix m = matrixFactory.rows(this.data.getDoubleDenseMatrixSI());
292             return (float) m.getDeterminant().doubleValue();
293         }
294         catch (IllegalArgumentException exception)
295         {
296             throw new ValueException(exception); // Matrix must be square
297         }
298     }
299 
300     /** {@inheritDoc} */
301     @Override
302     @SuppressWarnings("checkstyle:designforextension")
303     public int hashCode()
304     {
305         final int prime = 31;
306         int result = getUnit().getStandardUnit().hashCode();
307         result = prime * result + ((this.data == null) ? 0 : this.data.hashCode());
308         return result;
309     }
310 
311     /** {@inheritDoc} */
312     @Override
313     @SuppressWarnings({ "checkstyle:designforextension", "checkstyle:needbraces", "unchecked" })
314     public boolean equals(final Object obj)
315     {
316         if (this == obj)
317             return true;
318         if (obj == null)
319             return false;
320         if (getClass() != obj.getClass())
321             return false;
322         AbstractFloatMatrix<U, T> other = (AbstractFloatMatrix<U, T>) obj;
323         if (!getUnit().getStandardUnit().equals(other.getUnit().getStandardUnit()))
324             return false;
325         if (this.data == null)
326         {
327             if (other.data != null)
328                 return false;
329         }
330         else if (!this.data.equals(other.data))
331             return false;
332         return true;
333     }
334 
335 }