1 package org.djunits.value.vfloat.vector.data;
2
3 import java.util.Arrays;
4 import java.util.stream.IntStream;
5
6 import org.djunits.value.ValueRuntimeException;
7 import org.djunits.value.storage.StorageType;
8 import org.djunits.value.vfloat.function.FloatFunction;
9 import org.djunits.value.vfloat.function.FloatFunction2;
10
11
12
13
14
15
16
17
18
19
20 public class FloatVectorDataSparse extends FloatVectorData
21 {
22
23 private static final long serialVersionUID = 1L;
24
25
26 private int[] indices;
27
28
29 private final int size;
30
31
32
33
34
35
36
37 public FloatVectorDataSparse(final float[] vectorSI, final int[] indices, final int size)
38 {
39 super(StorageType.SPARSE);
40 this.vectorSI = vectorSI;
41 this.indices = indices;
42 this.size = size;
43 }
44
45
46 @Override
47 public final int cardinality()
48 {
49 return this.indices.length;
50 }
51
52
53 @Override
54 public FloatVectorData assign(final FloatFunction floatFunction)
55 {
56 if (floatFunction.apply(0f) != 0f)
57 {
58
59 FloatVectorDataSparse result = toDense().assign(floatFunction).toSparse();
60 this.indices = result.indices;
61 this.vectorSI = result.vectorSI;
62 return this;
63 }
64
65 int currentSize = size();
66 if (currentSize > 16)
67 {
68 currentSize = 16;
69 }
70 int[] newIndices = new int[currentSize];
71 float[] newValues = new float[currentSize];
72 int nonZeroValues = 0;
73 int ownIndex = 0;
74 while (ownIndex < this.indices.length)
75 {
76 int index = this.indices[ownIndex];
77 float value = floatFunction.apply(this.vectorSI[ownIndex]);
78 ownIndex++;
79 if (value != 0f)
80 {
81 if (nonZeroValues >= currentSize)
82 {
83
84 currentSize *= 2;
85 if (currentSize > size())
86 {
87 currentSize = size();
88 }
89 int[] newNewIndices = new int[currentSize];
90 System.arraycopy(newIndices, 0, newNewIndices, 0, newIndices.length);
91 newIndices = newNewIndices;
92 float[] newNewValues = new float[currentSize];
93 System.arraycopy(newValues, 0, newNewValues, 0, newValues.length);
94 newValues = newNewValues;
95 }
96 newIndices[nonZeroValues] = index;
97 newValues[nonZeroValues] = value;
98 nonZeroValues++;
99 }
100 }
101 if (nonZeroValues < currentSize)
102 {
103
104 int[] newNewIndices = new int[nonZeroValues];
105 System.arraycopy(newIndices, 0, newNewIndices, 0, nonZeroValues);
106 newIndices = newNewIndices;
107 float[] newNewValues = new float[nonZeroValues];
108 System.arraycopy(newValues, 0, newNewValues, 0, nonZeroValues);
109 newValues = newNewValues;
110 }
111 this.indices = newIndices;
112 this.vectorSI = newValues;
113 return this;
114 }
115
116
117 @Override
118 public final FloatVectorDataSparse assign(final FloatFunction2 floatFunction, final FloatVectorData right)
119 {
120 if (floatFunction.apply(0f, 0f) != 0f)
121 {
122
123 FloatVectorDataSparse result = toDense().assign(floatFunction, right).toSparse();
124 this.indices = result.indices;
125 this.vectorSI = result.vectorSI;
126 return this;
127 }
128
129 checkSizes(right);
130 int currentSize = size();
131 if (currentSize > 16)
132 {
133 currentSize = 16;
134 }
135 int[] newIndices = new int[currentSize];
136 float[] newValues = new float[currentSize];
137 int nonZeroValues = 0;
138 int ownIndex = 0;
139 int otherIndex = 0;
140 if (right.isSparse())
141 {
142 FloatVectorDataSparse/../org/djunits/value/vfloat/vector/data/FloatVectorDataSparse.html#FloatVectorDataSparse">FloatVectorDataSparse other = (FloatVectorDataSparse) right;
143 while (ownIndex < this.indices.length || otherIndex < other.indices.length)
144 {
145 float value;
146 int index;
147 if (ownIndex < this.indices.length && otherIndex < other.indices.length)
148 {
149 if (this.indices[ownIndex] == other.indices[otherIndex])
150 {
151 value = floatFunction.apply(this.vectorSI[ownIndex], other.vectorSI[otherIndex]);
152 index = this.indices[ownIndex];
153 ownIndex++;
154 otherIndex++;
155 }
156 else if (this.indices[ownIndex] < other.indices[otherIndex])
157 {
158
159 value = floatFunction.apply(this.vectorSI[ownIndex], 0f);
160 index = this.indices[ownIndex];
161 ownIndex++;
162 }
163 else
164 {
165
166 value = floatFunction.apply(0f, other.vectorSI[otherIndex]);
167 index = other.indices[otherIndex];
168 otherIndex++;
169 }
170 }
171 else if (ownIndex < this.indices.length)
172 {
173 value = floatFunction.apply(this.vectorSI[ownIndex], 0f);
174 index = this.indices[ownIndex];
175 ownIndex++;
176 }
177 else
178 {
179 value = floatFunction.apply(0f, other.vectorSI[otherIndex]);
180 index = other.indices[otherIndex];
181 otherIndex++;
182 }
183 if (value != 0f)
184 {
185 if (nonZeroValues >= currentSize)
186 {
187
188 currentSize *= 2;
189 if (currentSize > size())
190 {
191 currentSize = size();
192 }
193 int[] newNewIndices = new int[currentSize];
194 System.arraycopy(newIndices, 0, newNewIndices, 0, newIndices.length);
195 newIndices = newNewIndices;
196 float[] newNewValues = new float[currentSize];
197 System.arraycopy(newValues, 0, newNewValues, 0, newValues.length);
198 newValues = newNewValues;
199 }
200 newIndices[nonZeroValues] = index;
201 newValues[nonZeroValues] = value;
202 nonZeroValues++;
203 }
204 }
205 }
206 else
207 {
208 FloatVectorDataDense./../org/djunits/value/vfloat/vector/data/FloatVectorDataDense.html#FloatVectorDataDense">FloatVectorDataDense other = (FloatVectorDataDense) right;
209 while (otherIndex < right.vectorSI.length)
210 {
211 float value;
212 int index = otherIndex;
213 if (ownIndex < this.indices.length)
214 {
215 if (this.indices[ownIndex] == otherIndex)
216 {
217 value = floatFunction.apply(this.vectorSI[ownIndex], other.vectorSI[otherIndex]);
218 ownIndex++;
219 }
220 else
221 {
222
223 value = floatFunction.apply(0f, other.vectorSI[otherIndex]);
224 }
225 otherIndex++;
226 }
227 else
228 {
229 value = floatFunction.apply(0f, other.vectorSI[otherIndex]);
230 otherIndex++;
231 }
232 if (value != 0f)
233 {
234 if (nonZeroValues >= currentSize)
235 {
236
237 currentSize *= 2;
238 if (currentSize > size())
239 {
240 currentSize = size();
241 }
242 int[] newNewIndices = new int[currentSize];
243 System.arraycopy(newIndices, 0, newNewIndices, 0, newIndices.length);
244 newIndices = newNewIndices;
245 float[] newNewValues = new float[currentSize];
246 System.arraycopy(newValues, 0, newNewValues, 0, newValues.length);
247 newValues = newNewValues;
248 }
249 newIndices[nonZeroValues] = index;
250 newValues[nonZeroValues] = value;
251 nonZeroValues++;
252 }
253 }
254 }
255 if (nonZeroValues < currentSize)
256 {
257
258 int[] newNewIndices = new int[nonZeroValues];
259 System.arraycopy(newIndices, 0, newNewIndices, 0, nonZeroValues);
260 newIndices = newNewIndices;
261 float[] newNewValues = new float[nonZeroValues];
262 System.arraycopy(newValues, 0, newNewValues, 0, nonZeroValues);
263 newValues = newNewValues;
264 }
265 this.indices = newIndices;
266 this.vectorSI = newValues;
267 return this;
268 }
269
270
271 @Override
272 public final FloatVectorDataDense toDense()
273 {
274 float[] denseSI = new float[this.size];
275 for (int index = 0; index < this.vectorSI.length; index++)
276 {
277 denseSI[this.indices[index]] = this.vectorSI[index];
278 }
279 return new FloatVectorDataDense(denseSI);
280 }
281
282
283 @Override
284 public final FloatVectorDataSparse toSparse()
285 {
286 return this;
287 }
288
289
290 @Override
291 public final int size()
292 {
293 return this.size;
294 }
295
296
297 @Override
298 public final float getSI(final int index)
299 {
300 int internalIndex = Arrays.binarySearch(this.indices, index);
301 return internalIndex < 0 ? 0.0f : this.vectorSI[internalIndex];
302 }
303
304
305 @Override
306 public final void setSI(final int index, final float valueSI)
307 {
308 int internalIndex = Arrays.binarySearch(this.indices, index);
309 if (internalIndex >= 0)
310 {
311 if (valueSI == 0f)
312 {
313
314 int[] indicesNew = new int[this.indices.length - 1];
315 float[] vectorSINew = new float[this.vectorSI.length - 1];
316 System.arraycopy(this.indices, 0, indicesNew, 0, internalIndex);
317 System.arraycopy(this.vectorSI, 0, vectorSINew, 0, internalIndex);
318 System.arraycopy(this.indices, internalIndex + 1, indicesNew, internalIndex,
319 this.indices.length - internalIndex - 1);
320 System.arraycopy(this.vectorSI, internalIndex + 1, vectorSINew, internalIndex,
321 this.indices.length - internalIndex - 1);
322 this.indices = indicesNew;
323 this.vectorSI = vectorSINew;
324 }
325 else
326 {
327 this.vectorSI[internalIndex] = valueSI;
328 }
329 return;
330 }
331 if (valueSI == 0f)
332 {
333 return;
334 }
335
336 internalIndex = -internalIndex - 1;
337 int[] indicesNew = new int[this.indices.length + 1];
338 float[] vectorSINew = new float[this.vectorSI.length + 1];
339 System.arraycopy(this.indices, 0, indicesNew, 0, internalIndex);
340 System.arraycopy(this.vectorSI, 0, vectorSINew, 0, internalIndex);
341 System.arraycopy(this.indices, internalIndex, indicesNew, internalIndex + 1, this.indices.length - internalIndex);
342 System.arraycopy(this.vectorSI, internalIndex, vectorSINew, internalIndex + 1, this.indices.length - internalIndex);
343 indicesNew[internalIndex] = index;
344 vectorSINew[internalIndex] = valueSI;
345 this.indices = indicesNew;
346 this.vectorSI = vectorSINew;
347 }
348
349
350 @Override
351 public final float[] getDenseVectorSI()
352 {
353 return toDense().vectorSI;
354 }
355
356
357 @Override
358 public final FloatVectorDataSparse copy()
359 {
360 float[] vCopy = new float[this.vectorSI.length];
361 System.arraycopy(this.vectorSI, 0, vCopy, 0, this.vectorSI.length);
362 int[] iCopy = new int[this.indices.length];
363 System.arraycopy(this.indices, 0, iCopy, 0, this.indices.length);
364 return new FloatVectorDataSparse(vCopy, iCopy, this.size);
365 }
366
367
368
369
370
371
372 public static FloatVectorDataSparse instantiate(final float[] valuesSI)
373 {
374
375 int length = (int) IntStream.range(0, valuesSI.length).parallel().mapToDouble(i -> valuesSI[i]).filter(f -> f != 0.0f)
376 .count();
377 float[] sparseSI = new float[length];
378 int[] indices = new int[length];
379
380
381 int count = 0;
382 for (int i = 0; i < valuesSI.length; i++)
383 {
384 if (valuesSI[i] != 0.0)
385 {
386 sparseSI[count] = valuesSI[i];
387 indices[count] = i;
388 count++;
389 }
390 }
391 return new FloatVectorDataSparse(sparseSI, indices, valuesSI.length);
392 }
393
394
395 @Override
396 public final FloatVectorDataor/data/FloatVectorData.html#FloatVectorData">FloatVectorData plus(final FloatVectorData right)
397 {
398 if (right.isDense())
399 {
400 return right.plus(this);
401 }
402 return this.copy().incrementBy(right);
403 }
404
405
406 @Override
407 public final FloatVectorDatar/data/FloatVectorData.html#FloatVectorData">FloatVectorData minus(final FloatVectorData right)
408 {
409 if (right.isDense())
410 {
411 return this.toDense().decrementBy(right);
412 }
413 return this.copy().decrementBy(right);
414 }
415
416
417 @Override
418 public final FloatVectorDatar/data/FloatVectorData.html#FloatVectorData">FloatVectorData times(final FloatVectorData right)
419 {
420 return this.copy().multiplyBy(right);
421 }
422
423
424 @Override
425 public final FloatVectorData/data/FloatVectorData.html#FloatVectorData">FloatVectorData divide(final FloatVectorData right) throws ValueRuntimeException
426 {
427 if (right.isSparse())
428 {
429
430 return this.toDense().divideBy(right);
431 }
432
433 return this.copy().divideBy(right);
434 }
435
436
437 @Override
438 public int hashCode()
439 {
440 return super.hashCode();
441 }
442
443
444 @Override
445 @SuppressWarnings({"checkstyle:needbraces", "checkstyle:designforextension"})
446 public boolean equals(final Object obj)
447 {
448 if (this == obj)
449 return true;
450 if (obj == null)
451 return false;
452 if (!(obj instanceof FloatVectorData))
453 return false;
454 FloatVectorData/../../../org/djunits/value/vfloat/vector/data/FloatVectorData.html#FloatVectorData">FloatVectorData other = (FloatVectorData) obj;
455 if (this.size() != other.size())
456 return false;
457 if (other instanceof FloatVectorDataDense)
458 return super.equals(other);
459 if (getClass() != obj.getClass())
460 return false;
461
462 if (!Arrays.equals(this.indices, ((FloatVectorDataSparse) other).indices))
463 return false;
464 return Arrays.equals(this.vectorSI, ((FloatVectorDataSparse) other).vectorSI);
465 }
466
467 }