View Javadoc
1   package org.djunits.value.vfloat.vector;
2   
3   import static org.junit.Assert.assertEquals;
4   import static org.junit.Assert.assertFalse;
5   import static org.junit.Assert.assertNotEquals;
6   import static org.junit.Assert.assertTrue;
7   import static org.junit.Assert.fail;
8   
9   import java.lang.reflect.InvocationTargetException;
10  import java.lang.reflect.Method;
11  
12  import org.djunits.unit.AbsoluteTemperatureUnit;
13  import org.djunits.unit.AngleUnit;
14  import org.djunits.unit.AreaUnit;
15  import org.djunits.unit.DirectionUnit;
16  import org.djunits.unit.DurationUnit;
17  import org.djunits.unit.LengthUnit;
18  import org.djunits.unit.PositionUnit;
19  import org.djunits.unit.SIUnit;
20  import org.djunits.unit.TemperatureUnit;
21  import org.djunits.unit.TimeUnit;
22  import org.djunits.unit.Unit;
23  import org.djunits.unit.quantity.Quantities;
24  import org.djunits.unit.quantity.Quantity;
25  import org.djunits.unit.util.UnitException;
26  import org.djunits.unit.util.UnitRuntimeException;
27  import org.djunits.value.CLASSNAMES;
28  import org.djunits.value.ValueRuntimeException;
29  import org.djunits.value.storage.StorageType;
30  import org.djunits.value.vfloat.function.FloatMathFunctions;
31  import org.djunits.value.vfloat.matrix.FLOATMATRIX;
32  import org.djunits.value.vfloat.matrix.FloatSIMatrix;
33  import org.djunits.value.vfloat.matrix.base.AbstractFloatMatrixRel;
34  import org.djunits.value.vfloat.scalar.FloatAbsoluteTemperature;
35  import org.djunits.value.vfloat.scalar.FloatArea;
36  import org.djunits.value.vfloat.scalar.FloatDirection;
37  import org.djunits.value.vfloat.scalar.FloatDuration;
38  import org.djunits.value.vfloat.scalar.FloatPosition;
39  import org.djunits.value.vfloat.scalar.FloatTime;
40  import org.djunits.value.vfloat.vector.base.FloatVector;
41  import org.djunits.value.vfloat.vector.data.FloatVectorData;
42  import org.djutils.exceptions.Try;
43  import org.junit.Test;
44  
45  /**
46   * Test the incrementBy, etc. methods.
47   * <p>
48   * Copyright (c) 2013-2023 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
49   * BSD-style license. See <a href="https://djunits.org/docs/license.html">DJUNITS License</a>.
50   * </p>
51   * @author <a href="https://www.tudelft.nl/staff/p.knoppers/">Peter Knoppers</a>
52   */
53  public class FloatVectorMethodTest
54  {
55  
56      /**
57       * Test the standard methods of all vector classes.
58       * @throws UnitException on error
59       * @throws ValueRuntimeException on error
60       */
61      @Test
62      public void testVectorMethods() throws ValueRuntimeException, UnitException
63      {
64          float[] denseTestData = FLOATVECTOR.denseArray(105);
65          float[] sparseTestData = FLOATVECTOR.sparseArray(105);
66          float[] reverseSparseTestData = new float[sparseTestData.length];
67          // sparseTestData and reverseSparseTestData should not "run out of values" at the same index
68          for (int index = 0; index < sparseTestData.length; index++)
69          {
70              reverseSparseTestData[reverseSparseTestData.length - 1 - index] = sparseTestData[index];
71          }
72          // Ensure that both have a value at some index (i.c. 10)
73          sparseTestData[10] = 123.456f;
74          reverseSparseTestData[10] = sparseTestData[10];
75  
76          for (StorageType storageType : new StorageType[] {StorageType.DENSE, StorageType.SPARSE})
77          {
78              for (AreaUnit au : new AreaUnit[] {AreaUnit.SQUARE_METER, AreaUnit.ACRE})
79              {
80                  float[] testData = storageType.equals(StorageType.DENSE) ? denseTestData : sparseTestData;
81                  FloatAreaVector am =
82                          FloatVector.instantiate(FloatVectorData.instantiate(testData, au.getScale(), storageType), au);
83  
84                  // SPARSE AND DENSE
85                  assertEquals(am, am.toSparse());
86                  assertEquals(am, am.toDense());
87                  assertEquals(am, am.toSparse().toDense());
88                  assertEquals(am, am.toDense().toSparse());
89                  assertEquals(am.hashCode(), am.toSparse().hashCode());
90                  assertEquals(am.hashCode(), am.toDense().hashCode());
91                  assertTrue(am.toDense().isDense());
92                  assertFalse(am.toDense().isSparse());
93                  assertTrue(am.toSparse().isSparse());
94                  assertFalse(am.toSparse().isDense());
95  
96                  // EQUALS
97                  assertEquals(am, am);
98                  assertNotEquals(am, new Object());
99                  assertNotEquals(am, null);
100                 assertNotEquals(am, FloatVector.instantiate(
101                         FloatVectorData.instantiate(testData, LengthUnit.METER.getScale(), storageType), LengthUnit.METER));
102                 assertNotEquals(am, am.divide(2.0d));
103 
104                 // MUTABLE
105                 assertFalse(am.isMutable());
106                 FloatAreaVector ammut = am.mutable();
107                 assertTrue(ammut.isMutable());
108                 assertFalse(am.isMutable());
109                 FloatAreaVector ammut2 = ammut.multiplyBy(1.0);
110                 assertEquals(am, ammut2);
111                 assertTrue(ammut.isMutable());
112                 assertFalse(am.isMutable());
113                 assertTrue(ammut2.isMutable());
114                 ammut2 = ammut2.mutable().divideBy(2.0);
115                 assertEquals(am, ammut);
116                 assertNotEquals(am, ammut2);
117                 FloatAreaVector ammut3 = ammut2.mutable().divideBy(0.0);
118                 for (int index = 0; index < ammut3.size(); index++)
119                 {
120                     if (ammut2.getSI(index) == 0)
121                     {
122                         assertTrue("Value should be NaN", Float.isNaN(ammut3.getSI(index)));
123                     }
124                     else
125                     {
126                         assertTrue("Value should be Infinite", Float.isInfinite(ammut3.getSI(index)));
127                     }
128                 }
129 
130                 // ZSUM and CARDINALITY
131                 FloatArea zSum = am.zSum();
132                 double sum = 0;
133                 int card = 0;
134                 for (int index = 0; index < testData.length; index++)
135                 {
136                     sum += testData[index];
137                     card += testData[index] == 0.0d ? 0 : 1;
138                 }
139                 assertEquals("zSum", sum, zSum.getInUnit(), 0.1);
140                 assertEquals("cardinality", card, am.cardinality());
141 
142                 // INCREMENTBY(SCALAR) and DECREMENTBY(SCALAR)
143                 FloatAreaVector amold = am.clone();
144                 FloatArea fa = FloatArea.of(10.0f, "m^2");
145                 FloatAreaVector aminc = am.mutable().incrementBy(fa).immutable();
146                 FloatAreaVector amdec = am.mutable().decrementBy(fa).immutable();
147                 FloatAreaVector amid = aminc.mutable().decrementBy(fa);
148                 assertEquals("immutable vector should not change when converted to mutable", am, amold);
149                 for (int index = 0; index < testData.length; index++)
150                 {
151                     assertEquals("increment and decrement with scalar should result in same vector", am.getSI(index),
152                             amid.getSI(index), 0.1);
153                     assertEquals("m + s = (m+s)", au.getScale().toStandardUnit(testData[index]) + 10.0, aminc.getSI(index),
154                             0.1);
155                     assertEquals("m - s = (m-s)", au.getScale().toStandardUnit(testData[index]) - 10.0, amdec.getSI(index),
156                             0.1);
157                 }
158 
159                 // MULTIPLYBY() and DIVIDEBY(), TIMES(), DIVIDE()
160                 FloatAreaVector amt5 = am.mutable().multiplyBy(5.0d).immutable();
161                 FloatAreaVector amd5 = am.mutable().divideBy(5.0d).immutable();
162                 FloatAreaVector amtd = amt5.mutable().divideBy(5.0d);
163                 FloatAreaVector amtimD = am.times(5.0d);
164                 FloatAreaVector amtimF = am.times(5.0f);
165                 FloatAreaVector amdivD = am.divide(5.0d);
166                 FloatAreaVector amdivF = am.divide(5.0f);
167                 for (int index = 0; index < testData.length; index++)
168                 {
169                     assertEquals("times followed by divide with constant should result in same vector", am.getSI(index),
170                             amtd.getSI(index), 0.1);
171                     assertEquals("m * 5.0 = (m*5.0)", au.getScale().toStandardUnit(testData[index]) * 5.0d, amt5.getSI(index),
172                             0.2);
173                     assertEquals("m / 5.0 = (m/5.0)", au.getScale().toStandardUnit(testData[index]) / 5.0d, amd5.getSI(index),
174                             0.1);
175                     assertEquals("amtimD", amt5.getSI(index), amtimD.getSI(index), 0.1d);
176                     assertEquals("amtimF", amt5.getSI(index), amtimF.getSI(index), 0.1d);
177                     assertEquals("amdivD", amd5.getSI(index), amdivD.getSI(index), 0.01d);
178                     assertEquals("amdivD", amd5.getSI(index), amdivF.getSI(index), 0.01d);
179                 }
180 
181                 // GET(), GETINUNIT()
182                 assertEquals("get()", new FloatArea(testData[2], au), am.get(2));
183                 assertEquals("getSI()", au.getScale().toStandardUnit(testData[2]), am.getSI(2), 0.1);
184                 assertEquals("getInUnit()", testData[2], am.getInUnit(2), 0.1);
185                 assertEquals("getInUnit(unit)",
186                         AreaUnit.SQUARE_YARD.getScale().fromStandardUnit(au.getScale().toStandardUnit(testData[2])),
187                         am.getInUnit(2, AreaUnit.SQUARE_YARD), 0.1);
188 
189                 // SET(), SETINUNIT()
190                 FloatArea fasqft = new FloatArea(10.5d, AreaUnit.SQUARE_FOOT);
191                 FloatAreaVector famChange = am.clone().mutable();
192                 famChange.set(2, fasqft);
193                 assertEquals("set()", fasqft.si, famChange.get(2).si, 0.1d);
194                 famChange = am.clone().mutable();
195                 famChange.setSI(2, 123.4f);
196                 assertEquals("setSI()", 123.4d, famChange.get(2).si, 0.1d);
197                 famChange = am.clone().mutable();
198                 famChange.setInUnit(2, 1.2f);
199                 assertEquals("setInUnit()", 1.2d, famChange.getInUnit(2), 0.1d);
200                 famChange = am.clone().mutable();
201                 famChange.setInUnit(2, 1.5f, AreaUnit.HECTARE);
202                 assertEquals("setInUnit(unit)", 15000.0d, famChange.get(2).si, 1.0d);
203 
204                 // GETVALUES(), GETSCALARS()
205                 float[] valsi = am.getValuesSI();
206                 float[] valunit = am.getValuesInUnit();
207                 float[] valsqft = am.getValuesInUnit(AreaUnit.SQUARE_YARD);
208                 FloatArea[] valscalars = am.getScalars();
209                 for (int index = 0; index < testData.length; index++)
210                 {
211                     assertEquals("getValuesSI()", au.getScale().toStandardUnit(testData[index]), valsi[index], 0.1);
212                     assertEquals("getValuesInUnit()", testData[index], valunit[index], 0.1);
213                     assertEquals("getValuesInUnit(unit)",
214                             AreaUnit.SQUARE_YARD.getScale().fromStandardUnit(au.getScale().toStandardUnit(testData[index])),
215                             valsqft[index], 0.1);
216                     assertEquals("getValuesInUnit(unit)", au.getScale().toStandardUnit(testData[index]), valscalars[index].si,
217                             0.1);
218                 }
219 
220                 // ASSIGN FUNCTION ABS, CEIL, FLOOR, NEG, RINT
221                 FloatAreaVector amdiv2 = am.divide(2.0d);
222                 assertEquals(am.getStorageType(), amdiv2.getStorageType());
223                 assertEquals(am.getDisplayUnit(), amdiv2.getDisplayUnit());
224                 FloatAreaVector amAbs = amdiv2.mutable().abs().immutable();
225                 assertEquals(am.getStorageType(), amAbs.getStorageType());
226                 assertEquals(am.getDisplayUnit(), amAbs.getDisplayUnit());
227                 FloatAreaVector amCeil = amdiv2.mutable().ceil().immutable();
228                 assertEquals(am.getStorageType(), amCeil.getStorageType());
229                 assertEquals(am.getDisplayUnit(), amCeil.getDisplayUnit());
230                 FloatAreaVector amFloor = amdiv2.mutable().floor().immutable();
231                 assertEquals(am.getStorageType(), amFloor.getStorageType());
232                 assertEquals(am.getDisplayUnit(), amFloor.getDisplayUnit());
233                 FloatAreaVector amNeg = amdiv2.mutable().neg().immutable();
234                 assertEquals(am.getStorageType(), amNeg.getStorageType());
235                 assertEquals(am.getDisplayUnit(), amNeg.getDisplayUnit());
236                 FloatAreaVector amRint = amdiv2.mutable().rint().immutable();
237                 assertEquals(am.getStorageType(), amRint.getStorageType());
238                 assertEquals(am.getDisplayUnit(), amRint.getDisplayUnit());
239                 for (int index = 0; index < testData.length; index++)
240                 {
241                     // TODO: Should be rounded IN THE UNIT rather than BY SI VALUES
242                     assertEquals("div2", au.getScale().toStandardUnit(testData[index]) / 2.0d, amdiv2.getSI(index), 0.1d);
243                     assertEquals("abs", Math.abs(au.getScale().toStandardUnit(testData[index]) / 2.0d), amAbs.getSI(index),
244                             0.1d);
245                     assertEquals("ceil", Math.ceil(au.getScale().toStandardUnit(testData[index]) / 2.0d), amCeil.getSI(index),
246                             0.1d);
247                     assertEquals("floor", Math.floor(au.getScale().toStandardUnit(testData[index]) / 2.0d),
248                             amFloor.getSI(index), 0.1d);
249                     assertEquals("neg", -au.getScale().toStandardUnit(testData[index]) / 2.0d, amNeg.getSI(index), 0.1d);
250                     assertEquals("rint", Math.rint(au.getScale().toStandardUnit(testData[index]) / 2.0d), amRint.getSI(index),
251                             0.1d);
252                 }
253 
254                 // TEST METHODS THAT INVOLVE TWO VECTOR INSTANCES
255 
256                 for (StorageType storageType2 : new StorageType[] {StorageType.DENSE, StorageType.SPARSE})
257                 {
258                     float[] testData2 = storageType2.equals(StorageType.DENSE) ? denseTestData : reverseSparseTestData;
259                     for (AreaUnit au2 : new AreaUnit[] {AreaUnit.SQUARE_METER, AreaUnit.ACRE})
260                     {
261 
262                         // PLUS and INCREMENTBY(VECTOR)
263                         FloatAreaVector am2 = FloatVector
264                                 .instantiate(FloatVectorData.instantiate(testData2, au2.getScale(), storageType2), au2);
265                         FloatAreaVector amSum1 = am.plus(am2);
266                         FloatAreaVector amSum2 = am2.plus(am);
267                         FloatAreaVector amSum3 = am.mutable().incrementBy(am2).immutable();
268                         // different order of running out of nonzero values
269                         FloatAreaVector amSum4 = am2.mutable().incrementBy(am).immutable();
270                         assertEquals("a+b == b+a", amSum1, amSum2);
271                         assertEquals("a+b == b+a", amSum1, amSum3);
272                         assertEquals("a+c == c+a", amSum1, amSum4);
273                         for (int index = 0; index < testData.length; index++)
274                         {
275                             float tolerance = Float.isFinite(amSum1.getSI(index))
276                                     ? Math.abs((float) (amSum1.getSI(index) / 10000.0d)) : 0.1f;
277                             assertEquals("value in vector matches", au.getScale().toStandardUnit(testData[index])
278                                     + au2.getScale().toStandardUnit(testData2[index]), amSum1.getSI(index), tolerance);
279                         }
280 
281                         // MINUS and DECREMENTBY(VECTOR)
282                         FloatAreaVector amDiff1 = am.minus(am2);
283                         FloatAreaVector amDiff2 = am2.minus(am).mutable().neg();
284                         FloatAreaVector amDiff3 = am.mutable().decrementBy(am2).immutable();
285                         // different order of running out of nonzero values
286                         FloatAreaVector amDiff4 = am2.mutable().decrementBy(am).neg().immutable();
287                         assertEquals("a-b == -(b-a)", amDiff1, amDiff2);
288                         assertEquals("a-b == -(b-a)", amDiff1, amDiff3);
289                         assertEquals("a-c == -(c-a)", amDiff1, amDiff4);
290                         for (int index = 0; index < testData.length; index++)
291                         {
292                             float tolerance = Float.isFinite(amDiff1.getSI(index))
293                                     ? Math.abs((float) (amDiff1.getSI(index) / 10000.0d)) : 0.1f;
294                             assertEquals("value in vector matches", au.getScale().toStandardUnit(testData[index])
295                                     - au2.getScale().toStandardUnit(testData2[index]), amDiff1.getSI(index), tolerance);
296                         }
297 
298                         // TIMES(VECTOR) and DIVIDE(VECTOR)
299                         FloatSIVector amTim = am.times(am2);
300                         FloatSIVector amDiv = am.divide(am2);
301                         assertEquals("unit of m2 * m2 should be m4", "m4",
302                                 amTim.getDisplayUnit().getQuantity().getSiDimensions().toString(false, false, false));
303                         assertEquals("unit of m2 / m2 should be 1", "1",
304                                 amDiv.getDisplayUnit().getQuantity().getSiDimensions().toString(false, false, false));
305                         for (int index = 0; index < testData.length; index++)
306                         {
307                             float tolerance = Float.isFinite(amTim.getSI(index))
308                                     ? Math.abs((float) (amTim.getSI(index) / 10000.0d)) : 0.1f;
309                             assertEquals("value in m2 * m2 matches", au.getScale().toStandardUnit(testData[index])
310                                     * au2.getScale().toStandardUnit(testData2[index]), amTim.getSI(index), tolerance);
311                             tolerance = Float.isFinite(amTim.getSI(index)) ? Math.abs((float) (amDiv.getSI(index) / 10000.0d))
312                                     : 0.1f;
313                             assertEquals("value in m2 / m2 matches (could be NaN)",
314                                     au.getScale().toStandardUnit(testData[index])
315                                             / au2.getScale().toStandardUnit(testData2[index]),
316                                     amDiv.getSI(index), tolerance);
317                         }
318                         // This does not compile: SIVector amTim2 = am.immutable().multiplyBy(am2).immutable();
319                     }
320                 }
321             }
322         }
323     }
324 
325     /**
326      * Test if mutable methods give an error in case the vector is immutable.
327      */
328     @Test
329     public void testImmutableVector()
330     {
331         float[] denseTestData = FLOATVECTOR.denseArray(105);
332         float[] sparseTestData = FLOATVECTOR.sparseArray(105);
333 
334         for (StorageType storageType : new StorageType[] {StorageType.DENSE, StorageType.SPARSE})
335         {
336             for (AreaUnit au : new AreaUnit[] {AreaUnit.SQUARE_METER, AreaUnit.ACRE})
337             {
338                 float[] testData = storageType.equals(StorageType.DENSE) ? denseTestData : sparseTestData;
339                 FloatAreaVector am =
340                         FloatVector.instantiate(FloatVectorData.instantiate(testData, au.getScale(), storageType), au);
341                 am = am.immutable();
342                 final FloatAreaVector amPtr = am;
343                 FloatArea fa = FloatArea.of(10.0f, "m^2");
344                 Try.testFail(() -> amPtr.assign(FloatMathFunctions.ABS), "ImmutableVector.assign(...) should throw error");
345                 Try.testFail(() -> amPtr.decrementBy(fa), "ImmutableVector.decrementBy(scalar) should throw error");
346                 Try.testFail(() -> amPtr.decrementBy(amPtr), "ImmutableVector.decrementBy(vector) should throw error");
347                 Try.testFail(() -> amPtr.incrementBy(fa), "ImmutableVector.incrementBy(scalar) should throw error");
348                 Try.testFail(() -> amPtr.incrementBy(amPtr), "ImmutableVector.incrementBy(vector) should throw error");
349                 Try.testFail(() -> amPtr.divideBy(2.0d), "ImmutableVector.divideBy(factor) should throw error");
350                 Try.testFail(() -> amPtr.multiplyBy(2.0d), "ImmutableVector.multiplyBy(factor) should throw error");
351                 Try.testFail(() -> amPtr.set(1, fa), "ImmutableVector.set() should throw error");
352                 Try.testFail(() -> amPtr.setSI(1, 20.1f), "ImmutableVector.setSI() should throw error");
353                 Try.testFail(() -> amPtr.setInUnit(1, 15.2f), "ImmutableVector.setInUnit(f) should throw error");
354                 Try.testFail(() -> amPtr.setInUnit(1, 15.2f, AreaUnit.ARE),
355                         "ImmutableVector.setInUnit(f, u) should throw error");
356                 Try.testFail(() -> amPtr.abs(), "ImmutableVector.abs() should throw error");
357                 Try.testFail(() -> amPtr.ceil(), "ImmutableVector.ceil() should throw error");
358                 Try.testFail(() -> amPtr.floor(), "ImmutableVector.floor() should throw error");
359                 Try.testFail(() -> amPtr.neg(), "ImmutableVector.neg() should throw error");
360                 Try.testFail(() -> amPtr.rint(), "ImmutableVector.rint() should throw error");
361             }
362         }
363     }
364 
365     /**
366      * Test toString() methods. TODO: expand?
367      */
368     @Test
369     public void testVectorToString()
370     {
371         float[] denseTestData = FLOATVECTOR.denseArray(105);
372         float[] sparseTestData = FLOATVECTOR.sparseArray(105);
373 
374         for (StorageType storageType : new StorageType[] {StorageType.DENSE, StorageType.SPARSE})
375         {
376             for (AreaUnit au : new AreaUnit[] {AreaUnit.SQUARE_METER, AreaUnit.ACRE})
377             {
378                 float[] testData = storageType.equals(StorageType.DENSE) ? denseTestData : sparseTestData;
379                 FloatAreaVector am =
380                         FloatVector.instantiate(FloatVectorData.instantiate(testData, au.getScale(), storageType), au);
381                 String s1 = am.toString(); // non-verbose with unit
382                 assertTrue(s1.contains(au.getDefaultTextualAbbreviation()));
383                 String s2 = am.toString(AreaUnit.SQUARE_INCH); // non-verbose with unit
384                 assertTrue(s2.contains(AreaUnit.SQUARE_INCH.getDefaultTextualAbbreviation()));
385                 String s3 = am.toString(AreaUnit.SQUARE_INCH, true, true); // verbose with unit
386                 assertTrue(s3.contains(AreaUnit.SQUARE_INCH.getDefaultTextualAbbreviation()));
387                 if (storageType.equals(StorageType.DENSE))
388                 {
389                     assertTrue(s3.contains("Dense"));
390                     assertFalse(s3.contains("Sparse"));
391                 }
392                 else
393                 {
394                     assertFalse(s3.contains("Dense"));
395                     assertTrue(s3.contains("Sparse"));
396                 }
397                 assertTrue(s3.contains("Rel"));
398                 assertFalse(s3.contains("Abs"));
399                 assertTrue(s3.contains("Immutable"));
400                 assertFalse(s3.contains("Mutable"));
401                 FloatAreaVector ammut = am.mutable();
402                 String smut = ammut.toString(AreaUnit.SQUARE_INCH, true, true); // verbose with unit
403                 assertFalse(smut.contains("Immutable"));
404                 assertTrue(smut.contains("Mutable"));
405                 String sNotVerbose = ammut.toString(false, false);
406                 assertFalse(sNotVerbose.contains("Rel"));
407                 assertFalse(sNotVerbose.contains("Abs"));
408                 assertFalse(sNotVerbose.contains("Immutable"));
409                 assertFalse(sNotVerbose.contains("Mutable"));
410                 assertFalse(sNotVerbose.contains(au.getDefaultTextualAbbreviation()));
411             }
412         }
413         FloatTimeVector tm = FloatVector.instantiate(
414                 FloatVectorData.instantiate(denseTestData, TimeUnit.DEFAULT.getScale(), StorageType.DENSE), TimeUnit.DEFAULT);
415         String st = tm.toString(TimeUnit.DEFAULT, true, true); // verbose with unit
416         assertFalse(st.contains("Rel"));
417         assertTrue(st.contains("Abs"));
418         FloatLengthVector lm = FloatVector.instantiate(
419                 FloatVectorData.instantiate(denseTestData, LengthUnit.SI.getScale(), StorageType.DENSE), LengthUnit.SI);
420         String sl = lm.toString(LengthUnit.SI, true, true); // verbose with unit
421         assertTrue(sl.contains("Rel"));
422         assertFalse(sl.contains("Abs"));
423     }
424 
425     /**
426      * Test the extra methods that Absolute and Relative with Absolute matrices implement.
427      */
428     @Test
429     public void testSpecialVectorMethodsRelWithAbs()
430     {
431         float[] denseTestData = FLOATVECTOR.denseArray(105);
432         FloatTimeVector tv = FloatVector.instantiate(
433                 FloatVectorData.instantiate(denseTestData, TimeUnit.DEFAULT.getScale(), StorageType.DENSE), TimeUnit.DEFAULT);
434         FloatDurationVector dv = FloatVector.instantiate(
435                 FloatVectorData.instantiate(denseTestData, DurationUnit.MINUTE.getScale(), StorageType.DENSE),
436                 DurationUnit.SECOND);
437         assertTrue(tv.isAbsolute());
438         assertFalse(dv.isAbsolute());
439         assertFalse(tv.isRelative());
440         assertTrue(dv.isRelative());
441 
442         FloatTimeVector absPlusRel = tv.plus(dv);
443         FloatTimeVector absMinusRel = tv.minus(dv);
444         float[] halfDenseData = FLOATVECTOR.denseArray(105);
445         for (int index = 0; index < halfDenseData.length; index++)
446         {
447             halfDenseData[index] *= 0.5;
448         }
449         FloatTimeVector halfTimeVector = FloatVector.instantiate(
450                 FloatVectorData.instantiate(halfDenseData, TimeUnit.DEFAULT.getScale(), StorageType.DENSE), TimeUnit.DEFAULT);
451         FloatDurationVector absMinusAbs = tv.minus(halfTimeVector);
452         FloatTimeVector absDecByRelS = tv.mutable().decrementBy(FloatDuration.of(1.0f, "min"));
453         FloatTimeVector absDecByRelM = tv.mutable().decrementBy(dv.divide(2.0d));
454         FloatTimeVector relPlusAbs = dv.plus(tv);
455         for (int index = 0; index < denseTestData.length; index++)
456         {
457             assertEquals("absPlusRel", 61.0 * denseTestData[index], absPlusRel.getSI(index), 0.01);
458             assertEquals("absMinusRel", -59.0 * denseTestData[index], absMinusRel.getSI(index), 0.01);
459             assertEquals("absMinusAbs", denseTestData[index] / 2.0, absMinusAbs.getSI(index), 0.01);
460             assertEquals("absDecByRelS", denseTestData[index] - 60.0, absDecByRelS.getSI(index), 0.01);
461             assertEquals("absDecByRelM", -29.0 * denseTestData[index], absDecByRelM.getSI(index), 0.01);
462             assertEquals("relPlusAbs", 61.0 * denseTestData[index], relPlusAbs.getSI(index), 0.01);
463         }
464         for (int dLength : new int[] {-1, 1})
465         {
466             float[] other = FLOATVECTOR.denseArray(denseTestData.length + dLength);
467             FloatTimeVector wrongTimeVector = FloatVector.instantiate(
468                     FloatVectorData.instantiate(other, TimeUnit.DEFAULT.getScale(), StorageType.DENSE), TimeUnit.DEFAULT);
469             try
470             {
471                 tv.mutable().minus(wrongTimeVector);
472                 fail("Mismatching size should have thrown a ValueRuntimeException");
473             }
474             catch (ValueRuntimeException vre)
475             {
476                 // Ignore expected exception
477             }
478         }
479         assertTrue("toString returns something informative",
480                 FloatVectorData.instantiate(denseTestData, TimeUnit.DEFAULT.getScale(), StorageType.DENSE).toString()
481                         .startsWith("FloatVectorData"));
482     }
483 
484     /**
485      * Test the instantiateAbs method and instantiateScalarAbsSI method.
486      */
487     @Test
488     public void testInstantiateAbs()
489     {
490         float[] denseTestData = FLOATVECTOR.denseArray(105);
491         FloatTimeVector timeVector = FloatVector.instantiate(
492                 FloatVectorData.instantiate(denseTestData, TimeUnit.DEFAULT.getScale(), StorageType.DENSE), TimeUnit.DEFAULT);
493         FloatDurationVector durationVector = FloatVector.instantiate(
494                 FloatVectorData.instantiate(denseTestData, DurationUnit.MINUTE.getScale(), StorageType.DENSE),
495                 DurationUnit.SECOND);
496 
497         float[] halfDenseData = FLOATVECTOR.denseArray(105);
498         for (int index = 0; index < halfDenseData.length; index++)
499         {
500             halfDenseData[index] *= 0.5;
501         }
502         FloatTimeVector relPlusAbsTime = durationVector.plus(timeVector);
503         for (int index = 0; index < denseTestData.length; index++)
504         {
505             assertEquals("relPlusAbsTime", 61.0 * denseTestData[index], relPlusAbsTime.getSI(index), 0.01);
506         }
507         FloatTime floatTime = durationVector.instantiateScalarAbsSI(123.456f, TimeUnit.EPOCH_DAY);
508         assertEquals("Unit of instantiateScalarAbsSI matches", TimeUnit.EPOCH_DAY, floatTime.getDisplayUnit());
509         assertEquals("Value of instantiateScalarAbsSI matches", 123.456f, floatTime.si, 0.1);
510 
511         FloatAngleVector angleVector = FloatVector.instantiate(
512                 FloatVectorData.instantiate(denseTestData, AngleUnit.DEGREE.getScale(), StorageType.DENSE), AngleUnit.DEGREE);
513         FloatDirectionVector directionVector = FloatVector.instantiate(
514                 FloatVectorData.instantiate(denseTestData, DirectionUnit.EAST_DEGREE.getScale(), StorageType.DENSE),
515                 DirectionUnit.EAST_DEGREE);
516 
517         FloatDirectionVector relPlusAbsDirection = angleVector.plus(directionVector);
518         for (int index = 0; index < denseTestData.length; index++)
519         {
520             assertEquals("relPlusAbsDirection", 2.0 / 180 * Math.PI * denseTestData[index], relPlusAbsDirection.getSI(index),
521                     0.01);
522         }
523         FloatDirection floatDirection = angleVector.instantiateScalarAbsSI(123.456f, DirectionUnit.NORTH_RADIAN);
524         assertEquals("Unit of instantiateScalarAbsSI matches", DirectionUnit.NORTH_RADIAN, floatDirection.getDisplayUnit());
525         assertEquals("Value of instantiateScalarAbsSI matches", 123.456f, floatDirection.si, 0.1);
526 
527         FloatTemperatureVector temperatureVector = FloatVector.instantiate(
528                 FloatVectorData.instantiate(denseTestData, TemperatureUnit.DEGREE_FAHRENHEIT.getScale(), StorageType.DENSE),
529                 TemperatureUnit.DEGREE_FAHRENHEIT);
530         FloatAbsoluteTemperatureVector absoluteTemperatureVector = FloatVector.instantiate(
531                 FloatVectorData.instantiate(denseTestData, AbsoluteTemperatureUnit.KELVIN.getScale(), StorageType.DENSE),
532                 AbsoluteTemperatureUnit.KELVIN);
533 
534         FloatAbsoluteTemperatureVector relPlusAbsTemperature = temperatureVector.plus(absoluteTemperatureVector);
535         for (int index = 0; index < denseTestData.length; index++)
536         {
537             assertEquals("relPlusAbsTemperature", (1.0 + 5.0 / 9.0) * denseTestData[index], relPlusAbsTemperature.getSI(index),
538                     0.01);
539         }
540         FloatAbsoluteTemperature floatAbsoluteTemperature =
541                 temperatureVector.instantiateScalarAbsSI(123.456f, AbsoluteTemperatureUnit.DEGREE_FAHRENHEIT);
542         assertEquals("Unit of instantiateScalarAbsSI matches", AbsoluteTemperatureUnit.DEGREE_FAHRENHEIT,
543                 floatAbsoluteTemperature.getDisplayUnit());
544         assertEquals("Value of instantiateScalarAbsSI matches", 123.456f, floatAbsoluteTemperature.si, 0.1);
545 
546         FloatLengthVector lengthVector = FloatVector.instantiate(
547                 FloatVectorData.instantiate(denseTestData, LengthUnit.MILE.getScale(), StorageType.DENSE), LengthUnit.MILE);
548         FloatPositionVector positionVector = FloatVector.instantiate(
549                 FloatVectorData.instantiate(denseTestData, PositionUnit.KILOMETER.getScale(), StorageType.DENSE),
550                 PositionUnit.KILOMETER);
551 
552         FloatPositionVector relPlusAbsPosition = lengthVector.plus(positionVector);
553         for (int index = 0; index < denseTestData.length; index++)
554         {
555             assertEquals("relPlusAbsPosition", 2609.344 * denseTestData[index], relPlusAbsPosition.getSI(index), 1);
556         }
557         FloatPosition floatPosition = lengthVector.instantiateScalarAbsSI(123.456f, PositionUnit.ANGSTROM);
558         assertEquals("Unit of instantiateScalarAbsSI matches", PositionUnit.ANGSTROM, floatPosition.getDisplayUnit());
559         assertEquals("Value of instantiateScalarAbsSI matches", 123.456f, floatPosition.si, 0.1);
560     }
561 
562     /**
563      * Test the <code>as</code> method of the SIVector class.
564      * @throws SecurityException on error
565      * @throws NoSuchMethodException on error
566      * @throws InvocationTargetException on error
567      * @throws IllegalArgumentException on error
568      * @throws IllegalAccessException on error
569      * @throws ClassNotFoundException on error
570      * @throws UnitException on error
571      * @param <U> the unit type
572      */
573     @SuppressWarnings("unchecked")
574     @Test
575     public <U extends Unit<U>> void testAsUnit() throws ClassNotFoundException, NoSuchMethodException, SecurityException,
576             IllegalAccessException, IllegalArgumentException, InvocationTargetException, UnitException
577     {
578         float[][] testValues = FLOATMATRIX.denseRectArrays(10, 20);
579         for (StorageType storageType : new StorageType[] {StorageType.DENSE, StorageType.SPARSE})
580         {
581             for (String type : CLASSNAMES.REL_LIST)
582             {
583                 Class.forName("org.djunits.unit." + type + "Unit");
584                 Quantity<U> quantity = (Quantity<U>) Quantities.INSTANCE.getQuantity(type + "Unit");
585                 for (U unit : quantity.getUnitsById().values())
586                 {
587                     for (StorageType storageType2 : new StorageType[] {StorageType.DENSE, storageType})
588                     {
589                         SIUnit siUnit = SIUnit.of(unit.getQuantity().getSiDimensions());
590                         FloatSIMatrix matrix = FloatSIMatrix.instantiate(testValues, siUnit, storageType2);
591                         Method asMethod = FloatSIMatrix.class.getDeclaredMethod("as", Unit.class);
592                         AbstractFloatMatrixRel<U, ?, ?, ?> asMatrix =
593                                 (AbstractFloatMatrixRel<U, ?, ?, ?>) asMethod.invoke(matrix, siUnit);
594                         assertEquals(matrix.getDisplayUnit().getStandardUnit(), asMatrix.getDisplayUnit());
595                         siUnit = SIUnit.of(AbsoluteTemperatureUnit.KELVIN.getQuantity().getSiDimensions());
596                         for (int row = 0; row < testValues.length; row++)
597                         {
598                             for (int col = 0; col < testValues[0].length; col++)
599                             {
600                                 assertEquals("Values should match", testValues[row][col], matrix.getInUnit(row, col), 0.001);
601                             }
602                         }
603                         try
604                         {
605                             asMethod.invoke(matrix, siUnit);
606                             fail("as method should not be able to cast to unrelated (absoluteTemperature) unit");
607                         }
608                         catch (InvocationTargetException ite)
609                         {
610                             Throwable cause = ite.getCause();
611                             assertEquals("cause is UnitRuntimeException", UnitRuntimeException.class, cause.getClass());
612                             // Otherwise ignore expected exception
613                         }
614                     }
615                 }
616             }
617         }
618     }
619 
620     /**
621      * Test the equals method.
622      */
623     @SuppressWarnings("unlikely-arg-type")
624     @Test
625     public void testEquals()
626     {
627         float[] testData = FLOATVECTOR.denseArray(123);
628         testData[2] = 0;
629         for (StorageType storageType : new StorageType[] {StorageType.DENSE, StorageType.SPARSE})
630         {
631             FloatVectorData fvd = FloatVectorData.instantiate(testData, TemperatureUnit.KELVIN.getScale(), storageType);
632             assertTrue("Float vector data is equal to itself", fvd.equals(fvd));
633             assertFalse("Float vector data is not equal to null", fvd.equals(null));
634             assertFalse("Float vector data is not equal to some string", fvd.equals("some string"));
635             assertTrue("Float vector is equal to sparse version of itself", fvd.equals(fvd.toSparse()));
636             assertTrue("Float vector is equal to dense version of itself", fvd.equals(fvd.toDense()));
637             for (StorageType storageType2 : new StorageType[] {StorageType.DENSE, StorageType.SPARSE})
638             {
639                 FloatVectorData dvd2 = FloatVectorData.instantiate(testData, TemperatureUnit.KELVIN.getScale(), storageType2);
640                 assertEquals(
641                         "Float vector data is equal to other double vector containing same values regardless of storage type",
642                         fvd, dvd2);
643                 float[] testData2 = FLOATVECTOR.denseArray(122);
644                 testData2[2] = 0;
645                 dvd2 = FloatVectorData.instantiate(testData2, TemperatureUnit.KELVIN.getScale(), storageType2);
646                 assertFalse("Float vector data is not equal to other double vector containing same values except last one",
647                         fvd.equals(dvd2));
648                 testData2 = FLOATVECTOR.denseArray(123);
649                 dvd2 = FloatVectorData.instantiate(testData2, TemperatureUnit.KELVIN.getScale(), storageType2);
650                 assertFalse("Float vector data is not equal to other double vector containing same values except for one zero",
651                         fvd.equals(dvd2));
652             }
653         }
654     }
655 
656 }