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