View Javadoc
1   package org.djunits.value.vfloat.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.vfloat.scalar.AbstractFloatScalarRel;
14  
15  /**
16   * Relative Immutable typed vector.
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-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 AbstractFloatVectorRel<U extends Unit<U>, R extends AbstractFloatVectorRel<U, R, MR, S>,
31          MR extends AbstractMutableFloatVectorRel<U, R, MR, S>, S extends AbstractFloatScalarRel<U, S>>
32          extends AbstractFloatVector<U, R> implements Relative, Serializable, Iterable<S>
33  {
34      /** */
35      private static final long serialVersionUID = 20151006L;
36  
37      /**
38       * Construct a new Relative Immutable FloatVector.
39       * @param values float[]; the values of the entries in the new Relative Immutable FloatVector
40       * @param unit U; the unit of the new Relative Immutable FloatVector
41       * @param storageType the data type to use (e.g., DENSE or SPARSE)
42       * @throws ValueException when values is null
43       */
44      AbstractFloatVectorRel(final float[] values, final U unit, final StorageType storageType) throws ValueException
45      {
46          super(unit, FloatVectorData.instantiate(values, unit.getScale(), storageType));
47      }
48  
49      /**
50       * Construct a new Relative Immutable FloatVector.
51       * @param values List; the values of the entries in the new Relative Immutable FloatVector
52       * @param unit U; the unit of the new Relative Immutable FloatVector
53       * @param storageType the data type to use (e.g., DENSE or SPARSE)
54       * @throws ValueException when values is null
55       */
56      AbstractFloatVectorRel(final List<Float> values, final U unit, final StorageType storageType) throws ValueException
57      {
58          super(unit, FloatVectorData.instantiate(values, unit.getScale(), storageType));
59      }
60  
61      /**
62       * Construct a new Relative Immutable FloatVector.
63       * @param values FloatScalar.Rel&lt;U&gt;[]; the values of the entries in the new Relative Immutable FloatVector
64       * @param storageType the data type to use (e.g., DENSE or SPARSE)
65       * @throws ValueException when values has zero entries
66       */
67      AbstractFloatVectorRel(final S[] values, final StorageType storageType) throws ValueException
68      {
69          super(checkUnit(values), FloatVectorData.instantiate(values, storageType));
70      }
71  
72      /**
73       * Construct a new Relative Immutable FloatVector.
74       * @param values List; the values of the entries in the new Relative Immutable FloatVector
75       * @param storageType the data type to use (e.g., DENSE or SPARSE)
76       * @throws ValueException when values has zero entries
77       */
78      AbstractFloatVectorRel(final List<S> values, final StorageType storageType) throws ValueException
79      {
80          super(checkUnit(values), FloatVectorData.instantiateLD(values, storageType));
81      }
82  
83      /**
84       * Construct a new Relative Immutable FloatVector.
85       * @param values FloatScalar.Rel&lt;U&gt;[]; the values of the entries in the new Relative Sparse Mutable FloatVector
86       * @param length the size of the vector
87       * @param storageType the data type to use (e.g., DENSE or SPARSE)
88       * @throws ValueException when values has zero entries
89       */
90      AbstractFloatVectorRel(final SortedMap<Integer, S> values, final int length, final StorageType storageType)
91              throws ValueException
92      {
93          super(checkUnit(values), FloatVectorData.instantiateMD(values, length, storageType));
94      }
95  
96      /**
97       * Construct a new Relative Immutable FloatVector.
98       * @param values Map; the map of indexes to values of the Relative Sparse Mutable FloatVector
99       * @param unit U; the unit of the new Relative Sparse Mutable FloatVector
100      * @param length the size of the vector
101      * @param storageType the data type to use (e.g., DENSE or SPARSE)
102      * @throws ValueException when values is null
103      */
104     AbstractFloatVectorRel(final SortedMap<Integer, Float> values, final U unit, final int length,
105             final StorageType storageType) throws ValueException
106     {
107         super(unit, FloatVectorData.instantiate(values, length, unit.getScale(), storageType));
108     }
109 
110     /**
111      * Construct a new Relative Immutable FloatVector.
112      * @param data an internal data object
113      * @param unit the unit
114      */
115     AbstractFloatVectorRel(final FloatVectorData data, final U unit)
116     {
117         super(unit, data.copy());
118     }
119 
120     /**
121      * Create a mutable version of this FloatVector. <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 FloatVector
125      */
126     @Override
127     public MR mutable()
128     {
129         return instantiateMutableType(getData(), getUnit());
130     }
131 
132     /**
133      * Construct a new Relative Immutable FloatVector of the right type. Each extending class must implement this method.
134      * @param dvd an internal data object
135      * @param unit the unit
136      * @return R the FloatVector of the right type
137      */
138     protected abstract R instantiateType(FloatVectorData dvd, U unit);
139 
140     /**
141      * Construct a new Relative Mutable FloatVector of the right type. Each extending class must implement this method.
142      * @param dvd an internal data object
143      * @param unit the unit
144      * @return MR the Mutable FloatVector of the right type
145      */
146     protected abstract MR instantiateMutableType(FloatVectorData dvd, U unit);
147 
148     /**
149      * Construct a new Relative Immutable FloatScalar of the right type. Each extending class must implement this method.
150      * @param value the value
151      * @param unit the unit
152      * @return S the Immutable FloatScalar of the right type
153      */
154     protected abstract S instantiateScalar(float value, U unit);
155 
156     /** {@inheritDoc} */
157     @Override
158     public 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 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 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 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 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 FloatVector, and return the Unit.
225      * @param dsArray 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 AbstractFloatScalarRel<U, S>> U checkUnit(final AbstractFloatScalarRel<U, S>[] dsArray)
232             throws ValueException
233     {
234         if (dsArray != null && dsArray.length > 0)
235         {
236             return dsArray[0].getUnit();
237         }
238         throw new ValueException("Cannot create a FloatVector or MutableFloatVector from a null or empty array of FloatScalar");
239     }
240 
241     /**
242      * Check that a provided list can be used to create some descendant of a FloatVector, and return the Unit.
243      * @param dsList the list to check and get the unit for
244      * @param <U> the unit
245      * @param <S> the scalar in the list
246      * @return the unit of the object
247      * @throws ValueException when the array has length equal to 0
248      */
249     static <U extends Unit<U>, S extends AbstractFloatScalarRel<U, S>> U checkUnit(final List<S> dsList) throws ValueException
250     {
251         if (dsList != null && dsList.size() > 0)
252         {
253             return dsList.get(0).getUnit();
254         }
255         throw new ValueException("Cannot create a FloatVector or MutableFloatVector from a null or empty list of FloatScalar");
256     }
257 
258     /**
259      * Check that a provided Map can be used to create some descendant of a FloatVector.
260      * @param dsMap the provided map
261      * @param <U> Unit; the unit of the FloatScalar 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 AbstractFloatScalarRel<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("Cannot create a FloatVector or MutableFloatVector from a null or empty Map of FloatScalar");
274     }
275 
276     /* ============================================================================================ */
277     /* =============================== ITERATOR METHODS AND CLASS ================================= */
278     /* ============================================================================================ */
279 
280     /**
281      * Returns an iterator over the scalars in this vector in proper sequence.
282      * @return an iterator over the scalars in this vector in proper sequence
283      */
284     @Override
285     public Iterator<S> iterator()
286     {
287         return new Itr();
288     }
289 
290     /**
291      * The iterator class is loosely based in AbstractList.Itr. It does not throw a ConcurrentModificationException, because the
292      * size of the vector does not change. Normal (non-mutable) vectors cannot change their size, nor their content. The only
293      * thing for the MutableVector that can change is its content, not its length.
294      */
295     protected class Itr implements Iterator<S>
296     {
297         /** index of next element to return. */
298         private int cursor = 0;
299 
300         @Override
301         public boolean hasNext()
302         {
303             return this.cursor != size();
304         }
305 
306         /** {@inheritDoc} */
307         @Override
308         public S next()
309         {
310             if (this.cursor >= size())
311             {
312                 throw new NoSuchElementException();
313             }
314             try
315             {
316                 int i = this.cursor;
317                 S next = get(i);
318                 this.cursor = i + 1;
319                 return next;
320             }
321             catch (ValueException exception)
322             {
323                 throw new RuntimeException(exception);
324             }
325         }
326 
327         /** {@inheritDoc} */
328         @Override
329         public void remove()
330         {
331             throw new RuntimeException("Remove function cannot be applied on fixed-size DJUNITS Vector");
332         }
333     }
334 
335 }