1 package org.djunits.value.vfloat.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.matrix.AreaMatrix;
23 import org.djunits.value.vdouble.matrix.Determinant;
24 import org.djunits.value.vfloat.function.FloatMathFunctions;
25 import org.djunits.value.vfloat.matrix.base.FloatSparseValue;
26 import org.djunits.value.vfloat.matrix.data.FloatMatrixData;
27 import org.djunits.value.vfloat.scalar.FloatAbsoluteTemperature;
28 import org.djunits.value.vfloat.scalar.FloatArea;
29 import org.djunits.value.vfloat.scalar.FloatDirection;
30 import org.djunits.value.vfloat.scalar.FloatDuration;
31 import org.djunits.value.vfloat.scalar.FloatLength;
32 import org.djunits.value.vfloat.scalar.FloatPosition;
33 import org.djunits.value.vfloat.scalar.FloatTime;
34 import org.djunits.value.vfloat.vector.FLOATVECTOR;
35 import org.djunits.value.vfloat.vector.FloatAreaVector;
36 import org.djutils.test.UnitTest;
37 import org.junit.jupiter.api.Test;
38
39
40
41
42 public class FloatMatrixMethodTest
43 {
44
45
46
47
48
49
50 @Test
51 public void testMatrixMethods() throws ValueRuntimeException, UnitException
52 {
53 float[][] denseTestData = FLOATMATRIX.denseRectArrays(10, 20, false);
54 float[][] sparseTestData = FLOATMATRIX.sparseRectArrays(10, 20, false);
55 float[][] reverseSparseTestData = new float[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.456f + row + 100 * col;
67 reverseSparseTestData[row][col] = 20000.567f + 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 float[][] testData = storageType.equals(StorageType.DENSE) ? denseTestData : sparseTestData;
76 FloatAreaMatrix am = new FloatAreaMatrix(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 FloatLengthMatrix(testData, LengthUnit.METER, storageType));
150 assertNotEquals(am, am.divide(2.0f));
151
152
153 assertFalse(am.isMutable());
154 FloatAreaMatrix ammut = am.mutable();
155 assertTrue(ammut.isMutable());
156 assertFalse(am.isMutable());
157 FloatAreaMatrix 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 FloatAreaMatrix 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(Float.isNaN(ammut3.getSI(row, col)), "Value should be NaN");
173
174 }
175 else
176 {
177 assertTrue(Float.isInfinite(ammut3.getSI(row, col)), "Value should be Infinite");
178 }
179 }
180 }
181
182
183 FloatArea zSum = am.zSum();
184 float 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.0f ? 0 : 1;
192 }
193 }
194 assertEquals(sum, zSum.getInUnit(), 5f, "zSum");
195 assertEquals(card, am.cardinality(), "cardinality");
196 FloatAreaMatrix ammutZero = ammut.multiplyBy(0.0f);
197 assertEquals(0, ammutZero.cardinality(), "cardinality should be 0");
198 assertEquals(0.0, ammutZero.zSum().getSI(), 0, "zSum should be 0");
199
200
201 FloatAreaMatrix amold = am.clone();
202 FloatArea fa = FloatArea.of(10.0f, "m^2");
203 FloatAreaMatrix aminc = am.mutable().incrementBy(fa).immutable();
204 FloatAreaMatrix amdec = am.mutable().decrementBy(fa).immutable();
205 FloatAreaMatrix 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), 5f,
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), 6f,
214 "m + s = (m+s)");
215 assertEquals(au.getScale().toStandardUnit(testData[row][col]) - 10.0, amdec.getSI(row, col), 6f,
216 "m - s = (m-s)");
217 }
218 }
219
220
221 FloatAreaMatrix amt5 = am.mutable().multiplyBy(5.0f).immutable();
222 FloatAreaMatrix amd5 = am.mutable().divideBy(5.0f).immutable();
223 FloatAreaMatrix amtd = amt5.mutable().divideBy(5.0f);
224 FloatAreaMatrix amtimD = am.times(5.0d);
225 FloatAreaMatrix amtimF = am.times(5.0f);
226 FloatAreaMatrix amdivD = am.divide(5.0d);
227 FloatAreaMatrix 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.5,
233 "times followed by divide with constant should result in same matrix");
234 assertEquals(au.getScale().toStandardUnit(testData[row][col]) * 5.0f, amt5.getSI(row, col), 50f,
235 "m * 5.0 = (m*5.0)");
236 assertEquals(au.getScale().toStandardUnit(testData[row][col]) / 5.0f, amd5.getSI(row, col), 2f,
237 "m / 5.0 = (m/5.0)");
238 assertEquals(amt5.getSI(row, col), amtimD.getSI(row, col), 0.1f, "amtimD");
239 assertEquals(amt5.getSI(row, col), amtimF.getSI(row, col), 0.1f, "amtimF");
240 assertEquals(amd5.getSI(row, col), amdivD.getSI(row, col), 0.01f, "amdivD");
241 assertEquals(amd5.getSI(row, col), amdivF.getSI(row, col), 0.01f, "amdivD");
242 }
243 }
244
245
246 assertEquals(new FloatArea(testData[2][2], au), am.get(2, 2), "get()");
247 assertEquals(au.getScale().toStandardUnit(testData[2][2]), am.getSI(2, 2), 1f, "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), 10f, "getInUnit(unit)");
251
252
253 FloatArea fasqft = new FloatArea(10.5f, AreaUnit.SQUARE_FOOT);
254 FloatAreaMatrix famChange = am.clone().mutable();
255 famChange.set(2, 2, fasqft);
256 assertEquals(fasqft.si, famChange.get(2, 2).si, 0.1f, "set()");
257 famChange = am.clone().mutable();
258 famChange.setSI(2, 2, 123.4f);
259 assertEquals(123.4f, famChange.get(2, 2).si, 0.1f, "setSI()");
260 famChange = am.clone().mutable();
261 famChange.setInUnit(2, 2, 1.2f);
262 assertEquals(1.2f, famChange.getInUnit(2, 2), 0.1f, "setInUnit()");
263 famChange = am.clone().mutable();
264 famChange.setInUnit(2, 2, 1.5f, AreaUnit.HECTARE);
265 assertEquals(15000.0f, famChange.get(2, 2).si, 1.0f, "setInUnit(unit)");
266
267
268 float[][] squareData = storageType.equals(StorageType.DENSE) ? FLOATMATRIX.denseRectArrays(12, 12, false)
269 : FLOATMATRIX.sparseRectArrays(12, 12, false);
270 FloatAreaMatrix amSquare = new FloatAreaMatrix(squareData, au, storageType);
271 float[] row2si = am.getRowSI(2);
272 float[] col2si = am.getColumnSI(2);
273 float[] diagsi = amSquare.getDiagonalSI();
274 FloatAreaVector row2v = am.getRow(2);
275 FloatAreaVector col2v = am.getColumn(2);
276 FloatAreaVector diagv = amSquare.getDiagonal();
277 FloatArea[] row2scalar = am.getRowScalars(2);
278 FloatArea[] col2scalar = am.getColumnScalars(2);
279 FloatArea[] diagscalar = amSquare.getDiagonalScalars();
280 for (int col = 0; col < testData[0].length; col++)
281 {
282 assertEquals(au.getScale().toStandardUnit(testData[2][col]), row2si[col], 10f, "row2si");
283 assertEquals(au.getScale().toStandardUnit(testData[2][col]), row2v.getSI(col), 10f, "row2v");
284 assertEquals(au.getScale().toStandardUnit(testData[2][col]), row2scalar[col].si, 10f, "row2scalar");
285 }
286 for (int row = 0; row < testData.length; row++)
287 {
288 assertEquals(au.getScale().toStandardUnit(testData[row][2]), col2si[row], 10f, "col2si");
289 assertEquals(au.getScale().toStandardUnit(testData[row][2]), col2v.getSI(row), 10f, "col2v");
290 assertEquals(au.getScale().toStandardUnit(testData[row][2]), col2scalar[row].si, 10f, "col2scalar");
291 }
292 for (int diag = 0; diag < amSquare.rows(); diag++)
293 {
294 assertEquals(au.getScale().toStandardUnit(squareData[diag][diag]), diagsi[diag], 0.1f, "diag2si");
295 assertEquals(au.getScale().toStandardUnit(squareData[diag][diag]), diagv.getSI(diag), 0.1f, "diag2v");
296 assertEquals(au.getScale().toStandardUnit(squareData[diag][diag]), diagscalar[diag].si, 0.1f,
297 "diag2scalar");
298 }
299
300
301 float[][] valsi = am.getValuesSI();
302 float[][] valunit = am.getValuesInUnit();
303 float[][] valsqft = am.getValuesInUnit(AreaUnit.SQUARE_YARD);
304 FloatArea[][] 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], 5f, "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], 10f, "getValuesInUnit(unit)");
315 assertEquals(au.getScale().toStandardUnit(testData[row][col]), valscalars[row][col].si, 5f,
316 "getValuesInUnit(unit)");
317 }
318 }
319
320
321 FloatAreaMatrix amdiv2 = am.divide(2.0f);
322 assertEquals(am.getStorageType(), amdiv2.getStorageType());
323 assertEquals(am.getDisplayUnit(), amdiv2.getDisplayUnit());
324 FloatAreaMatrix amAbs = amdiv2.mutable().abs().immutable();
325 assertEquals(am.getStorageType(), amAbs.getStorageType());
326 assertEquals(am.getDisplayUnit(), amAbs.getDisplayUnit());
327 FloatAreaMatrix amCeil = amdiv2.mutable().ceil().immutable();
328 assertEquals(am.getStorageType(), amCeil.getStorageType());
329 assertEquals(am.getDisplayUnit(), amCeil.getDisplayUnit());
330 FloatAreaMatrix amFloor = amdiv2.mutable().floor().immutable();
331 assertEquals(am.getStorageType(), amFloor.getStorageType());
332 assertEquals(am.getDisplayUnit(), amFloor.getDisplayUnit());
333 FloatAreaMatrix amNeg = amdiv2.mutable().neg().immutable();
334 assertEquals(am.getStorageType(), amNeg.getStorageType());
335 assertEquals(am.getDisplayUnit(), amNeg.getDisplayUnit());
336 FloatAreaMatrix 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.0f, amdiv2.getSI(row, col), 5f,
345 "div2");
346 assertEquals((float) Math.abs(au.getScale().toStandardUnit(testData[row][col]) / 2.0f),
347 amAbs.getSI(row, col), 0.1f, "abs");
348 assertEquals((float) Math.ceil(au.getScale().toStandardUnit(testData[row][col]) / 2.0f),
349 amCeil.getSI(row, col), 5f, "ceil");
350 assertEquals((float) Math.floor(au.getScale().toStandardUnit(testData[row][col]) / 2.0f),
351 amFloor.getSI(row, col), 5f, "floor");
352 assertEquals(-au.getScale().toStandardUnit(testData[row][col]) / 2.0f, amNeg.getSI(row, col), 5f,
353 "neg");
354 assertEquals((float) Math.rint(au.getScale().toStandardUnit(testData[row][col]) / 2.0f),
355 amRint.getSI(row, col), 5f, "rint");
356 }
357 }
358
359 float[][] testData4x4 = new float[][] {{2, 3, 5, 7}, {11, 13, 17, 19}, {23, 29, 31, 37}, {41, 43, 47, 49}};
360 FloatAreaMatrix am4x4 = new FloatAreaMatrix(testData4x4, au, storageType);
361 float det = am4x4.determinantSI();
362 float detCalc = Determinant.det(am4x4.getValuesSI());
363 float err = Math.max(det, detCalc) / 1000.0f;
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 float[][] testData2 = storageType2.equals(StorageType.DENSE) ? denseTestData : reverseSparseTestData;
373 for (AreaUnit au2 : new AreaUnit[] {AreaUnit.SQUARE_METER, AreaUnit.ACRE})
374 {
375
376
377 FloatAreaMatrix am2 = new FloatAreaMatrix(testData2, au2, storageType2);
378 FloatAreaMatrix amSum1 = am.plus(am2);
379 FloatAreaMatrix amSum2 = am2.plus(am);
380 FloatAreaMatrix amSum3 = am.mutable().incrementBy(am2).immutable();
381 FloatAreaMatrix 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 float tolerance = Float.isFinite(amSum1.getSI(row, col))
390 ? Math.abs(amSum1.getSI(row, col) / 10000.0f) : 0.1f;
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 FloatAreaMatrix amDiff1 = am.minus(am2);
400 FloatAreaMatrix amDiff2 = am2.minus(am).mutable().neg();
401 FloatAreaMatrix 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 float tolerance = Float.isFinite(amDiff1.getSI(row, col))
409 ? Math.abs(amDiff1.getSI(row, col) / 10000.0f) : 0.1f;
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 FloatSIMatrix amTim = am.times(am2);
419 FloatSIMatrix 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 float tolerance = Float.isFinite(amTim.getSI(row, col))
429 ? Math.abs(amTim.getSI(row, col) / 10000.0f) : 0.1f;
430 assertEquals(
431 au.getScale().toStandardUnit(testData[row][col])
432 * au2.getScale().toStandardUnit(testData2[row][col]),
433 amTim.getSI(row, col), tolerance, "value in m2 * m2 matches");
434 tolerance = Float.isFinite(amDiv.getSI(row, col)) ? Math.abs(amDiv.getSI(row, col) / 10000.0f)
435 : 0.1f;
436 assertEquals(
437 au.getScale().toStandardUnit(testData[row][col])
438 / au2.getScale().toStandardUnit(testData2[row][col]),
439 amDiv.getSI(row, col), tolerance, "value in m2 / m2 matches (could be NaN)");
440 }
441 }
442 }
443 }
444 }
445 }
446 }
447
448
449
450
451 @Test
452 public final void testSetDisplayUnit()
453 {
454 FloatSpeedMatrix s = new FloatSpeedMatrix(new float[][] {{10.0f, 20.0f}, {30.0f, 40.0f}}, SpeedUnit.KM_PER_HOUR);
455 FloatSpeedMatrix t = s.setDisplayUnit(SpeedUnit.MILE_PER_HOUR);
456 assertTrue(s == t);
457 FloatSpeedMatrix u =
458 new FloatSpeedMatrix(new float[][] {{10.0f, 20.0f}, {30.0f, 40.0f}}).setDisplayUnit(SpeedUnit.KM_PER_HOUR);
459 assertEquals(SpeedUnit.KM_PER_HOUR, u.getDisplayUnit());
460 assertEquals(10.0f, u.getSI(0, 0));
461 }
462
463
464
465
466 @Test
467 public void testImmutableMatrix()
468 {
469 float[][] denseTestData = FLOATMATRIX.denseRectArrays(5, 10, false);
470 float[][] sparseTestData = FLOATMATRIX.sparseRectArrays(5, 10, false);
471
472 for (StorageType storageType : new StorageType[] {StorageType.DENSE, StorageType.SPARSE})
473 {
474 for (AreaUnit au : new AreaUnit[] {AreaUnit.SQUARE_METER, AreaUnit.ACRE})
475 {
476 float[][] testData = storageType.equals(StorageType.DENSE) ? denseTestData : sparseTestData;
477 FloatAreaMatrix am = new FloatAreaMatrix(testData, au, storageType);
478 am = am.immutable();
479 final FloatAreaMatrix amPtr = am;
480 FloatArea fa = FloatArea.of(10.0f, "m^2");
481 UnitTest.testFail(() -> amPtr.assign(FloatMathFunctions.ABS), "ImmutableMatrix.assign(...) should throw error");
482 UnitTest.testFail(() -> amPtr.decrementBy(fa), "ImmutableMatrix.decrementBy(scalar) should throw error");
483 UnitTest.testFail(() -> amPtr.decrementBy(amPtr), "ImmutableMatrix.decrementBy(matrix) should throw error");
484 UnitTest.testFail(() -> amPtr.incrementBy(fa), "ImmutableMatrix.incrementBy(scalar) should throw error");
485 UnitTest.testFail(() -> amPtr.incrementBy(amPtr), "ImmutableMatrix.incrementBy(matrix) should throw error");
486 UnitTest.testFail(() -> amPtr.divideBy(2.0f), "ImmutableMatrix.divideBy(factor) should throw error");
487 UnitTest.testFail(() -> amPtr.multiplyBy(2.0f), "ImmutableMatrix.multiplyBy(factor) should throw error");
488 UnitTest.testFail(() -> amPtr.set(1, 1, fa), "ImmutableMatrix.set() should throw error");
489 UnitTest.testFail(() -> amPtr.setSI(1, 1, 20.1f), "ImmutableMatrix.setSI() should throw error");
490 UnitTest.testFail(() -> amPtr.setInUnit(1, 1, 15.2f), "ImmutableMatrix.setInUnit(f) should throw error");
491 UnitTest.testFail(() -> amPtr.setInUnit(1, 1, 15.2f, AreaUnit.ARE),
492 "ImmutableMatrix.setInUnit(f, u) should throw error");
493 UnitTest.testFail(() -> amPtr.abs(), "ImmutableMatrix.abs() should throw error");
494 UnitTest.testFail(() -> amPtr.ceil(), "ImmutableMatrix.ceil() should throw error");
495 UnitTest.testFail(() -> amPtr.floor(), "ImmutableMatrix.floor() should throw error");
496 UnitTest.testFail(() -> amPtr.neg(), "ImmutableMatrix.neg() should throw error");
497 UnitTest.testFail(() -> amPtr.rint(), "ImmutableMatrix.rint() should throw error");
498 }
499 }
500 }
501
502
503
504
505 @Test
506 public void testMatrixToString()
507 {
508 float[][] denseTestData = FLOATMATRIX.denseRectArrays(5, 10, false);
509 float[][] sparseTestData = FLOATMATRIX.sparseRectArrays(5, 10, false);
510
511 for (StorageType storageType : new StorageType[] {StorageType.DENSE, StorageType.SPARSE})
512 {
513 for (AreaUnit au : new AreaUnit[] {AreaUnit.SQUARE_METER, AreaUnit.ACRE})
514 {
515 float[][] testData = storageType.equals(StorageType.DENSE) ? denseTestData : sparseTestData;
516 FloatAreaMatrix am = new FloatAreaMatrix(testData, au, storageType);
517 String s1 = am.toString();
518 assertTrue(s1.contains(au.getDefaultTextualAbbreviation()));
519 String s2 = am.toString(AreaUnit.SQUARE_INCH);
520 assertTrue(s2.contains(AreaUnit.SQUARE_INCH.getDefaultTextualAbbreviation()));
521 String s3 = am.toString(AreaUnit.SQUARE_INCH, true, true);
522 assertTrue(s3.contains(AreaUnit.SQUARE_INCH.getDefaultTextualAbbreviation()));
523 if (storageType.equals(StorageType.DENSE))
524 {
525 assertTrue(s3.contains("Dense"));
526 assertFalse(s3.contains("Sparse"));
527 }
528 else
529 {
530 assertFalse(s3.contains("Dense"));
531 assertTrue(s3.contains("Sparse"));
532 }
533 assertTrue(s3.contains("Rel"));
534 assertFalse(s3.contains("Abs"));
535 assertTrue(s3.contains("Immutable"));
536 assertFalse(s3.contains("Mutable"));
537 FloatAreaMatrix ammut = am.mutable();
538 String smut = ammut.toString(AreaUnit.SQUARE_INCH, true, true);
539 assertFalse(smut.contains("Immutable"));
540 assertTrue(smut.contains("Mutable"));
541 String sNotVerbose = ammut.toString(false, false);
542 assertFalse(sNotVerbose.contains("Rel"));
543 assertFalse(sNotVerbose.contains("Abs"));
544 assertFalse(sNotVerbose.contains("Immutable"));
545 assertFalse(sNotVerbose.contains("Mutable"));
546 assertFalse(sNotVerbose.contains(au.getDefaultTextualAbbreviation()));
547 }
548 }
549 FloatTimeMatrix tm = new FloatTimeMatrix(denseTestData, TimeUnit.DEFAULT, StorageType.DENSE);
550 String st = tm.toString(TimeUnit.DEFAULT, true, true);
551 assertFalse(st.contains("Rel"));
552 assertTrue(st.contains("Abs"));
553 FloatLengthMatrix lm = new FloatLengthMatrix(denseTestData, LengthUnit.SI, StorageType.DENSE);
554 String sl = lm.toString(LengthUnit.SI, true, true);
555 assertTrue(sl.contains("Rel"));
556 assertFalse(sl.contains("Abs"));
557 }
558
559
560
561
562 @Test
563 public void testSpecialMatrixMethodsRelWithAbs()
564 {
565 float[][] denseTestData = FLOATMATRIX.denseRectArrays(5, 10, false);
566 FloatTimeMatrix tm = new FloatTimeMatrix(denseTestData, TimeUnit.DEFAULT, StorageType.DENSE);
567 FloatDurationMatrix dm = new FloatDurationMatrix(denseTestData, DurationUnit.MINUTE, StorageType.DENSE);
568 assertTrue(tm.isAbsolute());
569 assertFalse(dm.isAbsolute());
570 assertFalse(tm.isRelative());
571 assertTrue(dm.isRelative());
572
573 FloatTimeMatrix absPlusRel = tm.plus(dm);
574 FloatTimeMatrix absMinusRel = tm.minus(dm);
575 float[][] halfDenseData = FLOATMATRIX.denseRectArrays(5, 10, false);
576 for (int row = 0; row < halfDenseData.length; row++)
577 {
578 for (int col = 0; col < halfDenseData[row].length; col++)
579 {
580 halfDenseData[row][col] *= 0.5;
581 }
582 }
583 FloatTimeMatrix halfTimeMatrix = new FloatTimeMatrix(halfDenseData, TimeUnit.DEFAULT, StorageType.DENSE);
584 FloatDurationMatrix absMinusAbs = tm.minus(halfTimeMatrix);
585 FloatTimeMatrix absDecByRelS = tm.mutable().decrementBy(FloatDuration.of(1.0f, "min"));
586 FloatTimeMatrix absDecByRelM = tm.mutable().decrementBy(dm.divide(2.0f));
587 FloatTimeMatrix relPlusAbs = dm.plus(tm);
588 for (int row = 0; row < denseTestData.length; row++)
589 {
590 for (int col = 0; col < denseTestData[0].length; col++)
591 {
592 assertEquals(61.0 * denseTestData[row][col], absPlusRel.getSI(row, col), 0.01, "absPlusRel");
593 assertEquals(-59.0 * denseTestData[row][col], absMinusRel.getSI(row, col), 0.01, "absMinusRel");
594 assertEquals(denseTestData[row][col] / 2.0, absMinusAbs.getSI(row, col), 0.01, "absMinusAbs");
595 assertEquals(denseTestData[row][col] - 60.0, absDecByRelS.getSI(row, col), 0.01, "absDecByRelS");
596 assertEquals(-29.0 * denseTestData[row][col], absDecByRelM.getSI(row, col), 0.01, "absDecByRelM");
597 assertEquals(61.0 * denseTestData[row][col], relPlusAbs.getSI(row, col), 0.01, "relPlusAbs");
598 }
599 }
600 for (int dRows : new int[] {-1, 0, 1})
601 {
602 for (int dCols : new int[] {-1, 0, 1})
603 {
604 if (dRows == 0 && dCols == 0)
605 {
606 continue;
607 }
608 float[][] other =
609 FLOATMATRIX.denseRectArrays(denseTestData.length + dRows, denseTestData[0].length + dCols, false);
610 FloatTimeMatrix wrongTimeMatrix = new FloatTimeMatrix(other, TimeUnit.DEFAULT, StorageType.DENSE);
611 try
612 {
613 tm.mutable().minus(wrongTimeMatrix);
614 fail("Mismatching size should have thrown a ValueRuntimeException");
615 }
616 catch (ValueRuntimeException vre)
617 {
618
619 }
620 }
621 }
622 assertTrue(FloatMatrixData.instantiate(denseTestData, TimeUnit.DEFAULT.getScale(), StorageType.DENSE).toString()
623 .startsWith("FloatMatrixData"), "toString returns something informative");
624 }
625
626
627
628
629
630 @Test
631 public void memoryTest()
632 {
633 AreaMatrix am = new AreaMatrix(new double[5][10], AreaUnit.SI, StorageType.SPARSE);
634 am = am.mutable();
635 double nonZeroValue = 123.456;
636
637 for (int compoundIndex = 0; compoundIndex < am.cols() * am.rows(); compoundIndex++)
638 {
639
640 int row = compoundIndex % am.rows();
641 int col = compoundIndex / am.rows();
642 assertEquals(0d, am.getSI(row, col), 0.0001, "initial value is 0");
643 am.setSI(row, col, nonZeroValue);
644 assertEquals(nonZeroValue, am.getSI(row, col), 0.0001, "current value is nonZero");
645 }
646 for (int compoundIndex = am.cols() * am.rows(); --compoundIndex >= 0;)
647 {
648
649 int row = compoundIndex % am.rows();
650 int col = compoundIndex / am.rows();
651 assertEquals(nonZeroValue, am.getSI(row, col), 0.0001, "current value is nonZero");
652 am.setSI(row, col, 0d);
653 assertEquals(0d, am.getSI(row, col), 0.0001, "final value is 0");
654 }
655 }
656
657
658
659
660 @Test
661 public void testInstantiateAbs()
662 {
663 float[][] denseTestData = FLOATMATRIX.denseRectArrays(10, 20, false);
664 FloatTimeMatrix timeMatrix = new FloatTimeMatrix(denseTestData, TimeUnit.DEFAULT, StorageType.DENSE);
665 FloatDurationMatrix durationMatrix = new FloatDurationMatrix(denseTestData, DurationUnit.MINUTE, StorageType.DENSE);
666
667 float[] halfDenseData = FLOATVECTOR.denseArray(105);
668 for (int index = 0; index < halfDenseData.length; index++)
669 {
670 halfDenseData[index] *= 0.5;
671 }
672 FloatTimeMatrix relPlusAbsTime = durationMatrix.plus(timeMatrix);
673 for (int row = 0; row < denseTestData.length; row++)
674 {
675 for (int col = 0; col < denseTestData[0].length; col++)
676 {
677 assertEquals(61.0 * denseTestData[row][col], relPlusAbsTime.getSI(row, col), 0.01, "relPlusAbsTime");
678 }
679 }
680 FloatTime floatTime = durationMatrix.instantiateScalarAbsSI(123.456f, TimeUnit.EPOCH_DAY);
681 assertEquals(TimeUnit.EPOCH_DAY, floatTime.getDisplayUnit(), "Unit of instantiateScalarAbsSI matches");
682 assertEquals(123.456f, floatTime.si, 0.1, "Value of instantiateScalarAbsSI matches");
683
684 FloatAngleMatrix angleMatrix = new FloatAngleMatrix(denseTestData, AngleUnit.DEGREE, StorageType.DENSE);
685 FloatDirectionMatrix directionMatrix =
686 new FloatDirectionMatrix(denseTestData, DirectionUnit.EAST_DEGREE, StorageType.DENSE);
687
688 FloatDirectionMatrix relPlusAbsDirection = angleMatrix.plus(directionMatrix);
689 for (int row = 0; row < denseTestData.length; row++)
690 {
691 for (int col = 0; col < denseTestData[0].length; col++)
692 {
693 assertEquals(2.0 / 180 * Math.PI * denseTestData[row][col], relPlusAbsDirection.getSI(row, col), 0.01,
694 "relPlusAbsTime");
695 }
696 }
697 FloatDirection floatDirection = angleMatrix.instantiateScalarAbsSI(123.456f, DirectionUnit.NORTH_RADIAN);
698 assertEquals(DirectionUnit.NORTH_RADIAN, floatDirection.getDisplayUnit(), "Unit of instantiateScalarAbsSI matches");
699 assertEquals(123.456f, floatDirection.si, 0.1, "Value of instantiateScalarAbsSI matches");
700
701 FloatTemperatureMatrix temperatureMatrix =
702 new FloatTemperatureMatrix(denseTestData, TemperatureUnit.DEGREE_FAHRENHEIT, StorageType.DENSE);
703 FloatAbsoluteTemperatureMatrix absoluteTemperatureMatrix =
704 new FloatAbsoluteTemperatureMatrix(denseTestData, AbsoluteTemperatureUnit.KELVIN, StorageType.DENSE);
705
706 FloatAbsoluteTemperatureMatrix relPlusAbsTemperature = temperatureMatrix.plus(absoluteTemperatureMatrix);
707 for (int row = 0; row < denseTestData.length; row++)
708 {
709 for (int col = 0; col < denseTestData[0].length; col++)
710 {
711 assertEquals((1.0 + 5.0 / 9.0) * denseTestData[row][col], relPlusAbsTemperature.getSI(row, col), 0.01,
712 "relPlusAbsTime");
713 }
714 }
715 FloatAbsoluteTemperature floatAbsoluteTemperature =
716 temperatureMatrix.instantiateScalarAbsSI(123.456f, AbsoluteTemperatureUnit.DEGREE_FAHRENHEIT);
717 assertEquals(AbsoluteTemperatureUnit.DEGREE_FAHRENHEIT, floatAbsoluteTemperature.getDisplayUnit(),
718 "Unit of instantiateScalarAbsSI matches");
719 assertEquals(123.456f, floatAbsoluteTemperature.si, 0.1, "Value of instantiateScalarAbsSI matches");
720
721 FloatLengthMatrix lengthMatrix = new FloatLengthMatrix(denseTestData, LengthUnit.MILE, StorageType.DENSE);
722 FloatPositionMatrix positionMatrix = new FloatPositionMatrix(denseTestData, PositionUnit.KILOMETER, StorageType.DENSE);
723
724 FloatPositionMatrix relPlusAbsPosition = lengthMatrix.plus(positionMatrix);
725 for (int row = 0; row < denseTestData.length; row++)
726 {
727 for (int col = 0; col < denseTestData[0].length; col++)
728 {
729 assertEquals(2609.344 * denseTestData[row][col], relPlusAbsPosition.getSI(row, col), 0.1, "relPlusAbsTime");
730 }
731 }
732 FloatPosition floatPosition = lengthMatrix.instantiateScalarAbsSI(123.456f, PositionUnit.ANGSTROM);
733 assertEquals(PositionUnit.ANGSTROM, floatPosition.getDisplayUnit(), "Unit of instantiateScalarAbsSI matches");
734 assertEquals(123.456f, floatPosition.si, 0.1, "Value of instantiateScalarAbsSI matches");
735 }
736
737
738
739
740 @SuppressWarnings("unlikely-arg-type")
741 @Test
742 public void testEquals()
743 {
744 float[][] testData = FLOATMATRIX.denseRectArrays(12, 34, false);
745 testData[2][2] = 0;
746 for (StorageType storageType : new StorageType[] {StorageType.DENSE, StorageType.SPARSE})
747 {
748 FloatMatrixData fmd = FloatMatrixData.instantiate(testData, TemperatureUnit.KELVIN.getScale(), storageType);
749 assertTrue(fmd.equals(fmd), "Float matrix is equal to itself");
750 assertFalse(fmd.equals(null), "Float matrix is not equal to null");
751 assertFalse(fmd.equals("some string"), "Float matrix data is not equal to some string");
752 assertTrue(fmd.equals(fmd.toSparse()), "Float matrix is equal to sparse version of itself");
753 assertTrue(fmd.equals(fmd.toDense()), "Float matrix is equal to dense version of itself");
754 for (StorageType storageType2 : new StorageType[] {StorageType.DENSE, StorageType.SPARSE})
755 {
756 FloatMatrixData dvd2 = FloatMatrixData.instantiate(testData, TemperatureUnit.KELVIN.getScale(), storageType2);
757 assertEquals(fmd, dvd2,
758 "Float matrix data is equal to other double vector containing same values regardless of storage type");
759 float[][] testData2 = FLOATMATRIX.denseRectArrays(12, 33, false);
760 testData2[2][2] = 0;
761 dvd2 = FloatMatrixData.instantiate(testData2, TemperatureUnit.KELVIN.getScale(), storageType2);
762 assertFalse(fmd.equals(dvd2),
763 "Float matrix data is not equal to other double vector containing same values except last one");
764 testData2 = FLOATMATRIX.denseRectArrays(13, 34, false);
765 testData2[2][2] = 0;
766 dvd2 = FloatMatrixData.instantiate(testData2, TemperatureUnit.KELVIN.getScale(), storageType2);
767 assertFalse(fmd.equals(dvd2),
768 "Float matrix data is not equal to other double vector containing same values except last one");
769 testData2 = FLOATMATRIX.denseRectArrays(12, 34, false);
770 dvd2 = FloatMatrixData.instantiate(testData2, TemperatureUnit.KELVIN.getScale(), storageType2);
771 assertFalse(fmd.equals(dvd2),
772 "Float matrix data is not equal to other double vector containing same values except for one zero");
773 }
774 }
775 }
776
777
778
779
780 @SuppressWarnings({"rawtypes", "unchecked"})
781 @Test
782 public void sparseValueTest()
783 {
784 try
785 {
786 new FloatSparseValue(-1, 0, 123.456f);
787 fail("Negative row should have caused a ValueRuntimeException");
788 }
789 catch (ValueRuntimeException vre)
790 {
791
792 }
793
794 try
795 {
796 new FloatSparseValue(0, -1, 123.456f);
797 fail("Negative column should have caused a ValueRuntimeException");
798 }
799 catch (ValueRuntimeException vre)
800 {
801
802 }
803
804 FloatLength length = FloatLength.valueOf("123 km");
805 FloatSparseValue dsv = new FloatSparseValue(2, 3, length);
806 assertEquals(2, dsv.getRow(), "row matches");
807 assertEquals(3, dsv.getColumn(), "column matches");
808 assertEquals(123000, dsv.getValueSI(), 0.1, "value matches");
809 dsv = new FloatSparseValue(2, 3, 123.000f, LengthUnit.KILOMETER);
810 assertEquals(2, dsv.getRow(), "row matches");
811 assertEquals(3, dsv.getColumn(), "column matches");
812 assertEquals(123000, dsv.getValueSI(), 0.1, "value matches");
813 }
814
815 }