View Javadoc
1   package org.djunits.value.vdouble.vector;
2   
3   import java.io.Serializable;
4   import java.util.Iterator;
5   import java.util.List;
6   import java.util.NoSuchElementException;
7   import java.util.SortedMap;
8   
9   import org.djunits.unit.Unit;
10  import org.djunits.value.Relative;
11  import org.djunits.value.StorageType;
12  import org.djunits.value.ValueException;
13  import org.djunits.value.vdouble.scalar.AbstractDoubleScalarRel;
14  
15  /**
16   * Relative Immutable typed vector.
17   * <p>
18   * Copyright (c) 2013-2019 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-09-29 14:14:28 +0200 (Tue, 29 Sep 2015) $, @version $Revision: 73 $, by $Author: pknoppers $, initial
22   * version Sep 5, 2015 <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   * @param <U> the unit
26   * @param <R> the relative vector type
27   * @param <MR> the mutable relative vector type
28   * @param <S> the relative scalar type
29   */
30  abstract class AbstractDoubleVectorRel<U extends Unit<U>, R extends AbstractDoubleVectorRel<U, R, MR, S>,
31          MR extends AbstractMutableDoubleVectorRel<U, R, MR, S>, S extends AbstractDoubleScalarRel<U, S>>
32          extends AbstractDoubleVector<U, R> implements Relative, Serializable, Iterable<S>
33  {
34      /** */
35      private static final long serialVersionUID = 20151006L;
36  
37      /**
38       * Construct a new Relative Immutable DoubleVector.
39       * @param values double[]; the values of the entries in the new Relative Immutable DoubleVector
40       * @param unit U; the unit of the new Relative Immutable DoubleVector
41       * @param storageType StorageType; the data type to use (e.g., DENSE or SPARSE)
42       * @throws ValueException when values is null
43       */
44      AbstractDoubleVectorRel(final double[] values, final U unit, final StorageType storageType) throws ValueException
45      {
46          super(unit, DoubleVectorData.instantiate(values, unit.getScale(), storageType));
47      }
48  
49      /**
50       * Construct a new Relative Immutable DoubleVector.
51       * @param values List&lt;Double&gt;; the values of the entries in the new Relative Immutable DoubleVector
52       * @param unit U; the unit of the new Relative Immutable DoubleVector
53       * @param storageType StorageType; the data type to use (e.g., DENSE or SPARSE)
54       * @throws ValueException when values is null
55       */
56      AbstractDoubleVectorRel(final List<Double> values, final U unit, final StorageType storageType) throws ValueException
57      {
58          super(unit, DoubleVectorData.instantiate(values, unit.getScale(), storageType));
59      }
60  
61      /**
62       * Construct a new Relative Immutable DoubleVector.
63       * @param values S[]; the values of the entries in the new Relative Immutable DoubleVector
64       * @param storageType StorageType; the data type to use (e.g., DENSE or SPARSE)
65       * @throws ValueException when values has zero entries
66       */
67      AbstractDoubleVectorRel(final S[] values, final StorageType storageType) throws ValueException
68      {
69          super(checkUnit(values), DoubleVectorData.instantiate(values, storageType));
70      }
71  
72      /**
73       * Construct a new Relative Immutable DoubleVector.
74       * @param values List&lt;S&gt;; the values of the entries in the new Relative Immutable DoubleVector
75       * @param storageType StorageType; the data type to use (e.g., DENSE or SPARSE)
76       * @throws ValueException when values has zero entries
77       */
78      AbstractDoubleVectorRel(final List<S> values, final StorageType storageType) throws ValueException
79      {
80          super(checkUnit(values), DoubleVectorData.instantiateLD(values, storageType));
81      }
82  
83      /**
84       * Construct a new Relative Immutable DoubleVector.
85       * @param values SortedMap&lt;Integer, S&gt;; the values of the entries in the new Relative Sparse Mutable DoubleVector
86       * @param length int; the size of the vector
87       * @param storageType StorageType; the data type to use (e.g., DENSE or SPARSE)
88       * @throws ValueException when values has zero entries
89       */
90      AbstractDoubleVectorRel(final SortedMap<Integer, S> values, final int length, final StorageType storageType)
91              throws ValueException
92      {
93          super(checkUnit(values), DoubleVectorData.instantiateMD(values, length, storageType));
94      }
95  
96      /**
97       * Construct a new Relative Immutable DoubleVector.
98       * @param values SortedMap&lt;Integer, Double&gt;; the map of indexes to values of the Relative Sparse Mutable DoubleVector
99       * @param unit U; the unit of the new Relative Sparse Mutable DoubleVector
100      * @param length int; the size of the vector
101      * @param storageType StorageType; the data type to use (e.g., DENSE or SPARSE)
102      * @throws ValueException when values is null
103      */
104     AbstractDoubleVectorRel(final SortedMap<Integer, Double> values, final U unit, final int length,
105             final StorageType storageType) throws ValueException
106     {
107         super(unit, DoubleVectorData.instantiate(values, length, unit.getScale(), storageType));
108     }
109 
110     /**
111      * Construct a new Relative Immutable DoubleVector.
112      * @param data DoubleVectorData; an internal data object
113      * @param unit U; the unit
114      */
115     AbstractDoubleVectorRel(final DoubleVectorData data, final U unit)
116     {
117         super(unit, data.copy());
118     }
119 
120     /**
121      * Create a mutable version of this DoubleVector. <br>
122      * The mutable version is created with a shallow copy of the data and the internal copyOnWrite flag set. The first operation
123      * in the mutable version that modifies the data shall trigger a deep copy of the data.
124      * @return MR; mutable version of this DoubleVector
125      */
126     @Override
127     public MR mutable()
128     {
129         return instantiateMutableType(getData(), getUnit());
130     }
131 
132     /**
133      * Construct a new Relative Immutable DoubleVector of the right type. Each extending class must implement this method.
134      * @param dvd DoubleVectorData; an internal data object
135      * @param unit U; the unit
136      * @return R the DoubleVector of the right type
137      */
138     protected abstract R instantiateType(DoubleVectorData dvd, U unit);
139 
140     /**
141      * Construct a new Relative Mutable DoubleVector of the right type. Each extending class must implement this method.
142      * @param dvd DoubleVectorData; an internal data object
143      * @param unit U; the unit
144      * @return MR the Mutable DoubleVector of the right type
145      */
146     protected abstract MR instantiateMutableType(DoubleVectorData dvd, U unit);
147 
148     /**
149      * Construct a new Relative Immutable DoubleScalar of the right type. Each extending class must implement this method.
150      * @param value double; the value
151      * @param unit U; the unit
152      * @return S the Immutable DoubleScalar of the right type
153      */
154     protected abstract S instantiateScalar(double value, U unit);
155 
156     /** {@inheritDoc} */
157     @Override
158     public final S get(final int index) throws ValueException
159     {
160         return instantiateScalar(getInUnit(index, getUnit()), getUnit());
161     }
162 
163     /**********************************************************************************/
164     /**************************** TYPED CALCULATION METHODS ***************************/
165     /**********************************************************************************/
166 
167     /**
168      * Add a Relative value to this Relative value for a vector or matrix. The addition is done value by value and store the
169      * result in a new Relative value. If both operands are sparse, the result is a sparse vector or matrix, otherwise the
170      * result is a dense vector or matrix.
171      * @param rel R; the right operand
172      * @return the addition of this vector and the operand
173      * @throws ValueException in case this vector or matrix and the operand have a different size
174      */
175     public final R plus(final R rel) throws ValueException
176     {
177         return instantiateType(this.getData().plus(rel.getData()), getUnit());
178     }
179 
180     /**
181      * Subtract a Relative value from this Relative value for a vector or matrix. The subtraction is done value by value and
182      * store the result in a new Relative value. If both operands are sparse, the result is a sparse vector or matrix, otherwise
183      * the result is a dense vector or matrix.
184      * @param rel R; the right operand
185      * @return the subtraction of this vector and the operand
186      * @throws ValueException in case this vector or matrix and the operand have a different size
187      */
188     public final R minus(final R rel) throws ValueException
189     {
190         return instantiateType(this.getData().minus(rel.getData()), getUnit());
191     }
192 
193     /**
194      * Multiply a Relative value with this Relative value for a vector or matrix. The multiplication is done value by value and
195      * store the result in a new Relative value. If both operands are dense, the result is a dense vector or matrix, otherwise
196      * the result is a sparse vector or matrix.
197      * @param rel R; the right operand
198      * @return the multiplication of this vector and the operand
199      * @throws ValueException in case this vector or matrix and the operand have a different size
200      */
201     public final R times(final R rel) throws ValueException
202     {
203         return instantiateType(this.getData().times(rel.getData()), getUnit());
204     }
205 
206     /**
207      * Divide this Relative value by a Relative value for a vector or matrix. The division is done value by value and store the
208      * result in a new Relative value. If both operands are dense, the result is a dense vector or matrix, otherwise the result
209      * is a sparse vector or matrix.
210      * @param rel R; the right operand
211      * @return the division of this vector and the operand
212      * @throws ValueException in case this vector or matrix and the operand have a different size
213      */
214     public final R divide(final R rel) throws ValueException
215     {
216         return instantiateType(this.getData().divide(rel.getData()), getUnit());
217     }
218 
219     /* ============================================================================================ */
220     /* ============================= STATIC CONSTRUCTOR HELP METHODS ============================== */
221     /* ============================================================================================ */
222 
223     /**
224      * Check that a provided array can be used to create some descendant of a DoubleVector, and return the Unit.
225      * @param dsArray AbstractDoubleScalarRel&lt;U,S&gt;[]; the array to check and get the unit for
226      * @param <U> the unit
227      * @param <S> the scalar type
228      * @return the unit of the object
229      * @throws ValueException when the array has length equal to 0
230      */
231     static <U extends Unit<U>, S extends AbstractDoubleScalarRel<U, S>> U checkUnit(
232             final AbstractDoubleScalarRel<U, S>[] dsArray) throws ValueException
233     {
234         if (dsArray != null && dsArray.length > 0)
235         {
236             return dsArray[0].getUnit();
237         }
238         throw new ValueException(
239                 "Cannot create a DoubleVector or MutableDoubleVector from a null or empty array of DoubleScalar");
240     }
241 
242     /**
243      * Check that a provided list can be used to create some descendant of a DoubleVector, and return the Unit.
244      * @param dsList List&lt;S&gt;; the list to check and get the unit for
245      * @param <U> the unit
246      * @param <S> the scalar in the list
247      * @return the unit of the object
248      * @throws ValueException when the array has length equal to 0
249      */
250     static <U extends Unit<U>, S extends AbstractDoubleScalarRel<U, S>> U checkUnit(final List<S> dsList) throws ValueException
251     {
252         if (dsList != null && dsList.size() > 0)
253         {
254             return dsList.get(0).getUnit();
255         }
256         throw new ValueException(
257                 "Cannot create a DoubleVector or MutableDoubleVector from a null or empty list of DoubleScalar");
258     }
259 
260     /**
261      * Check that a provided Map can be used to create some descendant of a DoubleVector.
262      * @param dsMap SortedMap&lt;Integer,S&gt;; the provided map
263      * @param <U> Unit; the unit of the DoubleScalar list
264      * @param <S> the scalar in the list
265      * @return List the provided list
266      * @throws ValueException when the list has size equal to 0
267      */
268     static <U extends Unit<U>, S extends AbstractDoubleScalarRel<U, S>> U checkUnit(final SortedMap<Integer, S> dsMap)
269             throws ValueException
270     {
271         if (dsMap != null && dsMap.size() > 0)
272         {
273             return dsMap.get(dsMap.firstKey()).getUnit();
274         }
275         throw new ValueException(
276                 "Cannot create a DoubleVector or MutableDoubleVector from a null or empty Map of DoubleScalar");
277     }
278 
279     /* ============================================================================================ */
280     /* =============================== ITERATOR METHODS AND CLASS ================================= */
281     /* ============================================================================================ */
282 
283     /**
284      * Returns an iterator over the scalars in this vector in proper sequence.
285      * @return an iterator over the scalars in this vector in proper sequence
286      */
287     @Override
288     public Iterator<S> iterator()
289     {
290         return new Itr();
291     }
292 
293     /**
294      * The iterator class is loosely based in AbstractList.Itr. It does not throw a ConcurrentModificationException, because the
295      * size of the vector does not change. Normal (non-mutable) vectors cannot change their size, nor their content. The only
296      * thing for the MutableVector that can change is its content, not its length.
297      */
298     protected class Itr implements Iterator<S>
299     {
300         /** index of next element to return. */
301         private int cursor = 0;
302 
303         @Override
304         public boolean hasNext()
305         {
306             return this.cursor != size();
307         }
308 
309         /** {@inheritDoc} */
310         @Override
311         public S next()
312         {
313             if (this.cursor >= size())
314             {
315                 throw new NoSuchElementException();
316             }
317             try
318             {
319                 int i = this.cursor;
320                 S next = get(i);
321                 this.cursor = i + 1;
322                 return next;
323             }
324             catch (ValueException exception)
325             {
326                 throw new RuntimeException(exception);
327             }
328         }
329 
330         /** {@inheritDoc} */
331         @Override
332         public void remove()
333         {
334             throw new RuntimeException("Remove function cannot be applied on fixed-size DJUNITS Vector");
335         }
336     }
337 
338 }