1 package org.djunits.value.vfloat.vector.data;
2
3 import java.io.Serializable;
4 import java.util.Arrays;
5 import java.util.List;
6 import java.util.Map.Entry;
7 import java.util.SortedMap;
8 import java.util.stream.IntStream;
9
10 import org.djunits.unit.Unit;
11 import org.djunits.unit.scale.Scale;
12 import org.djunits.value.ValueRuntimeException;
13 import org.djunits.value.storage.AbstractStorage;
14 import org.djunits.value.storage.StorageType;
15 import org.djunits.value.vfloat.function.FloatFunction;
16 import org.djunits.value.vfloat.function.FloatFunction2;
17 import org.djunits.value.vfloat.scalar.base.FloatScalarInterface;
18 import org.djutils.exceptions.Throw;
19
20
21
22
23
24
25
26
27
28
29 public abstract class FloatVectorData extends AbstractStorage<FloatVectorData> implements Serializable
30 {
31
32 private static final long serialVersionUID = 1L;
33
34
35 @SuppressWarnings("checkstyle:visibilitymodifier")
36 protected float[] vectorSI;
37
38
39
40
41
42 FloatVectorData(final StorageType storageType)
43 {
44 super(storageType);
45 }
46
47
48
49
50
51
52
53
54
55
56
57
58
59 public static FloatVectorData instantiate(final float[] values, final Scale scale, final StorageType storageType)
60 {
61 Throw.whenNull(values, "FloatVectorData.instantiate: float[] values is null");
62 Throw.whenNull(scale, "FloatVectorData.instantiate: scale is null");
63 Throw.whenNull(storageType, "FloatVectorData.instantiate: storageType is null");
64
65 float[] valuesSI = new float[values.length];
66 IntStream.range(0, values.length).parallel().forEach(i -> valuesSI[i] = (float) scale.toStandardUnit(values[i]));
67
68 switch (storageType)
69 {
70 case DENSE:
71 return new FloatVectorDataDense(valuesSI);
72
73 case SPARSE:
74 return FloatVectorDataSparse.instantiate(valuesSI);
75
76 default:
77 throw new ValueRuntimeException("Unknown storage type in FloatVectorData.instantiate: " + storageType);
78 }
79 }
80
81
82
83
84
85
86
87
88
89 public static FloatVectorData instantiate(final List<Float> values, final Scale scale, final StorageType storageType)
90 {
91 Throw.whenNull(values, "FloatVectorData.instantiate: float[] values is null");
92 Throw.whenNull(scale, "FloatVectorData.instantiate: scale is null");
93 Throw.whenNull(storageType, "FloatVectorData.instantiate: storageType is null");
94 Throw.when(values.parallelStream().filter(d -> d == null).count() > 0, NullPointerException.class,
95 "values contains one or more null values");
96
97 float[] valuesSI = new float[values.size()];
98 IntStream.range(0, values.size()).parallel().forEach(i -> valuesSI[i] = (float) scale.toStandardUnit(values.get(i)));
99
100 switch (storageType)
101 {
102 case DENSE:
103 return new FloatVectorDataDense(valuesSI);
104
105 case SPARSE:
106 return FloatVectorDataSparse.instantiate(valuesSI);
107
108 default:
109 throw new ValueRuntimeException("Unknown storage type in FloatVectorData.instantiate: " + storageType);
110 }
111 }
112
113
114
115
116
117
118
119
120
121
122 public static <U extends Unit<U>, S extends FloatScalarInterface<U, S>> FloatVectorData instantiate(final S[] values,
123 final StorageType storageType)
124 {
125 Throw.whenNull(values, "FloatVectorData.instantiate: double[] values is null");
126 Throw.whenNull(storageType, "FloatVectorData.instantiate: storageType is null");
127
128 for (S s : values)
129 {
130 Throw.whenNull(s, "null value in values");
131 }
132
133 float[] valuesSI = new float[values.length];
134 IntStream.range(0, values.length).parallel().forEach(i -> valuesSI[i] = values[i].getSI());
135
136 switch (storageType)
137 {
138 case DENSE:
139 return new FloatVectorDataDense(valuesSI);
140
141 case SPARSE:
142 return FloatVectorDataSparse.instantiate(valuesSI);
143
144 default:
145 throw new ValueRuntimeException("Unknown storage type in FloatVectorData.instantiate: " + storageType);
146 }
147 }
148
149
150
151
152
153
154
155
156
157
158 public static <U extends Unit<U>, S extends FloatScalarInterface<U, S>> FloatVectorData instantiateList(
159 final List<S> valueList, final StorageType storageType)
160 {
161 Throw.whenNull(valueList, "FloatVectorData.instantiate: valueList is null");
162 Throw.whenNull(storageType, "FloatVectorData.instantiate: storageType is null");
163
164 for (S s : valueList)
165 {
166 Throw.whenNull(s, "null value in valueList");
167 }
168
169 float[] valuesSI = new float[valueList.size()];
170 IntStream.range(0, valueList.size()).parallel().forEach(i -> valuesSI[i] = valueList.get(i).getSI());
171
172 switch (storageType)
173 {
174 case DENSE:
175 return new FloatVectorDataDense(valuesSI);
176
177 case SPARSE:
178 return FloatVectorDataSparse.instantiate(valuesSI);
179
180 default:
181 throw new ValueRuntimeException("Unknown storage type in FloatVectorData.instantiate: " + storageType);
182 }
183 }
184
185
186
187
188
189
190
191
192
193
194
195 public static FloatVectorData instantiate(final SortedMap<Integer, Float> valueMap, final int length, final Scale scale,
196 final StorageType storageType) throws ValueRuntimeException
197 {
198 Throw.whenNull(valueMap, "FloatVectorData.instantiate: values is null");
199 Throw.when(length < 0, ValueRuntimeException.class, "Length must be >= 0");
200 Throw.whenNull(scale, "FloatVectorData.instantiate: scale is null");
201 Throw.whenNull(storageType, "FloatVectorData.instantiate: storageType is null");
202 for (Integer key : valueMap.keySet())
203 {
204 Throw.when(key < 0 || key >= length, ValueRuntimeException.class, "Key in values out of range");
205 }
206
207 switch (storageType)
208 {
209 case DENSE:
210 {
211 float[] valuesSI = new float[length];
212 if (scale.isBaseSIScale())
213 {
214 valueMap.entrySet().parallelStream().forEach(entry -> valuesSI[entry.getKey()] = entry.getValue());
215 }
216 else
217 {
218 Arrays.fill(valuesSI, (float) scale.toStandardUnit(0.0));
219 valueMap.entrySet().parallelStream()
220 .forEach(entry -> valuesSI[entry.getKey()] = (float) scale.toStandardUnit(entry.getValue()));
221 }
222 return new FloatVectorDataDense(valuesSI);
223 }
224
225 case SPARSE:
226 {
227 int nonZeroCount;
228 if (scale.isBaseSIScale())
229 {
230 nonZeroCount = (int) valueMap.keySet().parallelStream().filter(d -> d != 0d).count();
231 }
232 else
233 {
234
235 nonZeroCount = length
236 - (int) valueMap.values().parallelStream().filter(d -> scale.toStandardUnit(d) == 0d).count();
237 }
238 int[] indices = new int[nonZeroCount];
239 float[] valuesSI = new float[nonZeroCount];
240 if (scale.isBaseSIScale())
241 {
242 int index = 0;
243 for (Integer key : valueMap.keySet())
244 {
245 float value = valueMap.get(key);
246 if (0.0 != value)
247 {
248 indices[index] = key;
249 valuesSI[index] = value;
250 index++;
251 }
252 }
253 }
254 else
255 {
256 Arrays.fill(valuesSI, (float) scale.toStandardUnit(0.0));
257 int index = 0;
258 int lastKey = 0;
259 for (Integer key : valueMap.keySet())
260 {
261 for (int i = lastKey; i < key; i++)
262 {
263 indices[index++] = i;
264 }
265 lastKey = key;
266 float value = (float) scale.toStandardUnit(valueMap.get(key));
267 if (0.0 != value)
268 {
269 indices[index] = key;
270 valuesSI[index] = value;
271 index++;
272 }
273 lastKey = key + 1;
274 }
275 while (index < indices.length)
276 {
277 indices[index++] = lastKey++;
278 }
279 }
280 return new FloatVectorDataSparse(valuesSI, indices, length);
281 }
282
283 default:
284 throw new ValueRuntimeException("Unknown storage type in FloatVectorData.instantiate: " + storageType);
285 }
286 }
287
288
289
290
291
292
293
294
295
296
297
298
299 public static <U extends Unit<U>, S extends FloatScalarInterface<U, S>> FloatVectorData instantiateMap(
300 final SortedMap<Integer, S> values, final int length, final StorageType storageType) throws ValueRuntimeException
301 {
302 Throw.whenNull(values, "FloatVectorData.instantiate: values is null");
303 Throw.when(length < 0, ValueRuntimeException.class, "Length must be >= 0");
304 Throw.whenNull(storageType, "FloatVectorData.instantiate: storageType is null");
305 for (Entry<Integer, S> e : values.entrySet())
306 {
307 Throw.when(e.getKey() < 0 || e.getKey() >= length, ValueRuntimeException.class, "Key in values out of range");
308 Throw.whenNull(e.getValue(), "null value in map");
309 }
310
311 switch (storageType)
312 {
313 case DENSE:
314 {
315 float[] valuesSI = new float[length];
316 values.entrySet().parallelStream().forEach(entry -> valuesSI[entry.getKey()] = entry.getValue().getSI());
317 return new FloatVectorDataDense(valuesSI);
318 }
319
320 case SPARSE:
321 {
322 int nonZeroCount = (int) values.values().parallelStream().filter(s -> s.getSI() != 0f).count();
323 int[] indices = new int[nonZeroCount];
324 float[] valuesSI = new float[nonZeroCount];
325 int index = 0;
326 for (Integer key : values.keySet())
327 {
328 float value = values.get(key).getSI();
329 if (0.0f != value)
330 {
331 indices[index] = key;
332 valuesSI[index] = value;
333 index++;
334 }
335 }
336 return new FloatVectorDataSparse(valuesSI, indices, length);
337 }
338
339 default:
340 throw new ValueRuntimeException("Unknown storage type in FloatVectorData.instantiate: " + storageType);
341 }
342 }
343
344
345
346
347
348
349
350
351
352 public abstract int size();
353
354
355
356
357
358 public abstract FloatVectorDataDense toDense();
359
360
361
362
363
364 public abstract FloatVectorDataSparse toSparse();
365
366
367
368
369
370
371 public abstract float getSI(int index);
372
373
374
375
376
377
378 public abstract void setSI(int index, float valueSI);
379
380
381
382
383
384 public final float zSum()
385 {
386
387 return (float) IntStream.range(0, this.vectorSI.length).parallel().mapToDouble(i -> this.vectorSI[i]).sum();
388 }
389
390
391
392
393
394 public abstract float[] getDenseVectorSI();
395
396
397
398
399
400
401 protected void checkSizes(final FloatVectorData other) throws ValueRuntimeException
402 {
403 if (this.size() != other.size())
404 {
405 throw new ValueRuntimeException("Two data objects used in a FloatVector operation do not have the same size");
406 }
407 }
408
409
410
411
412
413
414
415
416
417
418 public abstract FloatVectorData assign(FloatFunction floatFunction);
419
420
421
422
423
424
425
426
427 abstract FloatVectorData assign(FloatFunction2 floatFunction2, FloatVectorData right) throws ValueRuntimeException;
428
429
430
431
432
433
434
435
436 public abstract FloatVectorData plus(FloatVectorData right) throws ValueRuntimeException;
437
438
439
440
441
442
443
444 public final FloatVectorData incrementBy(final FloatVectorData right) throws ValueRuntimeException
445 {
446 return assign(new FloatFunction2()
447 {
448 @Override
449 public float apply(final float leftValue, final float rightValue)
450 {
451 return leftValue + rightValue;
452 }
453 }, right);
454 }
455
456
457
458
459
460
461
462
463 public abstract FloatVectorData minus(FloatVectorData right) throws ValueRuntimeException;
464
465
466
467
468
469
470
471 public final FloatVectorData decrementBy(final FloatVectorData right) throws ValueRuntimeException
472 {
473 return assign(new FloatFunction2()
474 {
475 @Override
476 public float apply(final float leftValue, final float rightValue)
477 {
478 return leftValue - rightValue;
479 }
480 }, right);
481 }
482
483
484
485
486
487
488
489
490 public abstract FloatVectorData times(FloatVectorData right) throws ValueRuntimeException;
491
492
493
494
495
496
497
498
499 public final FloatVectorData multiplyBy(final FloatVectorData right) throws ValueRuntimeException
500 {
501 assign(new FloatFunction2()
502 {
503 @Override
504 public float apply(final float leftValue, final float rightValue)
505 {
506 return leftValue * rightValue;
507 }
508 }, right);
509 return this;
510 }
511
512
513
514
515
516
517
518
519 public abstract FloatVectorData divide(FloatVectorData right) throws ValueRuntimeException;
520
521
522
523
524
525
526
527
528 public final FloatVectorData divideBy(final FloatVectorData right) throws ValueRuntimeException
529 {
530 return assign(new FloatFunction2()
531 {
532 @Override
533 public float apply(final float leftValue, final float rightValue)
534 {
535 return leftValue / rightValue;
536 }
537 }, right);
538 }
539
540
541
542
543
544
545 @Override
546 public int hashCode()
547 {
548 final int prime = 31;
549 int result = 1;
550 result = prime * result + this.size();
551 for (int index = 0; index < this.size(); index++)
552 {
553 result = 31 * result + Float.floatToIntBits(getSI(index));
554 }
555 return result;
556 }
557
558
559
560
561
562
563
564 protected boolean compareDenseVectorWithSparseVector(final FloatVectorDataDense dm, final FloatVectorDataSparse sm)
565 {
566 for (int index = 0; index < dm.size(); index++)
567 {
568 if (dm.getSI(index) != sm.getSI(index))
569 {
570 return false;
571 }
572 }
573 return true;
574 }
575
576
577 @Override
578 @SuppressWarnings("checkstyle:needbraces")
579 public boolean equals(final Object obj)
580 {
581 if (this == obj)
582 return true;
583 if (obj == null)
584 return false;
585 if (!(obj instanceof FloatVectorData))
586 return false;
587 FloatVectorData other = (FloatVectorData) obj;
588 if (this.size() != other.size())
589 return false;
590 if (other instanceof FloatVectorDataSparse && this instanceof FloatVectorDataDense)
591 {
592 return compareDenseVectorWithSparseVector((FloatVectorDataDense) this, (FloatVectorDataSparse) other);
593 }
594 else if (other instanceof FloatVectorDataDense && this instanceof FloatVectorDataSparse)
595 {
596 return compareDenseVectorWithSparseVector((FloatVectorDataDense) other, (FloatVectorDataSparse) this);
597 }
598
599 return Arrays.equals(this.vectorSI, other.vectorSI);
600 }
601
602
603 @Override
604 public String toString()
605 {
606 return "FloatVectorData [storageType=" + getStorageType() + ", vectorSI=" + Arrays.toString(this.vectorSI) + "]";
607 }
608
609 }