View Javadoc
1   package org.djunits.value.vdouble.vector;
2   
3   import java.io.Serializable;
4   import java.util.List;
5   import java.util.SortedMap;
6   
7   import org.djunits.unit.Unit;
8   import org.djunits.value.Relative;
9   import org.djunits.value.StorageType;
10  import org.djunits.value.ValueException;
11  import org.djunits.value.vdouble.scalar.AbstractDoubleScalarRel;
12  
13  /**
14   * Relative Immutable typed vector.
15   * <p>
16   * Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
17   * BSD-style license. See <a href="http://djunits.org/docs/license.html">DJUNITS License</a>.
18   * <p>
19   * $LastChangedDate: 2015-09-29 14:14:28 +0200 (Tue, 29 Sep 2015) $, @version $Revision: 73 $, by $Author: pknoppers $, initial
20   * version Sep 5, 2015 <br>
21   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
22   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
23   * @param <U> the unit
24   * @param <R> the relative vector type
25   * @param <MR> the mutable relative vector type
26   * @param <S> the relative scalar type
27   */
28  abstract class AbstractDoubleVectorRel<U extends Unit<U>, R extends AbstractDoubleVectorRel<U, R, MR, S>,
29          MR extends AbstractMutableDoubleVectorRel<U, R, MR, S>, S extends AbstractDoubleScalarRel<U, S>>
30          extends AbstractDoubleVector<U, R> implements Relative, Serializable
31  {
32      /** */
33      private static final long serialVersionUID = 20151006L;
34  
35      /**
36       * Construct a new Relative Immutable DoubleVector.
37       * @param values double[]; the values of the entries in the new Relative Immutable DoubleVector
38       * @param unit U; the unit of the new Relative Immutable DoubleVector
39       * @param storageType the data type to use (e.g., DENSE or SPARSE)
40       * @throws ValueException when values is null
41       */
42      AbstractDoubleVectorRel(final double[] values, final U unit, final StorageType storageType) throws ValueException
43      {
44          super(unit, DoubleVectorData.instantiate(values, unit.getScale(), storageType));
45      }
46  
47      /**
48       * Construct a new Relative Immutable DoubleVector.
49       * @param values List; the values of the entries in the new Relative Immutable DoubleVector
50       * @param unit U; the unit of the new Relative Immutable DoubleVector
51       * @param storageType the data type to use (e.g., DENSE or SPARSE)
52       * @throws ValueException when values is null
53       */
54      AbstractDoubleVectorRel(final List<Double> values, final U unit, final StorageType storageType) throws ValueException
55      {
56          super(unit, DoubleVectorData.instantiate(values, unit.getScale(), storageType));
57      }
58  
59      /**
60       * Construct a new Relative Immutable DoubleVector.
61       * @param values DoubleScalar.Rel&lt;U&gt;[]; the values of the entries in the new Relative Immutable DoubleVector
62       * @param storageType the data type to use (e.g., DENSE or SPARSE)
63       * @throws ValueException when values has zero entries
64       */
65      AbstractDoubleVectorRel(final S[] values, final StorageType storageType) throws ValueException
66      {
67          super(checkUnit(values), DoubleVectorData.instantiate(values, storageType));
68      }
69  
70      /**
71       * Construct a new Relative Immutable DoubleVector.
72       * @param values List; the values of the entries in the new Relative Immutable DoubleVector
73       * @param storageType the data type to use (e.g., DENSE or SPARSE)
74       * @throws ValueException when values has zero entries
75       */
76      AbstractDoubleVectorRel(final List<S> values, final StorageType storageType) throws ValueException
77      {
78          super(checkUnit(values), DoubleVectorData.instantiateLD(values, storageType));
79      }
80  
81      /**
82       * Construct a new Relative Immutable DoubleVector.
83       * @param values DoubleScalar.Rel&lt;U&gt;[]; the values of the entries in the new Relative Sparse Mutable DoubleVector
84       * @param length the size of the vector
85       * @param storageType the data type to use (e.g., DENSE or SPARSE)
86       * @throws ValueException when values has zero entries
87       */
88      AbstractDoubleVectorRel(final SortedMap<Integer, S> values, final int length, final StorageType storageType)
89              throws ValueException
90      {
91          super(checkUnit(values), DoubleVectorData.instantiateMD(values, length, storageType));
92      }
93  
94      /**
95       * Construct a new Relative Immutable DoubleVector.
96       * @param values Map; the map of indexes to values of the Relative Sparse Mutable DoubleVector
97       * @param unit U; the unit of the new Relative Sparse Mutable DoubleVector
98       * @param length the size of the vector
99       * @param storageType the data type to use (e.g., DENSE or SPARSE)
100      * @throws ValueException when values is null
101      */
102     AbstractDoubleVectorRel(final SortedMap<Integer, Double> values, final U unit, final int length,
103             final StorageType storageType) throws ValueException
104     {
105         super(unit, DoubleVectorData.instantiate(values, length, unit.getScale(), storageType));
106     }
107 
108     /**
109      * Construct a new Relative Immutable DoubleVector.
110      * @param data an internal data object
111      * @param unit the unit
112      */
113     AbstractDoubleVectorRel(final DoubleVectorData data, final U unit)
114     {
115         super(unit, data.copy());
116     }
117 
118     /**
119      * Create a mutable version of this DoubleVector. <br>
120      * The mutable version is created with a shallow copy of the data and the internal copyOnWrite flag set. The first operation
121      * in the mutable version that modifies the data shall trigger a deep copy of the data.
122      * @return MR; mutable version of this DoubleVector
123      */
124     @Override
125     public MR mutable()
126     {
127         return instantiateMutableType(getData(), getUnit());
128     }
129 
130     /**
131      * Construct a new Relative Immutable DoubleVector of the right type. Each extending class must implement this method.
132      * @param dvd an internal data object
133      * @param unit the unit
134      * @return R the DoubleVector of the right type
135      */
136     protected abstract R instantiateType(DoubleVectorData dvd, U unit);
137 
138     /**
139      * Construct a new Relative Mutable DoubleVector of the right type. Each extending class must implement this method.
140      * @param dvd an internal data object
141      * @param unit the unit
142      * @return MR the Mutable DoubleVector of the right type
143      */
144     protected abstract MR instantiateMutableType(DoubleVectorData dvd, U unit);
145 
146     /**
147      * Construct a new Relative Immutable DoubleScalar of the right type. Each extending class must implement this method.
148      * @param value the value
149      * @param unit the unit
150      * @return S the Immutable DoubleScalar of the right type
151      */
152     protected abstract S instantiateScalar(double value, U unit);
153 
154     /** {@inheritDoc} */
155     @Override
156     public final S get(final int index) throws ValueException
157     {
158         return instantiateScalar(getInUnit(index, getUnit()), getUnit());
159     }
160 
161     /**********************************************************************************/
162     /**************************** TYPED CALCULATION METHODS ***************************/
163     /**********************************************************************************/
164 
165     /**
166      * Add a Relative value to this Relative value for a vector or matrix. The addition is done value by value and store the
167      * result in a new Relative value. If both operands are sparse, the result is a sparse vector or matrix, otherwise the
168      * result is a dense vector or matrix.
169      * @param rel the right operand
170      * @return the addition of this vector and the operand
171      * @throws ValueException in case this vector or matrix and the operand have a different size
172      */
173     public final R plus(final R rel) throws ValueException
174     {
175         return instantiateType(this.getData().plus(rel.getData()), getUnit());
176     }
177 
178     /**
179      * Subtract a Relative value from this Relative value for a vector or matrix. The subtraction is done value by value and
180      * store the result in a new Relative value. If both operands are sparse, the result is a sparse vector or matrix, otherwise
181      * the result is a dense vector or matrix.
182      * @param rel the right operand
183      * @return the subtraction of this vector and the operand
184      * @throws ValueException in case this vector or matrix and the operand have a different size
185      */
186     public final R minus(final R rel) throws ValueException
187     {
188         return instantiateType(this.getData().minus(rel.getData()), getUnit());
189     }
190 
191     /**
192      * Multiply a Relative value with this Relative value for a vector or matrix. The multiplication is done value by value and
193      * store the result in a new Relative value. If both operands are dense, the result is a dense vector or matrix, otherwise
194      * the result is a sparse vector or matrix.
195      * @param rel the right operand
196      * @return the multiplication of this vector and the operand
197      * @throws ValueException in case this vector or matrix and the operand have a different size
198      */
199     public final R times(final R rel) throws ValueException
200     {
201         return instantiateType(this.getData().times(rel.getData()), getUnit());
202     }
203 
204     /**
205      * Divide this Relative value by a Relative value for a vector or matrix. The division is done value by value and store the
206      * result in a new Relative value. If both operands are dense, the result is a dense vector or matrix, otherwise the result
207      * is a sparse vector or matrix.
208      * @param rel the right operand
209      * @return the division of this vector and the operand
210      * @throws ValueException in case this vector or matrix and the operand have a different size
211      */
212     public final R divide(final R rel) throws ValueException
213     {
214         return instantiateType(this.getData().divide(rel.getData()), getUnit());
215     }
216 
217     /* ============================================================================================ */
218     /* ============================= STATIC CONSTRUCTOR HELP METHODS ============================== */
219     /* ============================================================================================ */
220 
221     /**
222      * Check that a provided array can be used to create some descendant of a DoubleVector, and return the Unit.
223      * @param dsArray the array to check and get the unit for
224      * @param <U> the unit
225      * @param <S> the scalar type
226      * @return the unit of the object
227      * @throws ValueException when the array has length equal to 0
228      */
229     static <U extends Unit<U>, S extends AbstractDoubleScalarRel<U, S>> U checkUnit(
230             final AbstractDoubleScalarRel<U, S>[] dsArray) throws ValueException
231     {
232         if (dsArray != null && dsArray.length > 0)
233         {
234             return dsArray[0].getUnit();
235         }
236         throw new ValueException(
237                 "Cannot create a DoubleVector or MutableDoubleVector from a null or empty array of DoubleScalar");
238     }
239 
240     /**
241      * Check that a provided list can be used to create some descendant of a DoubleVector, and return the Unit.
242      * @param dsList the list to check and get the unit for
243      * @param <U> the unit
244      * @param <S> the scalar in the list
245      * @return the unit of the object
246      * @throws ValueException when the array has length equal to 0
247      */
248     static <U extends Unit<U>, S extends AbstractDoubleScalarRel<U, S>> U checkUnit(final List<S> dsList) throws ValueException
249     {
250         if (dsList != null && dsList.size() > 0)
251         {
252             return dsList.get(0).getUnit();
253         }
254         throw new ValueException(
255                 "Cannot create a DoubleVector or MutableDoubleVector from a null or empty list of DoubleScalar");
256     }
257 
258     /**
259      * Check that a provided Map can be used to create some descendant of a DoubleVector.
260      * @param dsMap the provided map
261      * @param <U> Unit; the unit of the DoubleScalar list
262      * @param <S> the scalar in the list
263      * @return List the provided list
264      * @throws ValueException when the list has size equal to 0
265      */
266     static <U extends Unit<U>, S extends AbstractDoubleScalarRel<U, S>> U checkUnit(final SortedMap<Integer, S> dsMap)
267             throws ValueException
268     {
269         if (dsMap != null && dsMap.size() > 0)
270         {
271             return dsMap.get(dsMap.firstKey()).getUnit();
272         }
273         throw new ValueException(
274                 "Cannot create a DoubleVector or MutableDoubleVector from a null or empty Map of DoubleScalar");
275     }
276 }