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