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