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