1 package org.djunits.value.vdouble.vector.base;
2
3 import java.io.Serializable;
4 import java.lang.reflect.Array;
5 import java.util.Iterator;
6 import java.util.NoSuchElementException;
7
8 import org.djunits.unit.Unit;
9 import org.djunits.value.Absolute;
10 import org.djunits.value.ValueRuntimeException;
11 import org.djunits.value.base.Vector;
12 import org.djunits.value.formatter.Format;
13 import org.djunits.value.storage.StorageType;
14 import org.djunits.value.util.ValueUtil;
15 import org.djunits.value.vdouble.function.DoubleFunction;
16 import org.djunits.value.vdouble.function.DoubleMathFunctions;
17 import org.djunits.value.vdouble.scalar.base.DoubleScalar;
18 import org.djunits.value.vdouble.vector.data.DoubleVectorData;
19 import org.djunits.value.vdouble.vector.data.DoubleVectorDataDense;
20 import org.djunits.value.vdouble.vector.data.DoubleVectorDataSparse;
21 import org.djutils.exceptions.Throw;
22
23
24
25
26
27
28
29
30
31
32
33
34
35 public abstract class DoubleVector<U extends Unit<U>, S extends DoubleScalar<U, S>, V extends DoubleVector<U, S, V>>
36 extends Vector<U, S, V, DoubleVectorData>
37 {
38
39 private static final long serialVersionUID = 20161015L;
40
41
42 @SuppressWarnings("checkstyle:visibilitymodifier")
43 protected DoubleVectorData data;
44
45
46
47
48
49
50 DoubleVector(final DoubleVectorData data, final U unit)
51 {
52 super(unit);
53 Throw.whenNull(data, "data cannot be null");
54 this.data = data;
55 }
56
57
58
59
60
61
62
63
64
65 public abstract V instantiateVector(DoubleVectorData dvd, U displayUnit);
66
67
68
69
70
71
72
73
74
75 public abstract S instantiateScalarSI(double valueSI, U displayUnit);
76
77 @Override
78 protected final DoubleVectorData getData()
79 {
80 return this.data;
81 }
82
83 @Override
84 protected void setData(final DoubleVectorData data)
85 {
86 this.data = data;
87 }
88
89
90
91
92
93 public final double[] getValuesSI()
94 {
95 return getData().getDenseVectorSI();
96 }
97
98
99
100
101
102 public final double[] getValuesInUnit()
103 {
104 return getValuesInUnit(getDisplayUnit());
105 }
106
107
108
109
110
111
112 public final double[] getValuesInUnit(final U targetUnit)
113 {
114 double[] values = getValuesSI();
115 for (int i = values.length; --i >= 0;)
116 {
117 values[i] = ValueUtil.expressAsUnit(values[i], targetUnit);
118 }
119 return values;
120 }
121
122 @Override
123 public final int size()
124 {
125 return getData().size();
126 }
127
128
129
130
131
132
133 protected final void checkIndex(final int index) throws IndexOutOfBoundsException
134 {
135 if (index < 0 || index >= size())
136 {
137 throw new IndexOutOfBoundsException(
138 "index out of range (valid range is 0.." + (size() - 1) + ", got " + index + ")");
139 }
140 }
141
142
143
144
145
146
147
148 public final double getSI(final int index) throws IndexOutOfBoundsException
149 {
150 checkIndex(index);
151 return getData().getSI(index);
152 }
153
154 @Override
155 public S get(final int index) throws IndexOutOfBoundsException
156 {
157 return DoubleScalar.instantiateSI(getSI(index), getDisplayUnit());
158 }
159
160
161
162
163
164
165
166 public final double getInUnit(final int index) throws IndexOutOfBoundsException
167 {
168 return ValueUtil.expressAsUnit(getSI(index), getDisplayUnit());
169 }
170
171
172
173
174
175
176
177
178 public final double getInUnit(final int index, final U targetUnit) throws IndexOutOfBoundsException
179 {
180 return ValueUtil.expressAsUnit(getSI(index), targetUnit);
181 }
182
183
184
185
186
187
188
189 public final void setSI(final int index, final double valueSI) throws IndexOutOfBoundsException
190 {
191 checkIndex(index);
192 checkCopyOnWrite();
193 getData().setSI(index, valueSI);
194 }
195
196
197
198
199
200
201
202 public void setInUnit(final int index, final double valueInUnit) throws IndexOutOfBoundsException
203 {
204 setSI(index, ValueUtil.expressAsSIUnit(valueInUnit, getDisplayUnit()));
205 }
206
207
208
209
210
211
212
213
214 public void setInUnit(final int index, final double valueInUnit, final U valueUnit) throws IndexOutOfBoundsException
215 {
216 setSI(index, ValueUtil.expressAsSIUnit(valueInUnit, valueUnit));
217 }
218
219
220
221
222
223
224
225 public void set(final int index, final S value) throws IndexOutOfBoundsException
226 {
227 setSI(index, value.si);
228 }
229
230 @SuppressWarnings("unchecked")
231 @Override
232 public S[] getScalars()
233 {
234 S[] array = (S[]) Array.newInstance(getScalarClass(), size());
235 for (int i = 0; i < size(); i++)
236 {
237 array[i] = get(i);
238 }
239 return array;
240 }
241
242 @SuppressWarnings("unchecked")
243 @Override
244 public V toSparse()
245 {
246 V result;
247 if (getStorageType().equals(StorageType.SPARSE))
248 {
249 result = (V) this;
250 result.setDisplayUnit(getDisplayUnit());
251 }
252 else
253 {
254 result = instantiateVector(getData().toSparse(), getDisplayUnit());
255 }
256 result.setDisplayUnit(getDisplayUnit());
257 return result;
258 }
259
260 @SuppressWarnings("unchecked")
261 @Override
262 public V toDense()
263 {
264 V result;
265 if (getStorageType().equals(StorageType.DENSE))
266 {
267 result = (V) this;
268 result.setDisplayUnit(getDisplayUnit());
269 }
270 else
271 {
272 result = instantiateVector(getData().toDense(), getDisplayUnit());
273 }
274 return result;
275 }
276
277
278
279
280
281
282 @SuppressWarnings("unchecked")
283 public final V assign(final DoubleFunction doubleFunction)
284 {
285 checkCopyOnWrite();
286 if (getData() instanceof DoubleVectorDataDense)
287 {
288 ((DoubleVectorDataDense) getData()).assign(doubleFunction);
289 }
290 else
291 {
292 this.data = ((DoubleVectorDataSparse) getData()).toDense().assign(doubleFunction).toSparse();
293 }
294 return (V) this;
295 }
296
297 @Override
298 public final V abs()
299 {
300 return assign(DoubleMathFunctions.ABS);
301 }
302
303 @Override
304 public final V ceil()
305 {
306 return assign(DoubleMathFunctions.CEIL);
307 }
308
309 @Override
310 public final V floor()
311 {
312 return assign(DoubleMathFunctions.FLOOR);
313 }
314
315 @Override
316 public final V neg()
317 {
318 return assign(DoubleMathFunctions.NEG);
319 }
320
321 @Override
322 public final V rint()
323 {
324 return assign(DoubleMathFunctions.RINT);
325 }
326
327 @Override
328 public String toString()
329 {
330 return toString(getDisplayUnit(), false, true);
331 }
332
333 @Override
334 public String toString(final U displayUnit)
335 {
336 return toString(displayUnit, false, true);
337 }
338
339 @Override
340 public String toString(final boolean verbose, final boolean withUnit)
341 {
342 return toString(getDisplayUnit(), verbose, withUnit);
343 }
344
345 @Override
346 public String toString(final U displayUnit, final boolean verbose, final boolean withUnit)
347 {
348 StringBuffer buf = new StringBuffer();
349 if (verbose)
350 {
351 String ar = this instanceof Absolute ? "Abs " : "Rel ";
352 String ds = getData().isDense() ? "Dense " : getData().isSparse() ? "Sparse " : "?????? ";
353 if (isMutable())
354 {
355 buf.append("Mutable " + ar + ds);
356 }
357 else
358 {
359 buf.append("Immutable " + ar + ds);
360 }
361 }
362 buf.append("[");
363 for (int i = 0; i < size(); i++)
364 {
365 try
366 {
367 double d = ValueUtil.expressAsUnit(getSI(i), displayUnit);
368 buf.append(" " + Format.format(d));
369 }
370 catch (IndexOutOfBoundsException ve)
371 {
372 buf.append(" " + "********************".substring(0, Format.DEFAULTSIZE));
373 }
374 }
375 buf.append("]");
376 if (withUnit)
377 {
378 buf.append(" " + displayUnit.getLocalizedDisplayAbbreviation());
379 }
380 return buf.toString();
381 }
382
383
384
385
386
387
388
389 protected final void checkSize(final DoubleVector<?, ?, ?> other) throws ValueRuntimeException
390 {
391 Throw.whenNull(other, "Other vector is null");
392 Throw.when(size() != other.size(), ValueRuntimeException.class, "The vectors have different sizes: %d != %d", size(),
393 other.size());
394 }
395
396 @Override
397 @SuppressWarnings("checkstyle:designforextension")
398 public int hashCode()
399 {
400 final int prime = 31;
401 int result = getDisplayUnit().getStandardUnit().hashCode();
402 result = prime * result + ((this.data == null) ? 0 : this.data.hashCode());
403 return result;
404 }
405
406 @Override
407 @SuppressWarnings({"checkstyle:designforextension", "checkstyle:needbraces"})
408 public boolean equals(final Object obj)
409 {
410 if (this == obj)
411 return true;
412 if (obj == null)
413 return false;
414 if (getClass() != obj.getClass())
415 return false;
416 DoubleVector<?, ?, ?> other = (DoubleVector<?, ?, ?>) obj;
417 if (!getDisplayUnit().getStandardUnit().equals(other.getDisplayUnit().getStandardUnit()))
418 return false;
419 if (this.data == null)
420 {
421 if (other.data != null)
422 return false;
423 }
424 else if (!this.data.equals(other.data))
425 return false;
426 return true;
427 }
428
429
430
431
432
433 @Override
434 public Iterator<S> iterator()
435 {
436 return new Itr();
437 }
438
439
440
441
442
443
444 protected class Itr implements Iterator<S>, Serializable
445 {
446
447 private static final long serialVersionUID = 20191018L;
448
449
450 private int cursor = 0;
451
452 @Override
453 public boolean hasNext()
454 {
455 return this.cursor != size();
456 }
457
458 @Override
459 public S next()
460 {
461 if (this.cursor >= size())
462 {
463 throw new NoSuchElementException();
464 }
465 try
466 {
467 int i = this.cursor;
468 S next = get(i);
469 this.cursor = i + 1;
470 return next;
471 }
472 catch (IndexOutOfBoundsException exception)
473 {
474 throw new RuntimeException(exception);
475 }
476 }
477
478 @Override
479 public void remove()
480 {
481 throw new RuntimeException("Remove function cannot be applied on fixed-size DJUNITS Vector");
482 }
483
484 @Override
485 public String toString()
486 {
487 return "Itr [cursor=" + this.cursor + "]";
488 }
489
490 }
491
492 }