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