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