1 package org.djunits.value.vdouble.matrix;
2
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.assertFalse;
5 import static org.junit.Assert.assertNotEquals;
6 import static org.junit.Assert.assertTrue;
7 import static org.junit.Assert.fail;
8
9 import java.lang.reflect.InvocationTargetException;
10 import java.lang.reflect.Method;
11
12 import org.djunits.unit.AbsoluteTemperatureUnit;
13 import org.djunits.unit.AngleUnit;
14 import org.djunits.unit.AreaUnit;
15 import org.djunits.unit.DirectionUnit;
16 import org.djunits.unit.DurationUnit;
17 import org.djunits.unit.LengthUnit;
18 import org.djunits.unit.PositionUnit;
19 import org.djunits.unit.SIUnit;
20 import org.djunits.unit.TemperatureUnit;
21 import org.djunits.unit.TimeUnit;
22 import org.djunits.unit.Unit;
23 import org.djunits.unit.quantity.Quantities;
24 import org.djunits.unit.quantity.Quantity;
25 import org.djunits.unit.util.UnitException;
26 import org.djunits.unit.util.UnitRuntimeException;
27 import org.djunits.value.CLASSNAMES;
28 import org.djunits.value.ValueRuntimeException;
29 import org.djunits.value.storage.StorageType;
30 import org.djunits.value.vdouble.function.DoubleMathFunctions;
31 import org.djunits.value.vdouble.matrix.base.AbstractDoubleMatrixRel;
32 import org.djunits.value.vdouble.matrix.base.DoubleMatrix;
33 import org.djunits.value.vdouble.matrix.base.DoubleSparseValue;
34 import org.djunits.value.vdouble.matrix.data.DoubleMatrixData;
35 import org.djunits.value.vdouble.scalar.AbsoluteTemperature;
36 import org.djunits.value.vdouble.scalar.Area;
37 import org.djunits.value.vdouble.scalar.Direction;
38 import org.djunits.value.vdouble.scalar.Duration;
39 import org.djunits.value.vdouble.scalar.Length;
40 import org.djunits.value.vdouble.scalar.Position;
41 import org.djunits.value.vdouble.scalar.Time;
42 import org.djunits.value.vdouble.vector.AreaVector;
43 import org.djunits.value.vfloat.matrix.FloatAreaMatrix;
44 import org.djunits.value.vfloat.matrix.base.FloatMatrix;
45 import org.djunits.value.vfloat.vector.FLOATVECTOR;
46 import org.djutils.exceptions.Try;
47 import org.junit.Test;
48
49
50
51
52 public class DoubleMatrixMethodTest
53 {
54
55
56
57
58
59
60 @Test
61 @SuppressWarnings("checkstyle:methodlength")
62 public void testMatrixMethods() throws ValueRuntimeException, UnitException
63 {
64 double[][] denseTestData = DOUBLEMATRIX.denseRectArrays(10, 20);
65 double[][] sparseTestData = DOUBLEMATRIX.sparseRectArrays(10, 20);
66 double[][] reverseSparseTestData = new double[sparseTestData.length][];
67
68 for (int index = 0; index < sparseTestData.length; index++)
69 {
70 reverseSparseTestData[reverseSparseTestData.length - 1 - index] = sparseTestData[index];
71 }
72
73 for (int row = 1; row < 8; row++)
74 {
75 for (int col = 2; col < 18; col++)
76 {
77 sparseTestData[row][col] = 10000.456 + row + 100 * col;
78 reverseSparseTestData[row][col] = 20000.567 + row + 100 * col;
79 }
80 }
81
82 for (StorageType storageType : new StorageType[] {StorageType.DENSE, StorageType.SPARSE})
83 {
84 for (AreaUnit au : new AreaUnit[] {AreaUnit.SQUARE_METER, AreaUnit.ACRE})
85 {
86 double[][] testData = storageType.equals(StorageType.DENSE) ? denseTestData : sparseTestData;
87 AreaMatrix am =
88 DoubleMatrix.instantiate(DoubleMatrixData.instantiate(testData, au.getScale(), storageType), au);
89
90
91 for (int row : new int[] {-1, 0, denseTestData.length - 1, denseTestData.length})
92 {
93 for (int col : new int[] {-1, 0, denseTestData[0].length - 1, denseTestData[0].length})
94 {
95 if (row < 0 || col < 0 || row >= denseTestData.length || col >= denseTestData[0].length)
96 {
97 try
98 {
99 am.get(row, col);
100 fail("bad row or bad column value should have thrown a ValueRuntimeException");
101 }
102 catch (ValueRuntimeException vre)
103 {
104
105 }
106 }
107 else
108 {
109 am.get(row, col);
110 }
111 }
112 if (row < 0 || row >= denseTestData.length)
113 {
114 try
115 {
116 am.getRow(row);
117 fail("getRow with bad row value should have thrown a ValueRuntimeException");
118 }
119 catch (ValueRuntimeException vre)
120 {
121
122 }
123 }
124 }
125 for (int col : new int[] {-1, 0, denseTestData[0].length - 1, denseTestData[0].length})
126 {
127 if (col < 0 || col >= denseTestData[0].length)
128 {
129 try
130 {
131 am.getColumn(col);
132 fail("getColumn with bad column value should have thrown a ValueRuntimeException");
133 }
134 catch (ValueRuntimeException vre)
135 {
136
137 }
138 }
139 else
140 {
141 am.getColumn(col);
142 }
143 }
144
145
146 assertEquals(am, am.toSparse());
147 assertEquals(am, am.toDense());
148 assertEquals(am, am.toSparse().toDense());
149 assertEquals(am, am.toDense().toSparse());
150 assertEquals(am.hashCode(), am.toSparse().hashCode());
151 assertEquals(am.hashCode(), am.toDense().hashCode());
152 assertTrue(am.toDense().isDense());
153 assertFalse(am.toDense().isSparse());
154 assertTrue(am.toSparse().isSparse());
155 assertFalse(am.toSparse().isDense());
156
157
158 assertEquals(am, am);
159 assertNotEquals(am, new Object());
160 assertNotEquals(am, null);
161 assertNotEquals(am, DoubleMatrix.instantiate(
162 DoubleMatrixData.instantiate(testData, LengthUnit.METER.getScale(), storageType), LengthUnit.METER));
163 assertNotEquals(am, am.divide(2.0d));
164
165
166 assertFalse(am.isMutable());
167 AreaMatrix ammut = am.mutable();
168 assertTrue(ammut.isMutable());
169 assertFalse(am.isMutable());
170 AreaMatrix ammut2 = ammut.multiplyBy(1.0);
171 assertEquals(am, ammut2);
172 assertTrue(ammut.isMutable());
173 assertFalse(am.isMutable());
174 assertTrue(ammut2.isMutable());
175 ammut2 = ammut2.mutable().divideBy(2.0);
176 assertEquals(am, ammut);
177 assertNotEquals(am, ammut2);
178 AreaMatrix ammut3 = ammut2.mutable().divideBy(0.0);
179 for (int row = 0; row < ammut3.rows(); row++)
180 {
181 for (int col = 0; col < ammut3.cols(); col++)
182 {
183 if (ammut2.getSI(row, col) == 0)
184 {
185 assertTrue("Value should be NaN", Double.isNaN(ammut3.getSI(row, col)));
186
187 }
188 else
189 {
190 assertTrue("Value should be Infinite", Double.isInfinite(ammut3.getSI(row, col)));
191 }
192 }
193 }
194
195
196 Area zSum = am.zSum();
197 double sum = 0;
198 int card = 0;
199 for (int row = 0; row < testData.length; row++)
200 {
201 for (int col = 0; col < testData[0].length; col++)
202 {
203 sum += testData[row][col];
204 card += testData[row][col] == 0.0d ? 0 : 1;
205 }
206 }
207 assertEquals("zSum", sum, zSum.getInUnit(), 0.1);
208 assertEquals("cardinality", card, am.cardinality());
209 AreaMatrix ammutZero = ammut.multiplyBy(0.0);
210 assertEquals("cardinality should be 0", 0, ammutZero.cardinality());
211 assertEquals("zSum should be 0", 0.0, ammutZero.zSum().getSI(), 0);
212
213
214 AreaMatrix amold = am.clone();
215 Area fa = Area.of(10.0d, "m^2");
216 AreaMatrix aminc = am.mutable().incrementBy(fa).immutable();
217 AreaMatrix amdec = am.mutable().decrementBy(fa).immutable();
218 AreaMatrix amid = aminc.mutable().decrementBy(fa);
219 assertEquals("immutable matrix should not change when converted to mutable", am, amold);
220 for (int row = 0; row < testData.length; row++)
221 {
222 for (int col = 0; col < testData[0].length; col++)
223 {
224 assertEquals("increment and decrement with scalar should result in same matrix", am.getSI(row, col),
225 amid.getSI(row, col), 0.1);
226 assertEquals("m + s = (m+s)", au.getScale().toStandardUnit(testData[row][col]) + 10.0,
227 aminc.getSI(row, col), 0.1);
228 assertEquals("m - s = (m-s)", au.getScale().toStandardUnit(testData[row][col]) - 10.0,
229 amdec.getSI(row, col), 0.1);
230 }
231 }
232
233
234 AreaMatrix amt5 = am.mutable().multiplyBy(5.0d).immutable();
235 AreaMatrix amd5 = am.mutable().divideBy(5.0d).immutable();
236 AreaMatrix amtd = amt5.mutable().divideBy(5.0d);
237 AreaMatrix amtimD = am.times(5.0d);
238 AreaMatrix amtimF = am.times(5.0f);
239 AreaMatrix amdivD = am.divide(5.0d);
240 AreaMatrix amdivF = am.divide(5.0f);
241 for (int row = 0; row < testData.length; row++)
242 {
243 for (int col = 0; col < testData[0].length; col++)
244 {
245 assertEquals("times followed by divide with constant should result in same matrix", am.getSI(row, col),
246 amtd.getSI(row, col), 0.1);
247 assertEquals("m * 5.0 = (m*5.0)", au.getScale().toStandardUnit(testData[row][col]) * 5.0d,
248 amt5.getSI(row, col), 0.1);
249 assertEquals("m / 5.0 = (m/5.0)", au.getScale().toStandardUnit(testData[row][col]) / 5.0d,
250 amd5.getSI(row, col), 0.1);
251 assertEquals("amtimD", amt5.getSI(row, col), amtimD.getSI(row, col), 0.1d);
252 assertEquals("amtimF", amt5.getSI(row, col), amtimF.getSI(row, col), 0.1d);
253 assertEquals("amdivD", amd5.getSI(row, col), amdivD.getSI(row, col), 0.01d);
254 assertEquals("amdivD", amd5.getSI(row, col), amdivF.getSI(row, col), 0.01d);
255 }
256 }
257
258
259 assertEquals("get()", new Area(testData[2][2], au), am.get(2, 2));
260 assertEquals("getSI()", au.getScale().toStandardUnit(testData[2][2]), am.getSI(2, 2), 0.1);
261 assertEquals("getInUnit()", testData[2][2], am.getInUnit(2, 2), 0.1);
262 assertEquals("getInUnit(unit)",
263 AreaUnit.SQUARE_YARD.getScale().fromStandardUnit(au.getScale().toStandardUnit(testData[2][2])),
264 am.getInUnit(2, 2, AreaUnit.SQUARE_YARD), 0.1);
265
266
267 Area fasqft = new Area(10.5d, AreaUnit.SQUARE_FOOT);
268 AreaMatrix famChange = am.clone().mutable();
269 famChange.set(2, 2, fasqft);
270 assertEquals("set()", fasqft.si, famChange.get(2, 2).si, 0.1d);
271 famChange = am.clone().mutable();
272 famChange.setSI(2, 2, 123.4d);
273 assertEquals("setSI()", 123.4d, famChange.get(2, 2).si, 0.1d);
274 famChange = am.clone().mutable();
275 famChange.setInUnit(2, 2, 1.2d);
276 assertEquals("setInUnit()", 1.2d, famChange.getInUnit(2, 2), 0.1d);
277 famChange = am.clone().mutable();
278 famChange.setInUnit(2, 2, 1.5d, AreaUnit.HECTARE);
279 assertEquals("setInUnit(unit)", 15000.0d, famChange.get(2, 2).si, 1.0d);
280
281
282 double[][] squareData = storageType.equals(StorageType.DENSE) ? DOUBLEMATRIX.denseRectArrays(12, 12)
283 : DOUBLEMATRIX.sparseRectArrays(12, 12);
284 AreaMatrix amSquare =
285 DoubleMatrix.instantiate(DoubleMatrixData.instantiate(squareData, au.getScale(), storageType), au);
286 double[] row2si = am.getRowSI(2);
287 double[] col2si = am.getColumnSI(2);
288 double[] diagsi = amSquare.getDiagonalSI();
289 AreaVector row2v = am.getRow(2);
290 AreaVector col2v = am.getColumn(2);
291 AreaVector diagv = amSquare.getDiagonal();
292 Area[] row2scalar = am.getRowScalars(2);
293 Area[] col2scalar = am.getColumnScalars(2);
294 Area[] diagscalar = amSquare.getDiagonalScalars();
295 for (int col = 0; col < testData[0].length; col++)
296 {
297 assertEquals("row2si", au.getScale().toStandardUnit(testData[2][col]), row2si[col], 0.1d);
298 assertEquals("row2v", au.getScale().toStandardUnit(testData[2][col]), row2v.getSI(col), 0.1d);
299 assertEquals("row2scalar", au.getScale().toStandardUnit(testData[2][col]), row2scalar[col].si, 0.1d);
300 }
301 for (int row = 0; row < testData.length; row++)
302 {
303 assertEquals("col2si", au.getScale().toStandardUnit(testData[row][2]), col2si[row], 0.1d);
304 assertEquals("col2v", au.getScale().toStandardUnit(testData[row][2]), col2v.getSI(row), 0.1d);
305 assertEquals("col2scalar", au.getScale().toStandardUnit(testData[row][2]), col2scalar[row].si, 0.1d);
306 }
307 for (int diag = 0; diag < amSquare.rows(); diag++)
308 {
309 assertEquals("diag2si", au.getScale().toStandardUnit(squareData[diag][diag]), diagsi[diag], 0.1d);
310 assertEquals("diag2v", au.getScale().toStandardUnit(squareData[diag][diag]), diagv.getSI(diag), 0.1d);
311 assertEquals("diag2scalar", au.getScale().toStandardUnit(squareData[diag][diag]), diagscalar[diag].si,
312 0.1d);
313 }
314
315
316 double[][] valsi = am.getValuesSI();
317 double[][] valunit = am.getValuesInUnit();
318 double[][] valsqft = am.getValuesInUnit(AreaUnit.SQUARE_YARD);
319 Area[][] valscalars = am.getScalars();
320 for (int row = 0; row < testData.length; row++)
321 {
322 for (int col = 0; col < testData[0].length; col++)
323 {
324 assertEquals("getValuesSI()", au.getScale().toStandardUnit(testData[row][col]), valsi[row][col], 0.1);
325 assertEquals("getValuesInUnit()", testData[row][col], valunit[row][col], 0.1);
326 assertEquals("getValuesInUnit(unit)", AreaUnit.SQUARE_YARD.getScale()
327 .fromStandardUnit(au.getScale().toStandardUnit(testData[row][col])), valsqft[row][col], 0.1);
328 assertEquals("getValuesInUnit(unit)", au.getScale().toStandardUnit(testData[row][col]),
329 valscalars[row][col].si, 0.1);
330 }
331 }
332
333
334 AreaMatrix amdiv2 = am.divide(2.0d);
335 assertEquals(am.getStorageType(), amdiv2.getStorageType());
336 assertEquals(am.getDisplayUnit(), amdiv2.getDisplayUnit());
337 AreaMatrix amAbs = amdiv2.mutable().abs().immutable();
338 assertEquals(am.getStorageType(), amAbs.getStorageType());
339 assertEquals(am.getDisplayUnit(), amAbs.getDisplayUnit());
340 AreaMatrix amCeil = amdiv2.mutable().ceil().immutable();
341 assertEquals(am.getStorageType(), amCeil.getStorageType());
342 assertEquals(am.getDisplayUnit(), amCeil.getDisplayUnit());
343 AreaMatrix amFloor = amdiv2.mutable().floor().immutable();
344 assertEquals(am.getStorageType(), amFloor.getStorageType());
345 assertEquals(am.getDisplayUnit(), amFloor.getDisplayUnit());
346 AreaMatrix amNeg = amdiv2.mutable().neg().immutable();
347 assertEquals(am.getStorageType(), amNeg.getStorageType());
348 assertEquals(am.getDisplayUnit(), amNeg.getDisplayUnit());
349 AreaMatrix amRint = amdiv2.mutable().rint().immutable();
350 assertEquals(am.getStorageType(), amRint.getStorageType());
351 assertEquals(am.getDisplayUnit(), amRint.getDisplayUnit());
352 for (int row = 0; row < testData.length; row++)
353 {
354 for (int col = 0; col < testData[0].length; col++)
355 {
356
357 assertEquals("div2", au.getScale().toStandardUnit(testData[row][col]) / 2.0d, amdiv2.getSI(row, col),
358 0.1d);
359 assertEquals("abs", Math.abs(au.getScale().toStandardUnit(testData[row][col]) / 2.0d),
360 amAbs.getSI(row, col), 0.1d);
361 assertEquals("ceil", Math.ceil(au.getScale().toStandardUnit(testData[row][col]) / 2.0d),
362 amCeil.getSI(row, col), 0.1d);
363 assertEquals("floor", Math.floor(au.getScale().toStandardUnit(testData[row][col]) / 2.0d),
364 amFloor.getSI(row, col), 0.1d);
365 assertEquals("neg", -au.getScale().toStandardUnit(testData[row][col]) / 2.0d, amNeg.getSI(row, col),
366 0.1d);
367 assertEquals("rint", Math.rint(au.getScale().toStandardUnit(testData[row][col]) / 2.0d),
368 amRint.getSI(row, col), 0.1d);
369 }
370 }
371
372 double[][] testData4x4 = new double[][] {{2, 3, 5, 7}, {11, 13, 17, 19}, {23, 29, 31, 37}, {41, 43, 47, 49}};
373 AreaMatrix am4x4 =
374 DoubleMatrix.instantiate(DoubleMatrixData.instantiate(testData4x4, au.getScale(), storageType), au);
375 double det = am4x4.determinantSI();
376 double detCalc = Determinant.det(am4x4.getValuesSI());
377 double err = Math.max(det, detCalc) / 10000.0;
378 assertEquals("Determinant of square matrix with unit " + au.getDefaultTextualAbbreviation() + ", storage = "
379 + storageType + " = " + det + " but should have been " + detCalc, detCalc, det, err);
380 Try.testFail(() -> am.determinantSI(), "Determinant of non-square matrix should have thrown exception");
381
382
383
384 for (StorageType storageType2 : new StorageType[] {StorageType.DENSE, StorageType.SPARSE})
385 {
386 double[][] testData2 = storageType2.equals(StorageType.DENSE) ? denseTestData : reverseSparseTestData;
387 for (AreaUnit au2 : new AreaUnit[] {AreaUnit.SQUARE_METER, AreaUnit.ACRE})
388 {
389
390
391 AreaMatrix am2 = DoubleMatrix
392 .instantiate(DoubleMatrixData.instantiate(testData2, au2.getScale(), storageType2), au2);
393 AreaMatrix amSum1 = am.plus(am2);
394 AreaMatrix amSum2 = am2.plus(am);
395 AreaMatrix amSum3 = am.mutable().incrementBy(am2).immutable();
396 AreaMatrix amSum4 = am2.mutable().incrementBy(am).immutable();
397 assertEquals("a+b == b+a", amSum1, amSum2);
398 assertEquals("a+b == b+a", amSum1, amSum3);
399 assertEquals("a+b == b+a", amSum1, amSum4);
400 for (int row = 0; row < testData.length; row++)
401 {
402 for (int col = 0; col < testData[0].length; col++)
403 {
404 double tolerance = Double.isFinite(amSum1.getSI(row, col))
405 ? Math.abs(amSum1.getSI(row, col) / 10000.0d) : 0.1d;
406 assertEquals("value in matrix matches",
407 au.getScale().toStandardUnit(testData[row][col])
408 + au2.getScale().toStandardUnit(testData2[row][col]),
409 amSum1.getSI(row, col), tolerance);
410 }
411 }
412
413
414 AreaMatrix amDiff1 = am.minus(am2);
415 AreaMatrix amDiff2 = am2.minus(am).mutable().neg();
416 AreaMatrix amDiff3 = am.mutable().decrementBy(am2).immutable();
417 assertEquals("a-b == -(b-a)", amDiff1, amDiff2);
418 assertEquals("a-b == -(b-a)", amDiff1, amDiff3);
419 for (int row = 0; row < testData.length; row++)
420 {
421 for (int col = 0; col < testData[0].length; col++)
422 {
423 double tolerance = Double.isFinite(amDiff1.getSI(row, col))
424 ? Math.abs(amDiff1.getSI(row, col) / 10000.0d) : 0.1d;
425 assertEquals("value in matrix matches",
426 au.getScale().toStandardUnit(testData[row][col])
427 - au2.getScale().toStandardUnit(testData2[row][col]),
428 amDiff1.getSI(row, col), tolerance);
429 }
430 }
431
432
433 SIMatrix amTim = am.times(am2);
434 SIMatrix amDiv = am.divide(am2);
435 assertEquals("unit of m2 * m2 should be m4", "m4",
436 amTim.getDisplayUnit().getQuantity().getSiDimensions().toString(false, false, false));
437 assertEquals("unit of m2 / m2 should be 1", "1",
438 amDiv.getDisplayUnit().getQuantity().getSiDimensions().toString(false, false, false));
439 for (int row = 0; row < testData.length; row++)
440 {
441 for (int col = 0; col < testData[0].length; col++)
442 {
443 double tolerance = Double.isFinite(amTim.getSI(row, col))
444 ? Math.abs(amTim.getSI(row, col) / 10000.0d) : 0.1d;
445 if (Math.abs(au.getScale().toStandardUnit(testData[row][col])
446 * au2.getScale().toStandardUnit(testData2[row][col])
447 - amTim.getSI(row, col)) > tolerance)
448 {
449
450
451
452
453 am.times(am2);
454 }
455 assertEquals("value in m2 * m2 matches",
456 au.getScale().toStandardUnit(testData[row][col])
457 * au2.getScale().toStandardUnit(testData2[row][col]),
458 amTim.getSI(row, col), tolerance);
459 tolerance = Double.isFinite(amTim.getSI(row, col)) ? Math.abs(amDiv.getSI(row, col) / 10000.0d)
460 : 0.1d;
461 assertEquals("value in m2 / m2 matches (could be NaN)",
462 au.getScale().toStandardUnit(testData[row][col])
463 / au2.getScale().toStandardUnit(testData2[row][col]),
464 amDiv.getSI(row, col), tolerance);
465 }
466 }
467 }
468 }
469 }
470 }
471 }
472
473
474
475
476 @Test
477 public void testImmutableMatrix()
478 {
479 double[][] denseTestData = DOUBLEMATRIX.denseRectArrays(5, 10);
480 double[][] sparseTestData = DOUBLEMATRIX.sparseRectArrays(5, 10);
481
482 for (StorageType storageType : new StorageType[] {StorageType.DENSE, StorageType.SPARSE})
483 {
484 for (AreaUnit au : new AreaUnit[] {AreaUnit.SQUARE_METER, AreaUnit.ACRE})
485 {
486 double[][] testData = storageType.equals(StorageType.DENSE) ? denseTestData : sparseTestData;
487 AreaMatrix am =
488 DoubleMatrix.instantiate(DoubleMatrixData.instantiate(testData, au.getScale(), storageType), au);
489 am = am.immutable();
490 final AreaMatrix amPtr = am;
491 Area fa = Area.of(10.0d, "m^2");
492 Try.testFail(() -> amPtr.assign(DoubleMathFunctions.ABS), "ImmutableMatrix.assign(...) should throw error");
493 Try.testFail(() -> amPtr.decrementBy(fa), "ImmutableMatrix.decrementBy(scalar) should throw error");
494 Try.testFail(() -> amPtr.decrementBy(amPtr), "ImmutableMatrix.decrementBy(matrix) should throw error");
495 Try.testFail(() -> amPtr.incrementBy(fa), "ImmutableMatrix.incrementBy(scalar) should throw error");
496 Try.testFail(() -> amPtr.incrementBy(amPtr), "ImmutableMatrix.incrementBy(matrix) should throw error");
497 Try.testFail(() -> amPtr.divideBy(2.0d), "ImmutableMatrix.divideBy(factor) should throw error");
498 Try.testFail(() -> amPtr.multiplyBy(2.0d), "ImmutableMatrix.multiplyBy(factor) should throw error");
499 Try.testFail(() -> amPtr.set(1, 1, fa), "ImmutableMatrix.set() should throw error");
500 Try.testFail(() -> amPtr.setSI(1, 1, 20.1d), "ImmutableMatrix.setSI() should throw error");
501 Try.testFail(() -> amPtr.setInUnit(1, 1, 15.2d), "ImmutableMatrix.setInUnit(f) should throw error");
502 Try.testFail(() -> amPtr.setInUnit(1, 1, 15.2d, AreaUnit.ARE),
503 "ImmutableMatrix.setInUnit(f, u) should throw error");
504 Try.testFail(() -> amPtr.abs(), "ImmutableMatrix.abs() should throw error");
505 Try.testFail(() -> amPtr.ceil(), "ImmutableMatrix.ceil() should throw error");
506 Try.testFail(() -> amPtr.floor(), "ImmutableMatrix.floor() should throw error");
507 Try.testFail(() -> amPtr.neg(), "ImmutableMatrix.neg() should throw error");
508 Try.testFail(() -> amPtr.rint(), "ImmutableMatrix.rint() should throw error");
509 }
510 }
511 }
512
513
514
515
516 @Test
517 public void testMatrixToString()
518 {
519 double[][] denseTestData = DOUBLEMATRIX.denseRectArrays(5, 10);
520 double[][] sparseTestData = DOUBLEMATRIX.sparseRectArrays(5, 10);
521
522 for (StorageType storageType : new StorageType[] {StorageType.DENSE, StorageType.SPARSE})
523 {
524 for (AreaUnit au : new AreaUnit[] {AreaUnit.SQUARE_METER, AreaUnit.ACRE})
525 {
526 double[][] testData = storageType.equals(StorageType.DENSE) ? denseTestData : sparseTestData;
527 AreaMatrix am =
528 DoubleMatrix.instantiate(DoubleMatrixData.instantiate(testData, au.getScale(), storageType), au);
529 String s1 = am.toString();
530 assertTrue(s1.contains(au.getDefaultTextualAbbreviation()));
531 String s2 = am.toString(AreaUnit.SQUARE_INCH);
532 assertTrue(s2.contains(AreaUnit.SQUARE_INCH.getDefaultTextualAbbreviation()));
533 String s3 = am.toString(AreaUnit.SQUARE_INCH, true, true);
534 assertTrue(s3.contains(AreaUnit.SQUARE_INCH.getDefaultTextualAbbreviation()));
535 if (storageType.equals(StorageType.DENSE))
536 {
537 assertTrue(s3.contains("Dense"));
538 assertFalse(s3.contains("Sparse"));
539 }
540 else
541 {
542 assertFalse(s3.contains("Dense"));
543 assertTrue(s3.contains("Sparse"));
544 }
545 assertTrue(s3.contains("Rel"));
546 assertFalse(s3.contains("Abs"));
547 assertTrue(s3.contains("Immutable"));
548 assertFalse(s3.contains("Mutable"));
549 AreaMatrix ammut = am.mutable();
550 String smut = ammut.toString(AreaUnit.SQUARE_INCH, true, true);
551 assertFalse(smut.contains("Immutable"));
552 assertTrue(smut.contains("Mutable"));
553 String sNotVerbose = ammut.toString(false, false);
554 assertFalse(sNotVerbose.contains("Rel"));
555 assertFalse(sNotVerbose.contains("Abs"));
556 assertFalse(sNotVerbose.contains("Immutable"));
557 assertFalse(sNotVerbose.contains("Mutable"));
558 assertFalse(sNotVerbose.contains(au.getDefaultTextualAbbreviation()));
559 }
560 }
561 TimeMatrix tm = DoubleMatrix.instantiate(
562 DoubleMatrixData.instantiate(denseTestData, TimeUnit.DEFAULT.getScale(), StorageType.DENSE), TimeUnit.DEFAULT);
563 String st = tm.toString(TimeUnit.DEFAULT, true, true);
564 assertFalse(st.contains("Rel"));
565 assertTrue(st.contains("Abs"));
566 LengthMatrix lm = DoubleMatrix.instantiate(
567 DoubleMatrixData.instantiate(denseTestData, LengthUnit.SI.getScale(), StorageType.DENSE), LengthUnit.SI);
568 String sl = lm.toString(LengthUnit.SI, true, true);
569 assertTrue(sl.contains("Rel"));
570 assertFalse(sl.contains("Abs"));
571 }
572
573
574
575
576 @Test
577 public void testSpecialMatrixMethodsRelWithAbs()
578 {
579 double[][] denseTestData = DOUBLEMATRIX.denseRectArrays(5, 10);
580 TimeMatrix tm = DoubleMatrix.instantiate(
581 DoubleMatrixData.instantiate(denseTestData, TimeUnit.DEFAULT.getScale(), StorageType.DENSE), TimeUnit.DEFAULT);
582 DurationMatrix dm = DoubleMatrix.instantiate(
583 DoubleMatrixData.instantiate(denseTestData, DurationUnit.MINUTE.getScale(), StorageType.DENSE),
584 DurationUnit.SECOND);
585 assertTrue(tm.isAbsolute());
586 assertFalse(dm.isAbsolute());
587 assertFalse(tm.isRelative());
588 assertTrue(dm.isRelative());
589
590 TimeMatrix absPlusRel = tm.plus(dm);
591 TimeMatrix absMinusRel = tm.minus(dm);
592 double[][] halfDenseData = DOUBLEMATRIX.denseRectArrays(5, 10);
593 for (int row = 0; row < halfDenseData.length; row++)
594 {
595 for (int col = 0; col < halfDenseData[row].length; col++)
596 {
597 halfDenseData[row][col] *= 0.5;
598 }
599 }
600 TimeMatrix halfTimeMatrix = DoubleMatrix.instantiate(
601 DoubleMatrixData.instantiate(halfDenseData, TimeUnit.DEFAULT.getScale(), StorageType.DENSE), TimeUnit.DEFAULT);
602 DurationMatrix absMinusAbs = tm.minus(halfTimeMatrix);
603 TimeMatrix absDecByRelS = tm.mutable().decrementBy(Duration.of(1.0d, "min"));
604 TimeMatrix absDecByRelM = tm.mutable().decrementBy(dm.divide(2.0d));
605 TimeMatrix relPlusAbs = dm.plus(tm);
606 for (int row = 0; row < denseTestData.length; row++)
607 {
608 for (int col = 0; col < denseTestData[0].length; col++)
609 {
610 assertEquals("absPlusRel", 61.0 * denseTestData[row][col], absPlusRel.getSI(row, col), 0.01);
611 assertEquals("absMinusRel", -59.0 * denseTestData[row][col], absMinusRel.getSI(row, col), 0.01);
612 assertEquals("absMinusAbs", denseTestData[row][col] / 2.0, absMinusAbs.getSI(row, col), 0.01);
613 assertEquals("absDecByRelS", denseTestData[row][col] - 60.0, absDecByRelS.getSI(row, col), 0.01);
614 assertEquals("absDecByRelM", -29.0 * denseTestData[row][col], absDecByRelM.getSI(row, col), 0.01);
615 assertEquals("relPlusAbs", 61.0 * denseTestData[row][col], relPlusAbs.getSI(row, col), 0.01);
616 }
617 }
618 for (int dRows : new int[] {-1, 0, 1})
619 {
620 for (int dCols : new int[] {-1, 0, 1})
621 {
622 if (dRows == 0 && dCols == 0)
623 {
624 continue;
625 }
626 double[][] other = DOUBLEMATRIX.denseRectArrays(denseTestData.length + dRows, denseTestData[0].length + dCols);
627 TimeMatrix wrongTimeMatrix = DoubleMatrix.instantiate(
628 DoubleMatrixData.instantiate(other, TimeUnit.DEFAULT.getScale(), StorageType.DENSE), TimeUnit.DEFAULT);
629 try
630 {
631 tm.mutable().minus(wrongTimeMatrix);
632 fail("Mismatching size should have thrown a ValueRuntimeException");
633 }
634 catch (ValueRuntimeException vre)
635 {
636
637 }
638 }
639 }
640 assertTrue("toString returns something informative",
641 DoubleMatrixData.instantiate(denseTestData, TimeUnit.DEFAULT.getScale(), StorageType.DENSE).toString()
642 .startsWith("DoubleMatrixData"));
643 }
644
645
646
647
648
649 @Test
650 public void memoryTest()
651 {
652 FloatAreaMatrix am = FloatMatrix.instantiate(new float[5][10], AreaUnit.SI, StorageType.SPARSE);
653 am = am.mutable();
654 float nonZeroValue = 123.456f;
655
656 for (int compoundIndex = 0; compoundIndex < am.cols() * am.rows(); compoundIndex++)
657 {
658
659 int row = compoundIndex % am.rows();
660 int col = compoundIndex / am.rows();
661 assertEquals("initial value is 0", 0f, am.getSI(row, col), 0.0001);
662 am.setSI(row, col, nonZeroValue);
663 assertEquals("current value is nonZero", nonZeroValue, am.getSI(row, col), 0.0001);
664 }
665 for (int compoundIndex = am.cols() * am.rows(); --compoundIndex >= 0;)
666 {
667
668 int row = compoundIndex % am.rows();
669 int col = compoundIndex / am.rows();
670 assertEquals("current value is nonZero", nonZeroValue, am.getSI(row, col), 0.0001);
671 am.setSI(row, col, 0f);
672 assertEquals("final value is 0", 0f, am.getSI(row, col), 0.0001);
673 }
674 }
675
676
677
678
679 @Test
680 public void testInstantiateAbs()
681 {
682 double[][] denseTestData = DOUBLEMATRIX.denseRectArrays(10, 20);
683 TimeMatrix timeMatrix = DoubleMatrix.instantiate(
684 DoubleMatrixData.instantiate(denseTestData, TimeUnit.DEFAULT.getScale(), StorageType.DENSE), TimeUnit.DEFAULT);
685 DurationMatrix durationMatrix = DoubleMatrix.instantiate(
686 DoubleMatrixData.instantiate(denseTestData, DurationUnit.MINUTE.getScale(), StorageType.DENSE),
687 DurationUnit.SECOND);
688
689 float[] halfDenseData = FLOATVECTOR.denseArray(105);
690 for (int index = 0; index < halfDenseData.length; index++)
691 {
692 halfDenseData[index] *= 0.5;
693 }
694 TimeMatrix relPlusAbsTime = durationMatrix.plus(timeMatrix);
695 for (int row = 0; row < denseTestData.length; row++)
696 {
697 for (int col = 0; col < denseTestData[0].length; col++)
698 {
699 assertEquals("relPlusAbsTime", 61.0 * denseTestData[row][col], relPlusAbsTime.getSI(row, col), 0.01);
700 }
701 }
702 Time time = durationMatrix.instantiateScalarAbsSI(123.456f, TimeUnit.EPOCH_DAY);
703 assertEquals("Unit of instantiateScalarAbsSI matches", TimeUnit.EPOCH_DAY, time.getDisplayUnit());
704 assertEquals("Value of instantiateScalarAbsSI matches", 123.456f, time.si, 0.1);
705
706 AngleMatrix angleMatrix = DoubleMatrix.instantiate(
707 DoubleMatrixData.instantiate(denseTestData, AngleUnit.DEGREE.getScale(), StorageType.DENSE), AngleUnit.DEGREE);
708 DirectionMatrix directionMatrix = DoubleMatrix.instantiate(
709 DoubleMatrixData.instantiate(denseTestData, DirectionUnit.EAST_DEGREE.getScale(), StorageType.DENSE),
710 DirectionUnit.EAST_DEGREE);
711
712 DirectionMatrix relPlusAbsDirection = angleMatrix.plus(directionMatrix);
713 for (int row = 0; row < denseTestData.length; row++)
714 {
715 for (int col = 0; col < denseTestData[0].length; col++)
716 {
717 assertEquals("relPlusAbsTime", 2.0 / 180 * Math.PI * denseTestData[row][col],
718 relPlusAbsDirection.getSI(row, col), 0.01);
719 }
720 }
721 Direction direction = angleMatrix.instantiateScalarAbsSI(123.456f, DirectionUnit.NORTH_RADIAN);
722 assertEquals("Unit of instantiateScalarAbsSI matches", DirectionUnit.NORTH_RADIAN, direction.getDisplayUnit());
723 assertEquals("Value of instantiateScalarAbsSI matches", 123.456f, direction.si, 0.1);
724
725 TemperatureMatrix temperatureMatrix = DoubleMatrix.instantiate(
726 DoubleMatrixData.instantiate(denseTestData, TemperatureUnit.DEGREE_FAHRENHEIT.getScale(), StorageType.DENSE),
727 TemperatureUnit.DEGREE_FAHRENHEIT);
728 AbsoluteTemperatureMatrix absoluteTemperatureMatrix = DoubleMatrix.instantiate(
729 DoubleMatrixData.instantiate(denseTestData, AbsoluteTemperatureUnit.KELVIN.getScale(), StorageType.DENSE),
730 AbsoluteTemperatureUnit.KELVIN);
731
732 AbsoluteTemperatureMatrix relPlusAbsTemperature = temperatureMatrix.plus(absoluteTemperatureMatrix);
733 for (int row = 0; row < denseTestData.length; row++)
734 {
735 for (int col = 0; col < denseTestData[0].length; col++)
736 {
737 assertEquals("relPlusAbsTime", (1.0 + 5.0 / 9.0) * denseTestData[row][col],
738 relPlusAbsTemperature.getSI(row, col), 0.01);
739 }
740 }
741 AbsoluteTemperature absoluteTemperature =
742 temperatureMatrix.instantiateScalarAbsSI(123.456f, AbsoluteTemperatureUnit.DEGREE_FAHRENHEIT);
743 assertEquals("Unit of instantiateScalarAbsSI matches", AbsoluteTemperatureUnit.DEGREE_FAHRENHEIT,
744 absoluteTemperature.getDisplayUnit());
745 assertEquals("Value of instantiateScalarAbsSI matches", 123.456f, absoluteTemperature.si, 0.1);
746
747 LengthMatrix lengthMatrix = DoubleMatrix.instantiate(
748 DoubleMatrixData.instantiate(denseTestData, LengthUnit.MILE.getScale(), StorageType.DENSE), LengthUnit.MILE);
749 PositionMatrix positionMatrix = DoubleMatrix.instantiate(
750 DoubleMatrixData.instantiate(denseTestData, PositionUnit.KILOMETER.getScale(), StorageType.DENSE),
751 PositionUnit.KILOMETER);
752
753 PositionMatrix relPlusAbsPosition = lengthMatrix.plus(positionMatrix);
754 for (int row = 0; row < denseTestData.length; row++)
755 {
756 for (int col = 0; col < denseTestData[0].length; col++)
757 {
758 assertEquals("relPlusAbsTime", 2609.344 * denseTestData[row][col], relPlusAbsPosition.getSI(row, col), 0.1);
759 }
760 }
761 Position position = lengthMatrix.instantiateScalarAbsSI(123.456f, PositionUnit.ANGSTROM);
762 assertEquals("Unit of instantiateScalarAbsSI matches", PositionUnit.ANGSTROM, position.getDisplayUnit());
763 assertEquals("Value of instantiateScalarAbsSI matches", 123.456f, position.si, 0.01);
764 }
765
766
767
768
769
770
771
772
773
774
775
776
777 @SuppressWarnings("unchecked")
778 @Test
779 public <U extends Unit<U>> void testAsUnit() throws ClassNotFoundException, NoSuchMethodException, SecurityException,
780 IllegalAccessException, IllegalArgumentException, InvocationTargetException, UnitException
781 {
782 double[][] testValues = DOUBLEMATRIX.denseRectArrays(10, 20);
783 for (StorageType storageType : new StorageType[] {StorageType.DENSE, StorageType.SPARSE})
784 {
785 for (String type : CLASSNAMES.REL_LIST)
786 {
787 Class.forName("org.djunits.unit." + type + "Unit");
788 Quantity<U> quantity = (Quantity<U>) Quantities.INSTANCE.getQuantity(type + "Unit");
789 for (U unit : quantity.getUnitsById().values())
790 {
791 for (StorageType storageType2 : new StorageType[] {StorageType.DENSE, storageType})
792 {
793 SIUnit siUnit = SIUnit.of(unit.getQuantity().getSiDimensions());
794 SIMatrix matrix = SIMatrix.instantiate(testValues, siUnit, storageType2);
795 Method asMethod = SIMatrix.class.getDeclaredMethod("as", Unit.class);
796 AbstractDoubleMatrixRel<U, ?, ?, ?> asMatrix =
797 (AbstractDoubleMatrixRel<U, ?, ?, ?>) asMethod.invoke(matrix, siUnit);
798 assertEquals(matrix.getDisplayUnit().getStandardUnit(), asMatrix.getDisplayUnit());
799 siUnit = SIUnit.of(AbsoluteTemperatureUnit.KELVIN.getQuantity().getSiDimensions());
800 for (int row = 0; row < testValues.length; row++)
801 {
802 for (int col = 0; col < testValues[0].length; col++)
803 {
804 assertEquals("Values should match", testValues[row][col], matrix.getInUnit(row, col), 0.001);
805 }
806 }
807 try
808 {
809 asMethod.invoke(matrix, siUnit);
810 fail("as method should not be able to cast to unrelated (absoluteTemperature) unit");
811 }
812 catch (InvocationTargetException ite)
813 {
814 Throwable cause = ite.getCause();
815 assertEquals("cause is UnitRuntimeException", UnitRuntimeException.class, cause.getClass());
816
817 }
818 }
819 }
820 }
821 }
822 }
823
824
825
826
827 @SuppressWarnings("unlikely-arg-type")
828 @Test
829 public void testEquals()
830 {
831 double[][] testData = DOUBLEMATRIX.denseRectArrays(12, 34);
832 testData[2][2] = 0;
833 for (StorageType storageType : new StorageType[] {StorageType.DENSE, StorageType.SPARSE})
834 {
835 DoubleMatrixData dmd = DoubleMatrixData.instantiate(testData, TemperatureUnit.KELVIN.getScale(), storageType);
836 assertTrue("Double matrix is equal to itself", dmd.equals(dmd));
837 assertFalse("Double matrix is not equal to null", dmd.equals(null));
838 assertFalse("Double matrix data is not equal to some string", dmd.equals("some string"));
839 assertTrue("Double matrix is equal to sparse version of itself", dmd.equals(dmd.toSparse()));
840 assertTrue("Double matrix is equal to dense version of itself", dmd.equals(dmd.toDense()));
841 for (StorageType storageType2 : new StorageType[] {StorageType.DENSE, StorageType.SPARSE})
842 {
843 DoubleMatrixData dvd2 = DoubleMatrixData.instantiate(testData, TemperatureUnit.KELVIN.getScale(), storageType2);
844 assertEquals(
845 "Double matrix data is equal to other double vector containing same values regardless of storage type",
846 dmd, dvd2);
847 double[][] testData2 = DOUBLEMATRIX.denseRectArrays(12, 33);
848 testData2[2][2] = 0;
849 dvd2 = DoubleMatrixData.instantiate(testData2, TemperatureUnit.KELVIN.getScale(), storageType2);
850 assertFalse("Double matrix data is not equal to other double vector containing same values except last one",
851 dmd.equals(dvd2));
852 testData2 = DOUBLEMATRIX.denseRectArrays(13, 34);
853 testData2[2][2] = 0;
854 dvd2 = DoubleMatrixData.instantiate(testData2, TemperatureUnit.KELVIN.getScale(), storageType2);
855 assertFalse("Double matrix data is not equal to other double vector containing same values except last one",
856 dmd.equals(dvd2));
857 testData2 = DOUBLEMATRIX.denseRectArrays(12, 34);
858 dvd2 = DoubleMatrixData.instantiate(testData2, TemperatureUnit.KELVIN.getScale(), storageType2);
859 assertFalse("Double matrix data is not equal to other double vector containing same values except for one zero",
860 dmd.equals(dvd2));
861 }
862 }
863 }
864
865
866
867
868 @SuppressWarnings({"rawtypes", "unchecked"})
869 @Test
870 public void sparseValueTest()
871 {
872 try
873 {
874 new DoubleSparseValue(-1, 0, 123.456);
875 fail("Negative row should have caused a ValueRuntimeException");
876 }
877 catch (ValueRuntimeException vre)
878 {
879
880 }
881
882 try
883 {
884 new DoubleSparseValue(0, -1, 123.456);
885 fail("Negative column should have caused a ValueRuntimeException");
886 }
887 catch (ValueRuntimeException vre)
888 {
889
890 }
891
892 Length length = Length.valueOf("123 km");
893 DoubleSparseValue dsv = new DoubleSparseValue(2, 3, length);
894 assertEquals("row matches", 2, dsv.getRow());
895 assertEquals("column matches", 3, dsv.getColumn());
896 assertEquals("value matches", 123000, dsv.getValueSI(), 0.1);
897 dsv = new DoubleSparseValue(2, 3, 123.000, LengthUnit.KILOMETER);
898 assertEquals("row matches", 2, dsv.getRow());
899 assertEquals("column matches", 3, dsv.getColumn());
900 assertEquals("value matches", 123000, dsv.getValueSI(), 0.1);
901 }
902
903 }