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     /** {@inheritDoc} */
102     @Override
103     @SuppressWarnings("checkstyle:designforextension")
104     public final S get(final int row, final int column) throws ValueException
105     {
106         checkIndex(row, column);
107         return instantiateScalar(getInUnit(row, column, getUnit()), getUnit());
108     }
109 
110     /**********************************************************************************/
111     /**************************** TYPED CALCULATION METHODS ***************************/
112     /**********************************************************************************/
113 
114     /**
115      * Add a Relative value to this Relative value for a matrix or matrix. The addition is done value by value and store the
116      * result in a new Relative value. If both operands are sparse, the result is a sparse matrix or matrix, otherwise the
117      * result is a dense matrix or matrix.
118      * @param rel the right operand
119      * @return the addition of this matrix and the operand
120      * @throws ValueException in case this matrix or matrix and the operand have a different size
121      */
122     public final R plus(final R rel) throws ValueException
123     {
124         return instantiateType(this.getData().plus(rel.getData()), getUnit());
125     }
126 
127     /**
128      * Subtract a Relative value from this Relative value for a matrix or matrix. The subtraction is done value by value and
129      * store the result in a new Relative value. If both operands are sparse, the result is a sparse matrix or matrix, otherwise
130      * the result is a dense matrix or matrix.
131      * @param rel the right operand
132      * @return the subtraction of this matrix and the operand
133      * @throws ValueException in case this matrix or matrix and the operand have a different size
134      */
135     public final R minus(final R rel) throws ValueException
136     {
137         return instantiateType(this.getData().minus(rel.getData()), getUnit());
138     }
139 
140     /**
141      * Multiply a Relative value with this Relative value for a matrix or matrix. The multiplication is done value by value and
142      * store the result in a new Relative value. If both operands are dense, the result is a dense matrix or matrix, otherwise
143      * the result is a sparse matrix or matrix.
144      * @param rel the right operand
145      * @return the multiplication of this matrix and the operand
146      * @throws ValueException in case this matrix or matrix and the operand have a different size
147      */
148     public final R times(final R rel) throws ValueException
149     {
150         return instantiateType(this.getData().times(rel.getData()), getUnit());
151     }
152 
153     /**
154      * Divide this Relative value by a Relative value for a matrix or matrix. The division is done value by value and store the
155      * result in a new Relative value. If both operands are dense, the result is a dense matrix or matrix, otherwise the result
156      * is a sparse matrix or matrix.
157      * @param rel the right operand
158      * @return the division of this matrix and the operand
159      * @throws ValueException in case this matrix or matrix and the operand have a different size
160      */
161     public final R divide(final R rel) throws ValueException
162     {
163         return instantiateType(this.getData().divide(rel.getData()), getUnit());
164     }
165 
166     /* ============================================================================================ */
167     /* ============================= STATIC CONSTRUCTOR HELP METHODS ============================== */
168     /* ============================================================================================ */
169 
170     /**
171      * Check that a provided array can be used to create some descendant of a FloatMatrix, and return the Unit.
172      * @param dsArray the array to check and get the unit for
173      * @param <U> the unit
174      * @param <S> the scalar type
175      * @return the unit of the object
176      * @throws ValueException when the array is null, has length equal to 0, or has first entry with length equal to 0
177      */
178     static <U extends Unit<U>, S extends AbstractFloatScalarRel<U, S>> U checkUnit(final S[][] dsArray) throws ValueException
179     {
180         ensureRectangularAndNonEmpty(dsArray);
181         return dsArray[0][0].getUnit();
182     }
183 
184     /**
185      * Check that a 2D array of FloatScalar&lt;?&gt; is rectangular; i.e. all rows have the same length and is non empty.
186      * @param values FloatScalar&lt;?&gt;[][]; the 2D array to check
187      * @param <U> the unit
188      * @param <S> the scalar type
189      * @throws ValueException when values is not rectangular, or contains no data
190      */
191     protected static <U extends Unit<U>,
192             S extends AbstractFloatScalarRel<U, S>> void ensureRectangularAndNonEmpty(final S[][] values) throws ValueException
193     {
194         if (null == values)
195         {
196             throw new ValueException("Cannot create a FloatVector or MutableFloatVector from an empty array of FloatScalar");
197         }
198         if (0 == values.length || 0 == values[0].length)
199         {
200             throw new ValueException("Creating FloatVector or MutableFloatVector: "
201                     + "Cannot determine unit for FloatMatrix from an empty array of FloatScalar");
202         }
203         for (int row = values.length; --row >= 1;)
204         {
205             if (values[0].length != values[row].length)
206             {
207                 throw new ValueException("Creating FloatVector or MutableFloatVector: Lengths of rows are not all the same");
208             }
209         }
210     }
211 
212 }