1 package org.djunits.value.vdouble.vector; 2 3 import java.io.Serializable; 4 import java.util.Iterator; 5 import java.util.List; 6 import java.util.NoSuchElementException; 7 import java.util.SortedMap; 8 9 import org.djunits.unit.AbsoluteLinearUnit; 10 import org.djunits.unit.Unit; 11 import org.djunits.value.Absolute; 12 import org.djunits.value.FunctionsAbs; 13 import org.djunits.value.StorageType; 14 import org.djunits.value.ValueException; 15 import org.djunits.value.vdouble.scalar.AbstractDoubleScalarAbs; 16 17 /** 18 * Absolute Immutable 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 AbstractDoubleVectorAbs<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 AbstractDoubleVector<AU, A> implements FunctionsAbs<AU, RU, A, R>, Absolute, Serializable, Iterable<S> 38 { 39 /** */ 40 private static final long serialVersionUID = 20151006L; 41 42 /** 43 * Construct a new Absolute Immutable DoubleVector. 44 * @param values double[]; the values of the entries in the new Absolute Immutable DoubleVector 45 * @param unit AU; the unit of the new Absolute Immutable DoubleVector 46 * @param storageType StorageType; the data type to use (e.g., DENSE or SPARSE) 47 * @throws ValueException when values is null 48 */ 49 AbstractDoubleVectorAbs(final double[] values, final AU unit, final StorageType storageType) throws ValueException 50 { 51 super(unit, DoubleVectorData.instantiate(values, unit.getScale(), storageType)); 52 } 53 54 /** 55 * Construct a new Absolute Immutable DoubleVector. 56 * @param values List<Double>; the values of the entries in the new Absolute Immutable DoubleVector 57 * @param unit AU; the unit of the new Absolute Immutable DoubleVector 58 * @param storageType StorageType; the data type to use (e.g., DENSE or SPARSE) 59 * @throws ValueException when values is null 60 */ 61 AbstractDoubleVectorAbs(final List<Double> values, final AU unit, final StorageType storageType) throws ValueException 62 { 63 super(unit, DoubleVectorData.instantiate(values, unit.getScale(), storageType)); 64 } 65 66 /** 67 * Construct a new Absolute Immutable DoubleVector. 68 * @param values S[]; the values of the entries in the new Absolute Immutable DoubleVector 69 * @param storageType StorageType; the data type to use (e.g., DENSE or SPARSE) 70 * @throws ValueException when values has zero entries 71 */ 72 AbstractDoubleVectorAbs(final S[] values, final StorageType storageType) throws ValueException 73 { 74 super(checkUnit(values), DoubleVectorData.instantiate(values, storageType)); 75 } 76 77 /** 78 * Construct a new Absolute Immutable DoubleVector. 79 * @param values List<S>; the values of the entries in the new Absolute Immutable DoubleVector 80 * @param storageType StorageType; the data type to use (e.g., DENSE or SPARSE) 81 * @throws ValueException when values has zero entries 82 */ 83 AbstractDoubleVectorAbs(final List<S> values, final StorageType storageType) throws ValueException 84 { 85 super(checkUnit(values), DoubleVectorData.instantiateLD(values, storageType)); 86 } 87 88 /** 89 * Construct a new Absolute Immutable DoubleVector. 90 * @param values SortedMap<Integer, S>; the values of the entries in the new Absolute Sparse Mutable DoubleVector 91 * @param length int; the size of the vector 92 * @param storageType StorageType; the data type to use (e.g., DENSE or SPARSE) 93 * @throws ValueException when values has zero entries 94 */ 95 AbstractDoubleVectorAbs(final SortedMap<Integer, S> values, final int length, final StorageType storageType) 96 throws ValueException 97 { 98 super(checkUnit(values), DoubleVectorData.instantiateMD(values, length, storageType)); 99 } 100 101 /** 102 * Construct a new Absolute Immutable DoubleVector. 103 * @param values SortedMap<Integer, Double>; the map of indexes to values of the Absolute Sparse Mutable DoubleVector 104 * @param unit AU; the unit of the new Absolute Sparse Mutable DoubleVector 105 * @param length int; the size of the vector 106 * @param storageType StorageType; the data type to use (e.g., DENSE or SPARSE) 107 * @throws ValueException when values is null 108 */ 109 AbstractDoubleVectorAbs(final SortedMap<Integer, Double> values, final AU unit, final int length, 110 final StorageType storageType) throws ValueException 111 { 112 super(unit, DoubleVectorData.instantiate(values, length, unit.getScale(), storageType)); 113 } 114 115 /** 116 * Construct a new Relative Immutable DoubleVector. 117 * @param data DoubleVectorData; an internal data object 118 * @param unit AU; the unit 119 */ 120 AbstractDoubleVectorAbs(final DoubleVectorData data, final AU unit) 121 { 122 super(unit, data.copy()); 123 } 124 125 /** 126 * Create a mutable version of this DoubleVector. <br> 127 * The mutable version is created with a shallow copy of the data and the internal copyOnWrite flag set. The first operation 128 * in the mutable version that modifies the data shall trigger a deep copy of the data. 129 * @return MA; mutable version of this DoubleVector 130 */ 131 @Override 132 public MA mutable() 133 { 134 return instantiateMutableType(getData(), getUnit()); 135 } 136 137 /** 138 * Construct a new Absolute Immutable DoubleVector of the right type. Each extending class must implement this method. 139 * @param dvd DoubleVectorData; an internal data object 140 * @param unit AU; the unit 141 * @return M the Mutable DoubleVector of the right type 142 */ 143 protected abstract A instantiateTypeAbs(DoubleVectorData dvd, AU unit); 144 145 /** 146 * Construct a new Relative Immutable DoubleVector of the right type. Each extending class must implement this method. 147 * @param dvd DoubleVectorData; an internal data object 148 * @param unit RU; the unit 149 * @return M the Mutable DoubleVector of the right type 150 */ 151 protected abstract R instantiateTypeRel(DoubleVectorData dvd, RU unit); 152 153 /** 154 * Construct a new Absolute Mutable DoubleVector of the right type. Each extending class must implement this method. 155 * @param dvd DoubleVectorData; an internal data object 156 * @param unit AU; the unit 157 * @return M the Mutable DoubleVector of the right type 158 */ 159 protected abstract MA instantiateMutableType(DoubleVectorData dvd, AU unit); 160 161 /** 162 * Construct a new Absolute Immutable DoubleScalar of the right type. Each extending class must implement this method. 163 * @param value double; the value 164 * @param unit AU; the unit 165 * @return S the Immutable DoubleScalar of the right type 166 */ 167 protected abstract S instantiateScalar(double value, AU unit); 168 169 /** {@inheritDoc} */ 170 @Override 171 public final S get(final int index) throws ValueException 172 { 173 return instantiateScalar(getInUnit(index, getUnit()), getUnit()); 174 } 175 176 /**********************************************************************************/ 177 /**************************** TYPED CALCULATION METHODS ***************************/ 178 /**********************************************************************************/ 179 180 /** {@inheritDoc} */ 181 @Override 182 public final A plus(final R rel) throws ValueException 183 { 184 return instantiateTypeAbs(this.getData().plus(rel.getData()), getUnit()); 185 } 186 187 /** {@inheritDoc} */ 188 @Override 189 public A minus(final R rel) throws ValueException 190 { 191 return instantiateTypeAbs(this.getData().minus(rel.getData()), getUnit()); 192 } 193 194 /** {@inheritDoc} */ 195 @Override 196 public R minus(final A abs) throws ValueException 197 { 198 return instantiateTypeRel(this.getData().minus(abs.getData()), getUnit().getRelativeUnit()); 199 } 200 201 /* ============================================================================================ */ 202 /* ============================= STATIC CONSTRUCTOR HELP METHODS ============================== */ 203 /* ============================================================================================ */ 204 205 /** 206 * Check that a provided array can be used to create some descendant of a DoubleVector, and return the Unit. 207 * @param dsArray S[]; the array to check and get the unit for 208 * @param <AU> the absolute unit 209 * @param <RU> the corresponding relative unit 210 * @param <S> the scalar type 211 * @return the unit of the object 212 * @throws ValueException when the array has length equal to 0 213 */ 214 static <AU extends AbsoluteLinearUnit<AU, RU>, RU extends Unit<RU>, 215 S extends AbstractDoubleScalarAbs<AU, S, RU, ?>> AU checkUnit(final S[] dsArray) throws ValueException 216 { 217 if (dsArray != null && dsArray.length > 0) 218 { 219 return dsArray[0].getUnit(); 220 } 221 throw new ValueException( 222 "Cannot create a DoubleVector or MutableDoubleVector from a null or empty array of DoubleScalar"); 223 } 224 225 /** 226 * Check that a provided list can be used to create some descendant of a DoubleVector, and return the Unit. 227 * @param dsList List<S>; the list to check and get the unit for 228 * @param <AU> the absolute unit of the scalars in the list 229 * @param <RU> the corresponding relative unit 230 * @param <S> the scalar in the list 231 * @return the unit of the object 232 * @throws ValueException when the array has length equal to 0 233 */ 234 static <AU extends AbsoluteLinearUnit<AU, RU>, RU extends Unit<RU>, 235 S extends AbstractDoubleScalarAbs<AU, S, RU, ?>> AU checkUnit(final List<S> dsList) throws ValueException 236 { 237 if (dsList != null && dsList.size() > 0) 238 { 239 return dsList.get(0).getUnit(); 240 } 241 throw new ValueException( 242 "Cannot create a DoubleVector or MutableDoubleVector from a null or empty list of DoubleScalar"); 243 } 244 245 /** 246 * Check that a provided Map can be used to create some descendant of a DoubleVector. 247 * @param dsMap SortedMap<Integer,S>; the provided map 248 * @param <AU> the absolute unit of the scalars in the map 249 * @param <RU> the corresponding relative unit 250 * @param <S> the scalar in the list 251 * @return List the provided list 252 * @throws ValueException when the list has size equal to 0 253 */ 254 static <AU extends AbsoluteLinearUnit<AU, RU>, RU extends Unit<RU>, 255 S extends AbstractDoubleScalarAbs<AU, S, RU, ?>> AU checkUnit(final SortedMap<Integer, S> dsMap) 256 throws ValueException 257 { 258 if (dsMap != null && dsMap.size() > 0) 259 { 260 return dsMap.get(dsMap.firstKey()).getUnit(); 261 } 262 throw new ValueException( 263 "Cannot create a DoubleVector or MutableDoubleVector from a null or empty Map of DoubleScalar"); 264 } 265 266 /* ============================================================================================ */ 267 /* =============================== ITERATOR METHODS AND CLASS ================================= */ 268 /* ============================================================================================ */ 269 270 /** 271 * Returns an iterator over the scalars in this vector in proper sequence. 272 * @return an iterator over the scalars in this vector in proper sequence 273 */ 274 @Override 275 public Iterator<S> iterator() 276 { 277 return new Itr(); 278 } 279 280 /** 281 * The iterator class is loosely based in AbstractList.Itr. It does not throw a ConcurrentModificationException, because the 282 * size of the vector does not change. Normal (non-mutable) vectors cannot change their size, nor their content. The only 283 * thing for the MutableVector that can change is its content, not its length. 284 */ 285 protected class Itr implements Iterator<S> 286 { 287 /** index of next element to return. */ 288 private int cursor = 0; 289 290 @Override 291 public boolean hasNext() 292 { 293 return this.cursor != size(); 294 } 295 296 /** {@inheritDoc} */ 297 @Override 298 public S next() 299 { 300 if (this.cursor >= size()) 301 { 302 throw new NoSuchElementException(); 303 } 304 try 305 { 306 int i = this.cursor; 307 S next = get(i); 308 this.cursor = i + 1; 309 return next; 310 } 311 catch (ValueException exception) 312 { 313 throw new RuntimeException(exception); 314 } 315 } 316 317 /** {@inheritDoc} */ 318 @Override 319 public void remove() 320 { 321 throw new RuntimeException("Remove function cannot be applied on fixed-size DJUNITS Vector"); 322 } 323 } 324 325 }