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