View Javadoc
1   package org.djunits.value.vfloat.vector;
2   
3   import java.util.List;
4   import java.util.SortedMap;
5   
6   import org.djunits.unit.AbsoluteLinearUnit;
7   import org.djunits.unit.Unit;
8   import org.djunits.value.MathFunctionsAbs;
9   import org.djunits.value.Mutable;
10  import org.djunits.value.StorageType;
11  import org.djunits.value.ValueException;
12  import org.djunits.value.ValueUtil;
13  import org.djunits.value.vfloat.FloatFunction;
14  import org.djunits.value.vfloat.FloatMathFunctions;
15  import org.djunits.value.vfloat.scalar.AbstractFloatScalarAbs;
16  
17  /**
18   * Absolute Mutable typed Vector.
19   * <p>
20   * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
21   * BSD-style license. See <a href="http://djunits.org/docs/license.html">DJUNITS License</a>.
22   * <p>
23   * $LastChangedDate: 2015-09-29 14:14:28 +0200 (Tue, 29 Sep 2015) $, @version $Revision: 73 $, by $Author: pknoppers $, initial
24   * version Sep 5, 2015 <br>
25   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
26   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
27   * @param <AU> the absolute unit
28   * @param <RU> the relative unit
29   * @param <A> the absolute vector type
30   * @param <R> the relative vector type
31   * @param <MA> the mutable absolute vector type
32   * @param <S> the absolute scalar type
33   */
34  abstract class AbstractMutableFloatVectorAbs<AU extends AbsoluteLinearUnit<AU, RU>, RU extends Unit<RU>,
35          A extends AbstractFloatVectorAbs<AU, RU, A, R, MA, S>, R extends AbstractFloatVectorRel<RU, R, ?, ?>,
36          MA extends AbstractMutableFloatVectorAbs<AU, RU, A, R, MA, S>, S extends AbstractFloatScalarAbs<AU, S, RU, ?>>
37          extends AbstractFloatVectorAbs<AU, RU, A, R, MA, S>
38          implements Mutable, MathFunctionsAbs<MA>, FloatMathFunctions<MA>, MutableFloatVectorInterface<AU>
39  {
40      /** */
41      private static final long serialVersionUID = 20151006L;
42  
43      /** If set, any modification of the data must be preceded by replacing the data with a local copy. */
44      private boolean copyOnWrite = false;
45  
46      /**
47       * Construct a new Absolute Mutable FloatVector.
48       * @param values float[]; the values of the entries in the new Absolute Mutable FloatVector
49       * @param unit AU; the unit of the new Absolute Mutable FloatVector
50       * @param storageType StorageType; the data type to use (e.g., DENSE or SPARSE)
51       * @throws ValueException when values is null
52       */
53      AbstractMutableFloatVectorAbs(final float[] values, final AU unit, final StorageType storageType) throws ValueException
54      {
55          super(values, unit, storageType);
56      }
57  
58      /**
59       * Construct a new Absolute Mutable FloatVector.
60       * @param values List&lt;Float&gt;; the values of the entries in the new Absolute Mutable FloatVector
61       * @param unit AU; the unit of the new Absolute Mutable FloatVector
62       * @param storageType StorageType; the data type to use (e.g., DENSE or SPARSE)
63       * @throws ValueException when values is null
64       */
65      AbstractMutableFloatVectorAbs(final List<Float> values, final AU unit, final StorageType storageType) throws ValueException
66      {
67          super(values, unit, storageType);
68      }
69  
70      /**
71       * Construct a new Absolute Mutable FloatVector.
72       * @param values S[]; the values of the entries in the new Absolute Mutable FloatVector
73       * @param storageType StorageType; the data type to use (e.g., DENSE or SPARSE)
74       * @throws ValueException when values has zero entries
75       */
76      AbstractMutableFloatVectorAbs(final S[] values, final StorageType storageType) throws ValueException
77      {
78          super(values, storageType);
79      }
80  
81      /**
82       * Construct a new Absolute Mutable FloatVector.
83       * @param values List&lt;S&gt;; the values of the entries in the new Absolute Mutable FloatVector
84       * @param storageType StorageType; the data type to use (e.g., DENSE or SPARSE)
85       * @throws ValueException when values has zero entries
86       */
87      AbstractMutableFloatVectorAbs(final List<S> values, final StorageType storageType) throws ValueException
88      {
89          super(values, storageType);
90      }
91  
92      /**
93       * Construct a new Absolute Mutable FloatVector.
94       * @param values SortedMap&lt;Integer, S&gt;; the values of the entries in the new Absolute Sparse Mutable FloatVector
95       * @param length int; the size of the vector
96       * @param storageType StorageType; the data type to use (e.g., DENSE or SPARSE)
97       * @throws ValueException when values has zero entries
98       */
99      AbstractMutableFloatVectorAbs(final SortedMap<Integer, S> values, final int length, final StorageType storageType)
100             throws ValueException
101     {
102         super(values, length, storageType);
103     }
104 
105     /**
106      * Construct a new Absolute Mutable FloatVector.
107      * @param values SortedMap&lt;Integer, Float&gt;; the map of indexes to values of the Absolute Sparse Mutable FloatVector
108      * @param unit AU; the unit of the new Absolute Sparse Mutable FloatVector
109      * @param length int; the size of the vector
110      * @param storageType StorageType; the data type to use (e.g., DENSE or SPARSE)
111      * @throws ValueException when values is null
112      */
113     AbstractMutableFloatVectorAbs(final SortedMap<Integer, Float> values, final AU unit, final int length,
114             final StorageType storageType) throws ValueException
115     {
116         super(values, unit, length, storageType);
117     }
118 
119     /**
120      * Construct a new Absolute Mutable FloatVector.
121      * @param data FloatVectorData; an internal data object
122      * @param unit AU; the unit
123      */
124     AbstractMutableFloatVectorAbs(final FloatVectorData data, final AU unit)
125     {
126         super(data, unit);
127     }
128 
129     /**
130      * Retrieve the value of the copyOnWrite flag.
131      * @return boolean
132      */
133     private boolean isCopyOnWrite()
134     {
135         return this.copyOnWrite;
136     }
137 
138     /**
139      * Change the copyOnWrite flag.
140      * @param copyOnWrite boolean; the new value for the copyOnWrite flag
141      */
142     final void setCopyOnWrite(final boolean copyOnWrite)
143     {
144         this.copyOnWrite = copyOnWrite;
145     }
146 
147     /** {@inheritDoc} */
148     @Override
149     public final MA mutable()
150     {
151         setCopyOnWrite(true);
152         final MA result = instantiateMutableType(getData(), getUnit());
153         result.setCopyOnWrite(true);
154         return result;
155     }
156 
157     /**
158      * Create a immutable version of this MutableFloatVector. <br>
159      * @return FloatVector&lt;U&gt;; mutable version of this MutableFloatVector
160      */
161     @Override
162     public A immutable()
163     {
164         setCopyOnWrite(true);
165         return instantiateTypeAbs(getData(), getUnit());
166     }
167 
168     /**********************************************************************************/
169     /**************************** TYPED CALCULATION METHODS ***************************/
170     /**********************************************************************************/
171 
172     /**
173      * Create a deep copy of this MutableFloatVector. <br>
174      * @return FloatVector&lt;U&gt;; deep copy of this MutableFloatVector
175      */
176     public final MA copy()
177     {
178         return mutable();
179     }
180 
181     /**
182      * Increment the value by the supplied value and return the changed vector.
183      * @param increment R; amount by which the value is incremented
184      * @return the changed MutableFloatVector.Rel&lt;U&gt;
185      * @throws ValueException when the size of increment is not identical to the size of this
186      */
187     @SuppressWarnings("unchecked")
188     public final MA incrementBy(final R increment) throws ValueException
189     {
190         checkCopyOnWrite();
191         this.data.incrementBy(increment.getData());
192         return (MA) this;
193     }
194 
195     /**
196      * Increment the value by the supplied value and return the changed vector.
197      * @param increment S; amount by which the value is incremented
198      * @return the changed MutableFloatVector.Rel&lt;U&gt;
199      */
200     public final MA incrementBy(final S increment)
201     {
202         return incrementBy(increment.si);
203     }
204 
205     /**
206      * Increment the value by the supplied constant and return the changed vector.
207      * @param increment float; amount by which the value is incremented
208      * @return the changed MutableFloatVector.Rel&lt;U&gt;
209      */
210     @SuppressWarnings("unchecked")
211     public final MA incrementBy(final float increment)
212     {
213         checkCopyOnWrite();
214         this.data.incrementBy(increment);
215         return (MA) this;
216     }
217 
218     /**
219      * Decrement the value by the supplied value and return the changed vector.
220      * @param decrement R; amount by which the value is decremented
221      * @return the changed MutableFloatVector.Rel&lt;U&gt;
222      * @throws ValueException when the size of increment is not identical to the size of this
223      */
224     @SuppressWarnings("unchecked")
225     public final MA decrementBy(final R decrement) throws ValueException
226     {
227         checkCopyOnWrite();
228         this.data.decrementBy(decrement.getData());
229         return (MA) this;
230     }
231 
232     /**
233      * Decrement the value by the supplied value and return the changed vector.
234      * @param decrement S; amount by which the value is decremented
235      * @return the changed MutableFloatVector.Rel&lt;U&gt;
236      */
237     public final MA decrementBy(final S decrement)
238     {
239         return decrementBy(decrement.si);
240     }
241 
242     /**
243      * Decrement the value by the supplied constant and return the changed vector.
244      * @param decrement float; amount by which the value is decremented
245      * @return the changed MutableFloatVector.Rel&lt;U&gt;
246      */
247     @SuppressWarnings("unchecked")
248     public final MA decrementBy(final float decrement)
249     {
250         checkCopyOnWrite();
251         this.data.decrementBy(decrement);
252         return (MA) this;
253     }
254 
255     /** {@inheritDoc} */
256     @SuppressWarnings("unchecked")
257     @Override
258     public final MA multiplyBy(final float factor)
259     {
260         checkCopyOnWrite();
261         this.data.multiplyBy(factor);
262         return (MA) this;
263     }
264 
265     /** {@inheritDoc} */
266     @Override
267     @SuppressWarnings({ "checkstyle:designforextension", "unchecked" })
268     public MA divideBy(final float factor)
269     {
270         this.data.divideBy(factor);
271         return (MA) this;
272     }
273 
274     /**
275      * Multiply the values in the vector by the supplied values and return the changed vector.
276      * @param factors R; amounts by which the value is multiplied
277      * @return the changed MutableFloatVector.Rel&lt;U&gt;
278      * @throws ValueException when the size of the factors is not identical to the size of this
279      */
280     @SuppressWarnings("unchecked")
281     public final MA multiplyBy(final R factors) throws ValueException
282     {
283         checkCopyOnWrite();
284         this.data.multiplyBy(factors.getData());
285         return (MA) this;
286     }
287 
288     /**********************************************************************************/
289     /********************************** MATH METHODS **********************************/
290     /**********************************************************************************/
291 
292     /**
293      * Execute a function on a cell by cell basis. Note: because many functions have to act on zero cells or can generate cells
294      * with a zero value, the functions have to be applied on a dense dataset which has to be transformed back to a sparse
295      * dataset if necessary.
296      * @param floatFunction FloatFunction; the function to apply
297      */
298     public final void assign(final FloatFunction floatFunction)
299     {
300         checkCopyOnWrite();
301         if (this.data instanceof FloatVectorDataDense)
302         {
303             ((FloatVectorDataDense) this.data).assign(floatFunction);
304         }
305         else
306         {
307             FloatVectorDataDense dvdd = ((FloatVectorDataSparse) this.data).toDense();
308             dvdd.assign(floatFunction);
309             this.data = dvdd.toSparse();
310         }
311     }
312 
313     /** {@inheritDoc} */
314     @Override
315     @SuppressWarnings("unchecked")
316     public final MA ceil()
317     {
318         assign(FloatMathFunctions.CEIL);
319         return (MA) this;
320     }
321 
322     /** {@inheritDoc} */
323     @Override
324     @SuppressWarnings("unchecked")
325     public final MA floor()
326     {
327         assign(FloatMathFunctions.FLOOR);
328         return (MA) this;
329     }
330 
331     /** {@inheritDoc} */
332     @Override
333     @SuppressWarnings("unchecked")
334     public final MA rint()
335     {
336         assign(FloatMathFunctions.RINT);
337         return (MA) this;
338     }
339 
340     /** {@inheritDoc} */
341     @Override
342     @SuppressWarnings("unchecked")
343     public final MA round()
344     {
345         assign(FloatMathFunctions.ROUND);
346         return (MA) this;
347     }
348 
349     /**
350      * Check the copyOnWrite flag and, if it is set, make a deep copy of the data and clear the flag.
351      */
352     protected final void checkCopyOnWrite()
353     {
354         if (isCopyOnWrite())
355         {
356             this.data = this.data.copy();
357             setCopyOnWrite(false);
358         }
359     }
360 
361     /**
362      * Replace the value at index by the supplied value which is expressed in the standard SI unit.
363      * @param index int; index of the value to replace
364      * @param valueSI float; the value to store (expressed in the standard SI unit)
365      * @throws ValueException when index out of range (index &lt; 0 or index &gt;= size())
366      */
367     public final void setSI(final int index, final float valueSI) throws ValueException
368     {
369         checkIndex(index);
370         checkCopyOnWrite();
371         this.data.setSI(index, valueSI);
372     }
373 
374     /**
375      * Replace the value at index by the supplied value which is in a compatible unit.
376      * @param index int; index of the value to replace
377      * @param value S; the strongly typed value to store
378      * @throws ValueException when index out of range (index &lt; 0 or index &gt;= size())
379      */
380     public final void set(final int index, final S value) throws ValueException
381     {
382         setSI(index, value.getSI());
383     }
384 
385     /**
386      * Replace the value at index by the supplied value which is expressed in a supplied (compatible) unit.
387      * @param index int; index of the value to replace
388      * @param value float; the value to store (which is expressed in valueUnit)
389      * @param valueUnit AU; unit of the supplied value
390      * @throws ValueException when index out of range (index &lt; 0 or index &gt;= size())
391      */
392     public final void setInUnit(final int index, final float value, final AU valueUnit) throws ValueException
393     {
394         setSI(index, (float) ValueUtil.expressAsSIUnit(value, valueUnit));
395     }
396 
397     /**
398      * Normalize the vector, i.e. scale the values to make the sum equal to 1.
399      * @throws ValueException when the sum of the values is zero and normalization is not possible
400      */
401     public final void normalize() throws ValueException
402     {
403         float sum = zSum();
404         if (0 == sum)
405         {
406             throw new ValueException("zSum is 0; cannot normalize");
407         }
408         checkCopyOnWrite();
409         this.data.divideBy(sum);
410     }
411 }