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-2018 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 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; 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 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 DoubleScalar.Rel<U>[]; the values of the entries in the new Relative Mutable DoubleVector 68 * @param 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; the values of the entries in the new Relative Mutable DoubleVector 79 * @param 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 DoubleScalar.Rel<U>[]; the values of the entries in the new Relative Sparse Mutable DoubleVector 90 * @param length the size of the vector 91 * @param 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 Map; 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 the size of the vector 105 * @param 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 an internal data object 117 * @param unit 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<U>; 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<U>; 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 DoubleVector.Rel<U>; amount by which the value is incremented 179 * @return the changed MutableDoubleVector.Rel<U> 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 DoubleScalar.Rel<U>; amount by which the value is incremented 193 * @return the changed MutableDoubleVector.Rel<U> 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 amount by which the value is incremented 203 * @return the changed MutableDoubleVector.Rel<U> 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 DoubleVector.Rel<U>; amount by which the value is decremented 216 * @return the changed MutableDoubleVector.Rel<U> 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 DoubleScalar.Rel<U>; amount by which the value is decremented 230 * @return the changed MutableDoubleVector.Rel<U> 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 amount by which the value is decremented 240 * @return the changed MutableDoubleVector.Rel<U> 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 DoubleVector.Rel<U>; amounts by which the value is multiplied 253 * @return the changed MutableDoubleVector.Rel<U> 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 DoubleScalar.Rel<U>; amount by which the values in the vector are multiplied 267 * @return the changed MutableDoubleVector.Rel<U> 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 DoubleVector.Rel<U>; amounts by which the value is divided 287 * @return the changed MutableDoubleVector.Rel<U> 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 DoubleScalar.Rel<U>; amount by which the values in the vector are divided 310 * @return the changed MutableDoubleVector.Rel<U> 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 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 < 0 or index >= 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 DoubleScalar<U>; the strongly typed value to store 425 * @throws ValueException when index out of range (index < 0 or index >= 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 < 0 or index >= 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 }