1 package org.djunits.vecmat.storage;
2
3 import java.util.Arrays;
4 import java.util.List;
5 import java.util.Objects;
6
7 import org.djunits.quantity.def.AbsQuantity;
8 import org.djunits.quantity.def.Quantity;
9 import org.djunits.quantity.def.Reference;
10 import org.djunits.unit.UnitInterface;
11 import org.djunits.util.SuppressFBWarnings;
12 import org.djutils.exceptions.Throw;
13
14
15
16
17
18
19
20
21
22
23 public class DenseDoubleDataSi implements DataGridSi<DenseDoubleDataSi>
24 {
25
26 private static final long serialVersionUID = 601L;
27
28
29 private final double[] dataSi;
30
31
32 private final int rows;
33
34
35 private final int cols;
36
37
38
39
40
41
42
43
44
45
46 @SuppressFBWarnings(justification = "explicitly documented that no safe copy is made")
47 public DenseDoubleDataSi(final double[] dataSi, final int rows, final int cols)
48 {
49 Throw.whenNull(dataSi, "dataSi");
50 Throw.when(rows <= 0, IllegalArgumentException.class, "Number of rows <= 0");
51 Throw.when(cols <= 0, IllegalArgumentException.class, "Number of columns <= 0");
52 Throw.when(dataSi.length != rows * cols, IllegalArgumentException.class,
53 "Data object length != rows * cols, %d != %d * %d", dataSi.length, rows, cols);
54 this.dataSi = dataSi;
55 this.rows = rows;
56 this.cols = cols;
57 }
58
59
60
61
62
63
64
65
66
67
68 public static DenseDoubleDataSi ofSi(final double[] dataSi, final int rows, final int cols)
69 {
70 return new DenseDoubleDataSi(dataSi.clone(), rows, cols);
71 }
72
73
74
75
76
77
78
79
80
81
82
83
84 public static <Q extends Quantity<Q>> DenseDoubleDataSi of(final double[] dataInUnit, final int rows, final int cols,
85 final UnitInterface<Q> unit)
86 {
87 Throw.whenNull(dataInUnit, "dataInUnit");
88 Throw.whenNull(unit, "unit");
89 double[] dataSi = new double[dataInUnit.length];
90 for (int i = 0; i < dataInUnit.length; i++)
91 {
92 dataSi[i] = unit.toBaseValue(dataInUnit[i]);
93 }
94 return new DenseDoubleDataSi(dataSi, rows, cols);
95 }
96
97
98
99
100
101
102
103
104
105
106
107 public static <Q extends Quantity<Q>> DenseDoubleDataSi of(final Q[] data, final int rows, final int cols)
108 {
109 Throw.whenNull(data, "data");
110 Throw.when(data.length != rows * cols, IllegalArgumentException.class, "Q[] length != rows * cols");
111 double[] dataSi = new double[data.length];
112 for (int i = 0; i < data.length; i++)
113 {
114 Throw.whenNull(data[i], "data[%d] = null", i);
115 dataSi[i] = data[i].si();
116 }
117 return new DenseDoubleDataSi(dataSi, rows, cols);
118 }
119
120
121
122
123
124
125
126
127
128
129
130
131 public static <A extends AbsQuantity<A, Q, ?>, Q extends Quantity<Q>> DenseDoubleDataSi of(final A[] absData,
132 final int rows, final int cols)
133 {
134 Throw.whenNull(absData, "absData");
135 Throw.when(rows == 0, IllegalArgumentException.class, "rows = 0");
136 Throw.when(cols == 0, IllegalArgumentException.class, "cols = 0");
137 Throw.when(absData.length != rows * cols, IllegalArgumentException.class, "A[] length != rows * cols");
138 Throw.whenNull(absData[0], "absData[0] = null");
139 Reference<?, A, Q> reference = absData[0].getReference();
140 double[] dataSi = new double[rows * cols];
141 for (int i = 0; i < rows * cols; i++)
142 {
143 Throw.whenNull(absData[i], "absGrid[%d] = null", i);
144 Throw.when(!reference.equals(absData[i].getReference()), IllegalArgumentException.class,
145 "Reference of absData[%d] != %s, but %s", i, reference.toString(), absData[i].getReference().toString());
146 dataSi[i] = absData[i].si();
147 }
148 return new DenseDoubleDataSi(dataSi, rows, cols);
149 }
150
151
152
153
154
155
156
157
158
159
160
161
162 public static <A extends AbsQuantity<A, Q, ?>, Q extends Quantity<Q>> DenseDoubleDataSi of(final List<A> absData,
163 final int rows, final int cols)
164 {
165 Throw.whenNull(absData, "absData");
166 Throw.when(rows == 0, IllegalArgumentException.class, "rows = 0");
167 Throw.when(cols == 0, IllegalArgumentException.class, "cols = 0");
168 Throw.when(absData.size() != rows * cols, IllegalArgumentException.class, "List size != rows * cols");
169 Throw.whenNull(absData.get(0), "absData[0] = null");
170 Reference<?, A, Q> reference = absData.get(0).getReference();
171 double[] dataSi = new double[rows * cols];
172 for (int i = 0; i < rows * cols; i++)
173 {
174 Throw.whenNull(absData.get(i), "absData[%d] = null", i);
175 Throw.when(!reference.equals(absData.get(i).getReference()), IllegalArgumentException.class,
176 "Reference of absGrid[%d] != %s, but %s", i, reference.toString(),
177 absData.get(i).getReference().toString());
178 dataSi[i] = absData.get(i).si();
179 }
180 return new DenseDoubleDataSi(dataSi, rows, cols);
181 }
182
183
184
185
186
187
188
189 public static DenseDoubleDataSi ofSi(final double[][] gridSi)
190 {
191 Throw.whenNull(gridSi, "gridSi");
192 Throw.when(gridSi.length == 0, IllegalArgumentException.class, "Number of rows in the data grid = 0");
193 int rows = gridSi.length;
194 Throw.whenNull(gridSi[0], "gridSi[0] = null");
195 int cols = gridSi[0].length;
196 double[] dataSi = new double[rows * cols];
197 for (int r = 0; r < rows; r++)
198 {
199 Throw.whenNull(gridSi[r], "gridSi[%d] = null", r);
200 Throw.when(gridSi[r].length != cols, IllegalArgumentException.class,
201 "Number of columns in row %d (%d) is not equal to number of columns in row 0 (%d)", r, gridSi[r].length,
202 cols);
203 for (int c = 0; c < cols; c++)
204 {
205 dataSi[r * cols + c] = gridSi[r][c];
206 }
207 }
208 return new DenseDoubleDataSi(dataSi, rows, cols);
209 }
210
211
212
213
214
215
216
217
218
219 public static <Q extends Quantity<Q>> DenseDoubleDataSi of(final double[][] gridInUnit, final UnitInterface<Q> unit)
220 {
221 Throw.whenNull(gridInUnit, "gridInUnit");
222 Throw.whenNull(unit, "unit");
223 Throw.when(gridInUnit.length == 0, IllegalArgumentException.class, "Number of rows in the data grid = 0");
224 int rows = gridInUnit.length;
225 Throw.whenNull(gridInUnit[0], "gridInUnit[0] = null");
226 int cols = gridInUnit[0].length;
227 double[] dataSi = new double[rows * cols];
228 for (int r = 0; r < rows; r++)
229 {
230 Throw.whenNull(gridInUnit[r], "gridInUnit[%d] = null", r);
231 Throw.when(gridInUnit[r].length != cols, IllegalArgumentException.class,
232 "Number of columns in row %d (%d) is not equal to number of columns in row 0 (%d)", r, gridInUnit[r].length,
233 cols);
234 for (int c = 0; c < cols; c++)
235 {
236 dataSi[r * cols + c] = unit.toBaseValue(gridInUnit[r][c]);
237 }
238 }
239 return new DenseDoubleDataSi(dataSi, rows, cols);
240 }
241
242
243
244
245
246
247
248
249 public static <Q extends Quantity<Q>> DenseDoubleDataSi of(final Q[][] grid)
250 {
251 Throw.whenNull(grid, "grid");
252 Throw.when(grid.length == 0, IllegalArgumentException.class, "Number of rows in the data grid = 0");
253 int rows = grid.length;
254 Throw.whenNull(grid[0], "grid[0] = null");
255 int cols = grid[0].length;
256 double[] dataSi = new double[rows * cols];
257 for (int r = 0; r < rows; r++)
258 {
259 Throw.whenNull(grid[r], "grid[%d] = null", r);
260 Throw.when(grid[r].length != cols, IllegalArgumentException.class,
261 "Number of columns in row %d (%d) is not equal to number of columns in row 0 (%d)", r, grid[r].length,
262 cols);
263 for (int c = 0; c < cols; c++)
264 {
265 Throw.whenNull(grid[r][c], "grid[%d][%d] = null", r, c);
266 dataSi[r * cols + c] = grid[r][c].si();
267 }
268 }
269 return new DenseDoubleDataSi(dataSi, rows, cols);
270 }
271
272
273
274
275
276
277
278
279
280 public static <A extends AbsQuantity<A, Q, ?>, Q extends Quantity<Q>> DenseDoubleDataSi of(final A[][] absGrid)
281 {
282 Throw.whenNull(absGrid, "absGrid");
283 int rows = absGrid.length;
284 Throw.when(rows == 0, IllegalArgumentException.class, "rows = 0");
285 Throw.whenNull(absGrid[0], "absGrid[0] = null");
286 int cols = absGrid[0].length;
287 Throw.when(cols == 0, IllegalArgumentException.class, "cols = 0");
288 Throw.whenNull(absGrid[0][0], "absGrid[0][0] = null");
289 Reference<?, A, Q> reference = absGrid[0][0].getReference();
290 double[] dataSi = new double[rows * cols];
291 for (int r = 0; r < rows; r++)
292 {
293 Throw.whenNull(absGrid[r], "absGrid[%d] = null", r);
294 Throw.when(absGrid[r].length != cols, IllegalArgumentException.class,
295 "Number of columns in row %d (%d) is not equal to number of columns in row 0 (%d)", r, absGrid[r].length,
296 cols);
297 for (int c = 0; c < cols; c++)
298 {
299 Throw.whenNull(absGrid[r][c], "absGrid[%d][%d] = null", r, c);
300 Throw.when(!reference.equals(absGrid[r][c].getReference()), IllegalArgumentException.class,
301 "Reference of absGrid[%d][%d] != %s, but %s", r, c, reference.toString(),
302 absGrid[r][c].getReference().toString());
303 dataSi[r * cols + c] = absGrid[r][c].si();
304 }
305 }
306 return new DenseDoubleDataSi(dataSi, rows, cols);
307 }
308
309 @Override
310 public int rows()
311 {
312 return this.rows;
313 }
314
315 @Override
316 public int cols()
317 {
318 return this.cols;
319 }
320
321 @Override
322 public boolean isDense()
323 {
324 return true;
325 }
326
327 @Override
328 public boolean isDouble()
329 {
330 return true;
331 }
332
333
334
335
336
337
338
339 private void checkRowCol(final int row, final int col) throws IndexOutOfBoundsException
340 {
341 Throw.when(row < 0 || row >= this.rows, IndexOutOfBoundsException.class, "row %d not in range 0..%d", row, this.rows);
342 Throw.when(col < 0 || col >= this.cols, IndexOutOfBoundsException.class, "column %d not in range 0..%d", col,
343 this.cols);
344 }
345
346 @Override
347 public double get(final int row, final int col)
348 {
349 checkRowCol(row, col);
350 return this.dataSi[row * this.cols + col];
351 }
352
353 @Override
354 @SuppressFBWarnings(justification = "name of the method indicates unsafe access")
355 public double[] unsafeSiArray()
356 {
357 return this.dataSi;
358 }
359
360 @Override
361 public double[] getSiArray()
362 {
363 return this.dataSi.clone();
364 }
365
366 @Override
367 public DenseDoubleDataSi copy()
368 {
369 return new DenseDoubleDataSi(this.dataSi.clone(), rows(), cols());
370 }
371
372 @SuppressWarnings("checkstyle:needbraces")
373 @Override
374 public int nonZeroCount()
375 {
376 int result = 0;
377 for (int i = 0; i < this.dataSi.length; i++)
378 result += this.dataSi[i] == 0.0 ? 0 : 1;
379 return result;
380 }
381
382 @Override
383 public DenseDoubleDataSi instantiateNew(final double[] newData)
384 {
385 Throw.when(newData.length != rows() * cols(), IllegalArgumentException.class,
386 "Data object length != rows * cols, %d != %d * %d", newData.length, rows(), cols());
387 return new DenseDoubleDataSi(newData, rows(), cols());
388 }
389
390 @Override
391 public DenseDoubleDataSi instantiateNew(final double[] newData, final int newRows, final int newCols)
392 {
393 Throw.when(newData.length != newRows * newCols, IllegalArgumentException.class,
394 "Data object length != rows * cols, %d != %d * %d", newData.length, newRows, newCols);
395 return new DenseDoubleDataSi(newData, newRows, newCols);
396 }
397
398 @Override
399 public int hashCode()
400 {
401 final int prime = 31;
402 int result = 1;
403 result = prime * result + Arrays.hashCode(this.dataSi);
404 result = prime * result + Objects.hash(this.cols, this.rows);
405 return result;
406 }
407
408 @SuppressWarnings("checkstyle:needbraces")
409 @Override
410 public boolean equals(final Object obj)
411 {
412 if (this == obj)
413 return true;
414 if (obj == null)
415 return false;
416 if (getClass() != obj.getClass())
417 {
418 if (obj instanceof DataGridSi dg)
419 return this.cols == dg.cols() && this.rows == dg.rows() && Arrays.equals(this.dataSi, dg.unsafeSiArray());
420 return false;
421 }
422 DenseDoubleDataSi other = (DenseDoubleDataSi) obj;
423 return this.cols == other.cols && this.rows == other.rows && Arrays.equals(this.dataSi, other.dataSi);
424 }
425
426 }