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