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