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<Double>; 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<S>; 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<Integer, S>; 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<Integer, Double>; 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<U>; 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<U>; 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<U> 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<U> 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<U> 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<U> 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<U> 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<U> 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<U> 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 < 0 or index >= 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 < 0 or index >= 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 < 0 or index >= 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 }