View Javadoc
1   package org.djunits.value.vfloat.matrix;
2   
3   import java.io.Serializable;
4   
5   import org.djunits.unit.Unit;
6   import org.djunits.value.Relative;
7   import org.djunits.value.StorageType;
8   import org.djunits.value.ValueException;
9   import org.djunits.value.vfloat.scalar.AbstractFloatScalarRel;
10  
11  /**
12   * Relative Immutable typed matrix.
13   * <p>
14   * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
15   * BSD-style license. See <a href="http://djunits.org/docs/license.html">DJUNITS License</a>.
16   * <p>
17   * $LastChangedDate: 2015-09-29 14:14:28 +0200 (Tue, 29 Sep 2015) $, @version $Revision: 73 $, by $Author: pknoppers $, initial
18   * version Sep 5, 2015 <br>
19   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
20   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
21   * @param <U> the unit
22   * @param <R> the relative matrix type
23   * @param <MR> the mutable relative matrix type
24   * @param <S> the relative scalar type
25   */
26  abstract class AbstractFloatMatrixRel<U extends Unit<U>, R extends AbstractFloatMatrixRel<U, R, MR, S>,
27          MR extends AbstractMutableFloatMatrixRel<U, R, MR, S>, S extends AbstractFloatScalarRel<U, S>>
28          extends AbstractFloatMatrix<U, R> implements FloatMatrixInterface<U>, Relative, Serializable
29  {
30      /** */
31      private static final long serialVersionUID = 20151006L;
32  
33      /**
34       * Construct a new Relative Immutable FloatMatrix.
35       * @param values float[][]; the values of the entries in the new Relative Immutable FloatMatrix
36       * @param unit U; the unit of the new Relative Immutable FloatMatrix
37       * @param storageType the data type to use (e.g., DENSE or SPARSE)
38       * @throws ValueException when values is null
39       */
40      AbstractFloatMatrixRel(final float[][] values, final U unit, final StorageType storageType) throws ValueException
41      {
42          super(unit, FloatMatrixData.instantiate(ensureRectangularAndNonEmpty(values), unit.getScale(), storageType));
43      }
44  
45      /**
46       * Construct a new Relative Immutable FloatMatrix.
47       * @param values S[][]; the values of the entries in the new Relative Immutable FloatMatrix
48       * @param storageType the data type to use (e.g., DENSE or SPARSE)
49       * @throws ValueException when values has zero entries
50       */
51      AbstractFloatMatrixRel(final S[][] values, final StorageType storageType) throws ValueException
52      {
53          super(checkUnit(values), FloatMatrixData.instantiate(values, storageType));
54      }
55  
56      /**
57       * Construct a new Relative Immutable FloatMatrix.
58       * @param data an internal data object
59       * @param unit the unit
60       */
61      AbstractFloatMatrixRel(final FloatMatrixData data, final U unit)
62      {
63          super(unit, data.copy());
64      }
65  
66      /**
67       * Create a mutable version of this FloatMatrix. <br>
68       * The mutable version is created with a shallow copy of the data and the internal copyOnWrite flag set. The first operation
69       * in the mutable version that modifies the data shall trigger a deep copy of the data.
70       * @return MA; mutable version of this FloatMatrix
71       */
72      public MR mutable()
73      {
74          return instantiateMutableType(getData(), getUnit());
75      }
76  
77      /**
78       * Construct a new Relative Immutable FloatMatrix of the right type. Each extending class must implement this method.
79       * @param dmd an internal data object
80       * @param unit the unit
81       * @return M the Mutable FloatMatrix of the right type
82       */
83      protected abstract R instantiateType(FloatMatrixData dmd, U unit);
84  
85      /**
86       * Construct a new Relative Mutable FloatMatrix of the right type. Each extending class must implement this method.
87       * @param dmd an internal data object
88       * @param unit the unit
89       * @return M the Mutable FloatMatrix of the right type
90       */
91      protected abstract MR instantiateMutableType(FloatMatrixData dmd, U unit);
92  
93      /**
94       * Construct a new Relative Immutable FloatScalar of the right type. Each extending class must implement this method.
95       * @param value the value
96       * @param unit the unit
97       * @return S the Immutable FloatScalar of the right type
98       */
99      protected abstract S instantiateScalar(float value, U unit);
100 
101     /**
102      * Return the Scalar value at the index position.
103      * @param row the row position
104      * @param column the column position
105      * @return S the scalar
106      * @throws ValueException when index out of bounds
107      */
108     @SuppressWarnings("checkstyle:designforextension")
109     public final S get(final int row, final int column) throws ValueException
110     {
111         checkIndex(row, column);
112         return instantiateScalar(getInUnit(row, column, getUnit()), getUnit());
113     }
114 
115     /**********************************************************************************/
116     /**************************** TYPED CALCULATION METHODS ***************************/
117     /**********************************************************************************/
118 
119     /**
120      * Add a Relative value to this Relative value for a matrix or matrix. The addition is done value by value and store the
121      * result in a new Relative value. If both operands are sparse, the result is a sparse matrix or matrix, otherwise the
122      * result is a dense matrix or matrix.
123      * @param rel the right operand
124      * @return the addition of this matrix and the operand
125      * @throws ValueException in case this matrix or matrix and the operand have a different size
126      */
127     public final R plus(final R rel) throws ValueException
128     {
129         return instantiateType(this.getData().plus(rel.getData()), getUnit());
130     }
131 
132     /**
133      * Subtract a Relative value from this Relative value for a matrix or matrix. The subtraction is done value by value and
134      * store the result in a new Relative value. If both operands are sparse, the result is a sparse matrix or matrix, otherwise
135      * the result is a dense matrix or matrix.
136      * @param rel the right operand
137      * @return the subtraction of this matrix and the operand
138      * @throws ValueException in case this matrix or matrix and the operand have a different size
139      */
140     public final R minus(final R rel) throws ValueException
141     {
142         return instantiateType(this.getData().minus(rel.getData()), getUnit());
143     }
144 
145     /**
146      * Multiply a Relative value with this Relative value for a matrix or matrix. The multiplication is done value by value and
147      * store the result in a new Relative value. If both operands are dense, the result is a dense matrix or matrix, otherwise
148      * the result is a sparse matrix or matrix.
149      * @param rel the right operand
150      * @return the multiplication of this matrix and the operand
151      * @throws ValueException in case this matrix or matrix and the operand have a different size
152      */
153     public final R times(final R rel) throws ValueException
154     {
155         return instantiateType(this.getData().times(rel.getData()), getUnit());
156     }
157 
158     /**
159      * Divide this Relative value by a Relative value for a matrix or matrix. The division is done value by value and store the
160      * result in a new Relative value. If both operands are dense, the result is a dense matrix or matrix, otherwise the result
161      * is a sparse matrix or matrix.
162      * @param rel the right operand
163      * @return the division of this matrix and the operand
164      * @throws ValueException in case this matrix or matrix and the operand have a different size
165      */
166     public final R divide(final R rel) throws ValueException
167     {
168         return instantiateType(this.getData().divide(rel.getData()), getUnit());
169     }
170 
171     /* ============================================================================================ */
172     /* ============================= STATIC CONSTRUCTOR HELP METHODS ============================== */
173     /* ============================================================================================ */
174 
175     /**
176      * Check that a provided array can be used to create some descendant of a FloatMatrix, and return the Unit.
177      * @param dsArray the array to check and get the unit for
178      * @param <U> the unit
179      * @param <S> the scalar type
180      * @return the unit of the object
181      * @throws ValueException when the array is null, has length equal to 0, or has first entry with length equal to 0
182      */
183     static <U extends Unit<U>, S extends AbstractFloatScalarRel<U, S>> U checkUnit(final S[][] dsArray) throws ValueException
184     {
185         ensureRectangularAndNonEmpty(dsArray);
186         return dsArray[0][0].getUnit();
187     }
188 
189     /**
190      * Check that a 2D array of FloatScalar&lt;?&gt; is rectangular; i.e. all rows have the same length and is non empty.
191      * @param values FloatScalar&lt;?&gt;[][]; the 2D array to check
192      * @param <U> the unit
193      * @param <S> the scalar type
194      * @throws ValueException when values is not rectangular, or contains no data
195      */
196     protected static <U extends Unit<U>,
197             S extends AbstractFloatScalarRel<U, S>> void ensureRectangularAndNonEmpty(final S[][] values) throws ValueException
198     {
199         if (null == values)
200         {
201             throw new ValueException("Cannot create a FloatVector or MutableFloatVector from an empty array of FloatScalar");
202         }
203         if (0 == values.length || 0 == values[0].length)
204         {
205             throw new ValueException("Creating FloatVector or MutableFloatVector: "
206                     + "Cannot determine unit for FloatMatrix from an empty array of FloatScalar");
207         }
208         for (int row = values.length; --row >= 1;)
209         {
210             if (values[0].length != values[row].length)
211             {
212                 throw new ValueException("Creating FloatVector or MutableFloatVector: Lengths of rows are not all the same");
213             }
214         }
215     }
216 
217 }