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