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