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