View Javadoc
1   package org.djunits.value.vdouble.matrix;
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.base.AbstractDoubleMatrixRel;
33  import org.djunits.value.vdouble.matrix.base.DoubleMatrix;
34  import org.djunits.value.vdouble.matrix.base.DoubleSparseValue;
35  import org.djunits.value.vdouble.matrix.data.DoubleMatrixData;
36  import org.djunits.value.vdouble.scalar.AbsoluteTemperature;
37  import org.djunits.value.vdouble.scalar.Area;
38  import org.djunits.value.vdouble.scalar.Direction;
39  import org.djunits.value.vdouble.scalar.Duration;
40  import org.djunits.value.vdouble.scalar.Length;
41  import org.djunits.value.vdouble.scalar.Position;
42  import org.djunits.value.vdouble.scalar.Time;
43  import org.djunits.value.vdouble.vector.AreaVector;
44  import org.djunits.value.vfloat.matrix.FloatAreaMatrix;
45  import org.djunits.value.vfloat.matrix.base.FloatMatrix;
46  import org.djunits.value.vfloat.vector.FLOATVECTOR;
47  import org.junit.Test;
48  
49  /**
50   * ...
51   */
52  public class DoubleMatrixMethodTest
53  {
54  
55      /**
56       * Test the standard methods of all matrix classes.
57       * @throws UnitException on error
58       * @throws ValueRuntimeException on error
59       */
60      @Test
61      @SuppressWarnings("checkstyle:methodlength")
62      public void testMatrixMethods() throws ValueRuntimeException, UnitException
63      {
64          double[][] denseTestData = DOUBLEMATRIX.denseRectArrays(10, 20);
65          double[][] sparseTestData = DOUBLEMATRIX.sparseRectArrays(10, 20);
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 there are > 50% positions where both have a non-zero value
73          for (int row = 1; row < 8; row++)
74          {
75              for (int col = 2; col < 18; col++)
76              {
77                  sparseTestData[row][col] = 10000.456 + row + 100 * col;
78                  reverseSparseTestData[row][col] = 20000.567 + row + 100 * col;
79              }
80          }
81  
82          for (StorageType storageType : new StorageType[] { StorageType.DENSE, StorageType.SPARSE })
83          {
84              for (AreaUnit au : new AreaUnit[] { AreaUnit.SQUARE_METER, AreaUnit.ACRE })
85              {
86                  double[][] testData = storageType.equals(StorageType.DENSE) ? denseTestData : sparseTestData;
87                  AreaMatrix am =
88                          DoubleMatrix.instantiate(DoubleMatrixData.instantiate(testData, au.getScale(), storageType), au);
89  
90                  // INDEX CHECKING
91                  for (int row : new int[] { -1, 0, denseTestData.length - 1, denseTestData.length })
92                  {
93                      for (int col : new int[] { -1, 0, denseTestData[0].length - 1, denseTestData[0].length })
94                      {
95                          if (row < 0 || col < 0 || row >= denseTestData.length || col >= denseTestData[0].length)
96                          {
97                              try
98                              {
99                                  am.get(row, col);
100                                 fail("bad row or bad column value should have thrown a ValueRuntimeException");
101                             }
102                             catch (ValueRuntimeException vre)
103                             {
104                                 // Ignore expected exception
105                             }
106                         }
107                         else
108                         {
109                             am.get(row, col);
110                         }
111                     }
112                     if (row < 0 || row >= denseTestData.length)
113                     {
114                         try
115                         {
116                             am.getRow(row);
117                             fail("getRow with bad row value should have thrown a ValueRuntimeException");
118                         }
119                         catch (ValueRuntimeException vre)
120                         {
121                             // Ignore expected exception
122                         }
123                     }
124                 }
125                 for (int col : new int[] { -1, 0, denseTestData[0].length - 1, denseTestData[0].length })
126                 {
127                     if (col < 0 || col >= denseTestData[0].length)
128                     {
129                         try
130                         {
131                             am.getColumn(col);
132                             fail("getColumn with bad column value should have thrown a ValueRuntimeException");
133                         }
134                         catch (ValueRuntimeException vre)
135                         {
136                             // Ignore expected exception
137                         }
138                     }
139                     else
140                     {
141                         am.getColumn(col);
142                     }
143                 }
144 
145                 // SPARSE AND DENSE
146                 assertEquals(am, am.toSparse());
147                 assertEquals(am, am.toDense());
148                 assertEquals(am, am.toSparse().toDense());
149                 assertEquals(am, am.toDense().toSparse());
150                 assertEquals(am.hashCode(), am.toSparse().hashCode());
151                 assertEquals(am.hashCode(), am.toDense().hashCode());
152                 assertTrue(am.toDense().isDense());
153                 assertFalse(am.toDense().isSparse());
154                 assertTrue(am.toSparse().isSparse());
155                 assertFalse(am.toSparse().isDense());
156 
157                 // EQUALS
158                 assertEquals(am, am);
159                 assertNotEquals(am, new Object());
160                 assertNotEquals(am, null);
161                 assertNotEquals(am, DoubleMatrix.instantiate(
162                         DoubleMatrixData.instantiate(testData, LengthUnit.METER.getScale(), storageType), LengthUnit.METER));
163                 assertNotEquals(am, am.divide(2.0d));
164 
165                 // MUTABLE
166                 assertFalse(am.isMutable());
167                 AreaMatrix ammut = am.mutable();
168                 assertTrue(ammut.isMutable());
169                 assertFalse(am.isMutable());
170                 AreaMatrix ammut2 = ammut.multiplyBy(1.0);
171                 assertEquals(am, ammut2);
172                 assertTrue(ammut.isMutable());
173                 assertFalse(am.isMutable());
174                 assertTrue(ammut2.isMutable());
175                 ammut2 = ammut2.mutable().divideBy(2.0);
176                 assertEquals(am, ammut);
177                 assertNotEquals(am, ammut2);
178                 AreaMatrix ammut3 = ammut2.mutable().divideBy(0.0);
179                 for (int row = 0; row < ammut3.rows(); row++)
180                 {
181                     for (int col = 0; col < ammut3.cols(); col++)
182                     {
183                         if (ammut2.getSI(row, col) == 0)
184                         {
185                             assertTrue("Value should be NaN", Double.isNaN(ammut3.getSI(row, col)));
186 
187                         }
188                         else
189                         {
190                             assertTrue("Value should be Infinite", Double.isInfinite(ammut3.getSI(row, col)));
191                         }
192                     }
193                 }
194 
195                 // ZSUM and CARDINALITY
196                 Area zSum = am.zSum();
197                 double sum = 0;
198                 int card = 0;
199                 for (int row = 0; row < testData.length; row++)
200                 {
201                     for (int col = 0; col < testData[0].length; col++)
202                     {
203                         sum += testData[row][col];
204                         card += testData[row][col] == 0.0d ? 0 : 1;
205                     }
206                 }
207                 assertEquals("zSum", sum, zSum.getInUnit(), 0.1);
208                 assertEquals("cardinality", card, am.cardinality());
209                 AreaMatrix ammutZero = ammut.multiplyBy(0.0);
210                 assertEquals("cardinality should be 0", 0, ammutZero.cardinality());
211                 assertEquals("zSum should be 0", 0.0, ammutZero.zSum().getSI(), 0);
212 
213                 // INCREMENTBY(SCALAR) and DECREMENTBY(SCALAR)
214                 AreaMatrix amold = am.clone();
215                 Area fa = Area.of(10.0d, "m^2");
216                 AreaMatrix aminc = am.mutable().incrementBy(fa).immutable();
217                 AreaMatrix amdec = am.mutable().decrementBy(fa).immutable();
218                 AreaMatrix amid = aminc.mutable().decrementBy(fa);
219                 assertEquals("immutable matrix should not change when converted to mutable", am, amold);
220                 for (int row = 0; row < testData.length; row++)
221                 {
222                     for (int col = 0; col < testData[0].length; col++)
223                     {
224                         assertEquals("increment and decrement with scalar should result in same matrix", am.getSI(row, col),
225                                 amid.getSI(row, col), 0.1);
226                         assertEquals("m + s = (m+s)", au.getScale().toStandardUnit(testData[row][col]) + 10.0,
227                                 aminc.getSI(row, col), 0.1);
228                         assertEquals("m - s = (m-s)", au.getScale().toStandardUnit(testData[row][col]) - 10.0,
229                                 amdec.getSI(row, col), 0.1);
230                     }
231                 }
232 
233                 // MULTIPLYBY() and DIVIDEBY(), TIMES(), DIVIDE()
234                 AreaMatrix amt5 = am.mutable().multiplyBy(5.0d).immutable();
235                 AreaMatrix amd5 = am.mutable().divideBy(5.0d).immutable();
236                 AreaMatrix amtd = amt5.mutable().divideBy(5.0d);
237                 AreaMatrix amtimD = am.times(5.0d);
238                 AreaMatrix amtimF = am.times(5.0f);
239                 AreaMatrix amdivD = am.divide(5.0d);
240                 AreaMatrix amdivF = am.divide(5.0f);
241                 for (int row = 0; row < testData.length; row++)
242                 {
243                     for (int col = 0; col < testData[0].length; col++)
244                     {
245                         assertEquals("times followed by divide with constant should result in same matrix", am.getSI(row, col),
246                                 amtd.getSI(row, col), 0.1);
247                         assertEquals("m * 5.0 = (m*5.0)", au.getScale().toStandardUnit(testData[row][col]) * 5.0d,
248                                 amt5.getSI(row, col), 0.1);
249                         assertEquals("m / 5.0 = (m/5.0)", au.getScale().toStandardUnit(testData[row][col]) / 5.0d,
250                                 amd5.getSI(row, col), 0.1);
251                         assertEquals("amtimD", amt5.getSI(row, col), amtimD.getSI(row, col), 0.1d);
252                         assertEquals("amtimF", amt5.getSI(row, col), amtimF.getSI(row, col), 0.1d);
253                         assertEquals("amdivD", amd5.getSI(row, col), amdivD.getSI(row, col), 0.01d);
254                         assertEquals("amdivD", amd5.getSI(row, col), amdivF.getSI(row, col), 0.01d);
255                     }
256                 }
257 
258                 // GET(), GETINUNIT()
259                 assertEquals("get()", new Area(testData[2][2], au), am.get(2, 2));
260                 assertEquals("getSI()", au.getScale().toStandardUnit(testData[2][2]), am.getSI(2, 2), 0.1);
261                 assertEquals("getInUnit()", testData[2][2], am.getInUnit(2, 2), 0.1);
262                 assertEquals("getInUnit(unit)",
263                         AreaUnit.SQUARE_YARD.getScale().fromStandardUnit(au.getScale().toStandardUnit(testData[2][2])),
264                         am.getInUnit(2, 2, AreaUnit.SQUARE_YARD), 0.1);
265 
266                 // SET(), SETINUNIT()
267                 Area fasqft = new Area(10.5d, AreaUnit.SQUARE_FOOT);
268                 AreaMatrix famChange = am.clone().mutable();
269                 famChange.set(2, 2, fasqft);
270                 assertEquals("set()", fasqft.si, famChange.get(2, 2).si, 0.1d);
271                 famChange = am.clone().mutable();
272                 famChange.setSI(2, 2, 123.4d);
273                 assertEquals("setSI()", 123.4d, famChange.get(2, 2).si, 0.1d);
274                 famChange = am.clone().mutable();
275                 famChange.setInUnit(2, 2, 1.2d);
276                 assertEquals("setInUnit()", 1.2d, famChange.getInUnit(2, 2), 0.1d);
277                 famChange = am.clone().mutable();
278                 famChange.setInUnit(2, 2, 1.5d, AreaUnit.HECTARE);
279                 assertEquals("setInUnit(unit)", 15000.0d, famChange.get(2, 2).si, 1.0d);
280 
281                 // GETROW(), GETCOLUMN(), GETDIAGONAL
282                 double[][] squareData = storageType.equals(StorageType.DENSE) ? DOUBLEMATRIX.denseRectArrays(12, 12)
283                         : DOUBLEMATRIX.sparseRectArrays(12, 12);
284                 AreaMatrix amSquare =
285                         DoubleMatrix.instantiate(DoubleMatrixData.instantiate(squareData, au.getScale(), storageType), au);
286                 double[] row2si = am.getRowSI(2);
287                 double[] col2si = am.getColumnSI(2);
288                 double[] diagsi = amSquare.getDiagonalSI();
289                 AreaVector row2v = am.getRow(2);
290                 AreaVector col2v = am.getColumn(2);
291                 AreaVector diagv = amSquare.getDiagonal();
292                 Area[] row2scalar = am.getRowScalars(2);
293                 Area[] col2scalar = am.getColumnScalars(2);
294                 Area[] diagscalar = amSquare.getDiagonalScalars();
295                 for (int col = 0; col < testData[0].length; col++)
296                 {
297                     assertEquals("row2si", au.getScale().toStandardUnit(testData[2][col]), row2si[col], 0.1d);
298                     assertEquals("row2v", au.getScale().toStandardUnit(testData[2][col]), row2v.getSI(col), 0.1d);
299                     assertEquals("row2scalar", au.getScale().toStandardUnit(testData[2][col]), row2scalar[col].si, 0.1d);
300                 }
301                 for (int row = 0; row < testData.length; row++)
302                 {
303                     assertEquals("col2si", au.getScale().toStandardUnit(testData[row][2]), col2si[row], 0.1d);
304                     assertEquals("col2v", au.getScale().toStandardUnit(testData[row][2]), col2v.getSI(row), 0.1d);
305                     assertEquals("col2scalar", au.getScale().toStandardUnit(testData[row][2]), col2scalar[row].si, 0.1d);
306                 }
307                 for (int diag = 0; diag < amSquare.rows(); diag++)
308                 {
309                     assertEquals("diag2si", au.getScale().toStandardUnit(squareData[diag][diag]), diagsi[diag], 0.1d);
310                     assertEquals("diag2v", au.getScale().toStandardUnit(squareData[diag][diag]), diagv.getSI(diag), 0.1d);
311                     assertEquals("diag2scalar", au.getScale().toStandardUnit(squareData[diag][diag]), diagscalar[diag].si,
312                             0.1d);
313                 }
314 
315                 // GETVALUES(), GETSCALARS()
316                 double[][] valsi = am.getValuesSI();
317                 double[][] valunit = am.getValuesInUnit();
318                 double[][] valsqft = am.getValuesInUnit(AreaUnit.SQUARE_YARD);
319                 Area[][] valscalars = am.getScalars();
320                 for (int row = 0; row < testData.length; row++)
321                 {
322                     for (int col = 0; col < testData[0].length; col++)
323                     {
324                         assertEquals("getValuesSI()", au.getScale().toStandardUnit(testData[row][col]), valsi[row][col], 0.1);
325                         assertEquals("getValuesInUnit()", testData[row][col], valunit[row][col], 0.1);
326                         assertEquals("getValuesInUnit(unit)", AreaUnit.SQUARE_YARD.getScale()
327                                 .fromStandardUnit(au.getScale().toStandardUnit(testData[row][col])), valsqft[row][col], 0.1);
328                         assertEquals("getValuesInUnit(unit)", au.getScale().toStandardUnit(testData[row][col]),
329                                 valscalars[row][col].si, 0.1);
330                     }
331                 }
332 
333                 // ASSIGN FUNCTION ABS, CEIL, FLOOR, NEG, RINT
334                 AreaMatrix amdiv2 = am.divide(2.0d);
335                 assertEquals(am.getStorageType(), amdiv2.getStorageType());
336                 assertEquals(am.getDisplayUnit(), amdiv2.getDisplayUnit());
337                 AreaMatrix amAbs = amdiv2.mutable().abs().immutable();
338                 assertEquals(am.getStorageType(), amAbs.getStorageType());
339                 assertEquals(am.getDisplayUnit(), amAbs.getDisplayUnit());
340                 AreaMatrix amCeil = amdiv2.mutable().ceil().immutable();
341                 assertEquals(am.getStorageType(), amCeil.getStorageType());
342                 assertEquals(am.getDisplayUnit(), amCeil.getDisplayUnit());
343                 AreaMatrix amFloor = amdiv2.mutable().floor().immutable();
344                 assertEquals(am.getStorageType(), amFloor.getStorageType());
345                 assertEquals(am.getDisplayUnit(), amFloor.getDisplayUnit());
346                 AreaMatrix amNeg = amdiv2.mutable().neg().immutable();
347                 assertEquals(am.getStorageType(), amNeg.getStorageType());
348                 assertEquals(am.getDisplayUnit(), amNeg.getDisplayUnit());
349                 AreaMatrix amRint = amdiv2.mutable().rint().immutable();
350                 assertEquals(am.getStorageType(), amRint.getStorageType());
351                 assertEquals(am.getDisplayUnit(), amRint.getDisplayUnit());
352                 for (int row = 0; row < testData.length; row++)
353                 {
354                     for (int col = 0; col < testData[0].length; col++)
355                     {
356                         // TODO: Should be rounded IN THE UNIT rather than BY SI VALUES
357                         assertEquals("div2", au.getScale().toStandardUnit(testData[row][col]) / 2.0d, amdiv2.getSI(row, col),
358                                 0.1d);
359                         assertEquals("abs", Math.abs(au.getScale().toStandardUnit(testData[row][col]) / 2.0d),
360                                 amAbs.getSI(row, col), 0.1d);
361                         assertEquals("ceil", Math.ceil(au.getScale().toStandardUnit(testData[row][col]) / 2.0d),
362                                 amCeil.getSI(row, col), 0.1d);
363                         assertEquals("floor", Math.floor(au.getScale().toStandardUnit(testData[row][col]) / 2.0d),
364                                 amFloor.getSI(row, col), 0.1d);
365                         assertEquals("neg", -au.getScale().toStandardUnit(testData[row][col]) / 2.0d, amNeg.getSI(row, col),
366                                 0.1d);
367                         assertEquals("rint", Math.rint(au.getScale().toStandardUnit(testData[row][col]) / 2.0d),
368                                 amRint.getSI(row, col), 0.1d);
369                     }
370                 }
371 
372                 double[][] testData4x4 =
373                         new double[][] { { 2, 3, 5, 7 }, { 11, 13, 17, 19 }, { 23, 29, 31, 37 }, { 41, 43, 47, 49 } };
374                 AreaMatrix am4x4 =
375                         DoubleMatrix.instantiate(DoubleMatrixData.instantiate(testData4x4, au.getScale(), storageType), au);
376                 double det = am4x4.determinant();
377                 double detCalc = Determinant.det(am4x4.getValuesSI());
378                 double err = Math.max(det, detCalc) / 10000.0;
379                 assertEquals("Determinant of square matrix with unit " + au.getDefaultTextualAbbreviation() + ", storage = "
380                         + storageType + " = " + det + " but should have been " + detCalc, detCalc, det, err);
381                 new Try()
382                 {
383                     @Override
384                     public void execute()
385                     {
386                         double detErr = am.determinant();
387                         System.out.println(detErr);
388                     }
389                 }.test("Determinant of non-square matrix should have thrown exception");
390 
391                 // TEST METHODS THAT INVOLVE TWO MATRIX INSTANCES
392 
393                 for (StorageType storageType2 : new StorageType[] { StorageType.DENSE, StorageType.SPARSE })
394                 {
395                     double[][] testData2 = storageType2.equals(StorageType.DENSE) ? denseTestData : reverseSparseTestData;
396                     for (AreaUnit au2 : new AreaUnit[] { AreaUnit.SQUARE_METER, AreaUnit.ACRE })
397                     {
398 
399                         // PLUS and INCREMENTBY(MATRIX)
400                         AreaMatrix am2 = DoubleMatrix
401                                 .instantiate(DoubleMatrixData.instantiate(testData2, au2.getScale(), storageType2), au2);
402                         AreaMatrix amSum1 = am.plus(am2);
403                         AreaMatrix amSum2 = am2.plus(am);
404                         AreaMatrix amSum3 = am.mutable().incrementBy(am2).immutable();
405                         AreaMatrix amSum4 = am2.mutable().incrementBy(am).immutable();
406                         assertEquals("a+b == b+a", amSum1, amSum2);
407                         assertEquals("a+b == b+a", amSum1, amSum3);
408                         assertEquals("a+b == b+a", amSum1, amSum4);
409                         for (int row = 0; row < testData.length; row++)
410                         {
411                             for (int col = 0; col < testData[0].length; col++)
412                             {
413                                 double tolerance = Double.isFinite(amSum1.getSI(row, col))
414                                         ? Math.abs(amSum1.getSI(row, col) / 10000.0d) : 0.1d;
415                                 assertEquals("value in matrix matches",
416                                         au.getScale().toStandardUnit(testData[row][col])
417                                                 + au2.getScale().toStandardUnit(testData2[row][col]),
418                                         amSum1.getSI(row, col), tolerance);
419                             }
420                         }
421 
422                         // MINUS and DECREMENTBY(MATRIX)
423                         AreaMatrix amDiff1 = am.minus(am2);
424                         AreaMatrix amDiff2 = am2.minus(am).mutable().neg();
425                         AreaMatrix amDiff3 = am.mutable().decrementBy(am2).immutable();
426                         assertEquals("a-b == -(b-a)", amDiff1, amDiff2);
427                         assertEquals("a-b == -(b-a)", amDiff1, amDiff3);
428                         for (int row = 0; row < testData.length; row++)
429                         {
430                             for (int col = 0; col < testData[0].length; col++)
431                             {
432                                 double tolerance = Double.isFinite(amDiff1.getSI(row, col))
433                                         ? Math.abs(amDiff1.getSI(row, col) / 10000.0d) : 0.1d;
434                                 assertEquals("value in matrix matches",
435                                         au.getScale().toStandardUnit(testData[row][col])
436                                                 - au2.getScale().toStandardUnit(testData2[row][col]),
437                                         amDiff1.getSI(row, col), tolerance);
438                             }
439                         }
440 
441                         // TIMES(MATRIX) and DIVIDE(MATRIX)
442                         SIMatrix amTim = am.times(am2);
443                         SIMatrix amDiv = am.divide(am2);
444                         assertEquals("unit of m2 * m2 should be m4", "m4",
445                                 amTim.getDisplayUnit().getQuantity().getSiDimensions().toString(false, false, false));
446                         assertEquals("unit of m2 / m2 should be 1", "1",
447                                 amDiv.getDisplayUnit().getQuantity().getSiDimensions().toString(false, false, false));
448                         for (int row = 0; row < testData.length; row++)
449                         {
450                             for (int col = 0; col < testData[0].length; col++)
451                             {
452                                 double tolerance = Double.isFinite(amTim.getSI(row, col))
453                                         ? Math.abs(amTim.getSI(row, col) / 10000.0d) : 0.1d;
454                                 if (Math.abs(au.getScale().toStandardUnit(testData[row][col])
455                                         * au2.getScale().toStandardUnit(testData2[row][col])
456                                         - amTim.getSI(row, col)) > tolerance)
457                                 {
458                                     System.out.println(
459                                             "mismatch at row " + row + ", col " + col + ", got " + amTim.getSI(row, col)
460                                                     + ", expected " + au.getScale().toStandardUnit(testData[row][col])
461                                                             * au2.getScale().toStandardUnit(testData2[row][col]));
462                                     am.times(am2);
463                                 }
464                                 assertEquals("value in m2 * m2 matches",
465                                         au.getScale().toStandardUnit(testData[row][col])
466                                                 * au2.getScale().toStandardUnit(testData2[row][col]),
467                                         amTim.getSI(row, col), tolerance);
468                                 tolerance = Double.isFinite(amTim.getSI(row, col)) ? Math.abs(amDiv.getSI(row, col) / 10000.0d)
469                                         : 0.1d;
470                                 assertEquals("value in m2 / m2 matches (could be NaN)",
471                                         au.getScale().toStandardUnit(testData[row][col])
472                                                 / au2.getScale().toStandardUnit(testData2[row][col]),
473                                         amDiv.getSI(row, col), tolerance);
474                             }
475                         }
476                     }
477                 }
478             }
479         }
480     }
481 
482     /**
483      * Test if mutable methods give an error in case the matrix is immutable.
484      */
485     @Test
486     public void testImmutableMatrix()
487     {
488         double[][] denseTestData = DOUBLEMATRIX.denseRectArrays(5, 10);
489         double[][] sparseTestData = DOUBLEMATRIX.sparseRectArrays(5, 10);
490 
491         for (StorageType storageType : new StorageType[] { StorageType.DENSE, StorageType.SPARSE })
492         {
493             for (AreaUnit au : new AreaUnit[] { AreaUnit.SQUARE_METER, AreaUnit.ACRE })
494             {
495                 double[][] testData = storageType.equals(StorageType.DENSE) ? denseTestData : sparseTestData;
496                 AreaMatrix am =
497                         DoubleMatrix.instantiate(DoubleMatrixData.instantiate(testData, au.getScale(), storageType), au);
498                 am = am.immutable();
499                 final AreaMatrix amPtr = am;
500                 Area fa = Area.of(10.0d, "m^2");
501                 new Try()
502                 {
503                     @Override
504                     public void execute()
505                     {
506                         amPtr.assign(DoubleMathFunctions.ABS);
507                     }
508                 }.test("ImmutableMatrix.assign(...) should throw error");
509                 new Try()
510                 {
511                     @Override
512                     public void execute()
513                     {
514                         amPtr.decrementBy(fa);
515                     }
516                 }.test("ImmutableMatrix.decrementBy(scalar) should throw error");
517                 new Try()
518                 {
519                     @Override
520                     public void execute()
521                     {
522                         amPtr.decrementBy(amPtr);
523                     }
524                 }.test("ImmutableMatrix.decrementBy(matrix) should throw error");
525                 new Try()
526                 {
527                     @Override
528                     public void execute()
529                     {
530                         amPtr.incrementBy(fa);
531                     }
532                 }.test("ImmutableMatrix.incrementBy(scalar) should throw error");
533                 new Try()
534                 {
535                     @Override
536                     public void execute()
537                     {
538                         amPtr.incrementBy(amPtr);
539                     }
540                 }.test("ImmutableMatrix.incrementBy(matrix) should throw error");
541                 new Try()
542                 {
543                     @Override
544                     public void execute()
545                     {
546                         amPtr.divideBy(2.0d);
547                     }
548                 }.test("ImmutableMatrix.divideBy(factor) should throw error");
549                 new Try()
550                 {
551                     @Override
552                     public void execute()
553                     {
554                         amPtr.multiplyBy(2.0d);
555                     }
556                 }.test("ImmutableMatrix.multiplyBy(factor) should throw error");
557                 new Try()
558                 {
559                     @Override
560                     public void execute()
561                     {
562                         amPtr.set(1, 1, fa);
563                     }
564                 }.test("ImmutableMatrix.set() should throw error");
565                 new Try()
566                 {
567                     @Override
568                     public void execute()
569                     {
570                         amPtr.setSI(1, 1, 20.1d);
571                     }
572                 }.test("ImmutableMatrix.setSI() should throw error");
573                 new Try()
574                 {
575                     @Override
576                     public void execute()
577                     {
578                         amPtr.setInUnit(1, 1, 15.2d);
579                     }
580                 }.test("ImmutableMatrix.setInUnit(f) should throw error");
581                 new Try()
582                 {
583                     @Override
584                     public void execute()
585                     {
586                         amPtr.setInUnit(1, 1, 15.2d, AreaUnit.ARE);
587                     }
588                 }.test("ImmutableMatrix.setInUnit(f, u) should throw error");
589                 new Try()
590                 {
591                     @Override
592                     public void execute()
593                     {
594                         amPtr.abs();
595                     }
596                 }.test("ImmutableMatrix.abs() should throw error");
597                 new Try()
598                 {
599                     @Override
600                     public void execute()
601                     {
602                         amPtr.ceil();
603                     }
604                 }.test("ImmutableMatrix.ceil() should throw error");
605                 new Try()
606                 {
607                     @Override
608                     public void execute()
609                     {
610                         amPtr.floor();
611                     }
612                 }.test("ImmutableMatrix.floor() should throw error");
613                 new Try()
614                 {
615                     @Override
616                     public void execute()
617                     {
618                         amPtr.neg();
619                     }
620                 }.test("ImmutableMatrix.neg() should throw error");
621                 new Try()
622                 {
623                     @Override
624                     public void execute()
625                     {
626                         amPtr.rint();
627                     }
628                 }.test("ImmutableMatrix.rint() should throw error");
629             }
630         }
631     }
632 
633     /**
634      * Test toString() methods. TODO: expand?
635      */
636     @Test
637     public void testMatrixToString()
638     {
639         double[][] denseTestData = DOUBLEMATRIX.denseRectArrays(5, 10);
640         double[][] sparseTestData = DOUBLEMATRIX.sparseRectArrays(5, 10);
641 
642         for (StorageType storageType : new StorageType[] { StorageType.DENSE, StorageType.SPARSE })
643         {
644             for (AreaUnit au : new AreaUnit[] { AreaUnit.SQUARE_METER, AreaUnit.ACRE })
645             {
646                 double[][] testData = storageType.equals(StorageType.DENSE) ? denseTestData : sparseTestData;
647                 AreaMatrix am =
648                         DoubleMatrix.instantiate(DoubleMatrixData.instantiate(testData, au.getScale(), storageType), au);
649                 String s1 = am.toString(); // non-verbose with unit
650                 assertTrue(s1.contains(au.getDefaultTextualAbbreviation()));
651                 String s2 = am.toString(AreaUnit.SQUARE_INCH); // non-verbose with unit
652                 assertTrue(s2.contains(AreaUnit.SQUARE_INCH.getDefaultTextualAbbreviation()));
653                 String s3 = am.toString(AreaUnit.SQUARE_INCH, true, true); // verbose with unit
654                 assertTrue(s3.contains(AreaUnit.SQUARE_INCH.getDefaultTextualAbbreviation()));
655                 if (storageType.equals(StorageType.DENSE))
656                 {
657                     assertTrue(s3.contains("Dense"));
658                     assertFalse(s3.contains("Sparse"));
659                 }
660                 else
661                 {
662                     assertFalse(s3.contains("Dense"));
663                     assertTrue(s3.contains("Sparse"));
664                 }
665                 assertTrue(s3.contains("Rel"));
666                 assertFalse(s3.contains("Abs"));
667                 assertTrue(s3.contains("Immutable"));
668                 assertFalse(s3.contains("Mutable"));
669                 AreaMatrix ammut = am.mutable();
670                 String smut = ammut.toString(AreaUnit.SQUARE_INCH, true, true); // verbose with unit
671                 assertFalse(smut.contains("Immutable"));
672                 assertTrue(smut.contains("Mutable"));
673                 String sNotVerbose = ammut.toString(false, false);
674                 assertFalse(sNotVerbose.contains("Rel"));
675                 assertFalse(sNotVerbose.contains("Abs"));
676                 assertFalse(sNotVerbose.contains("Immutable"));
677                 assertFalse(sNotVerbose.contains("Mutable"));
678                 assertFalse(sNotVerbose.contains(au.getDefaultTextualAbbreviation()));
679             }
680         }
681         TimeMatrix tm = DoubleMatrix.instantiate(
682                 DoubleMatrixData.instantiate(denseTestData, TimeUnit.DEFAULT.getScale(), StorageType.DENSE), TimeUnit.DEFAULT);
683         String st = tm.toString(TimeUnit.DEFAULT, true, true); // verbose with unit
684         assertFalse(st.contains("Rel"));
685         assertTrue(st.contains("Abs"));
686         LengthMatrix lm = DoubleMatrix.instantiate(
687                 DoubleMatrixData.instantiate(denseTestData, LengthUnit.SI.getScale(), StorageType.DENSE), LengthUnit.SI);
688         String sl = lm.toString(LengthUnit.SI, true, true); // verbose with unit
689         assertTrue(sl.contains("Rel"));
690         assertFalse(sl.contains("Abs"));
691     }
692 
693     /**
694      * Test the extra methods that Absolute and Relative with Absolute matrices implement.
695      */
696     @Test
697     public void testSpecialMatrixMethodsRelWithAbs()
698     {
699         double[][] denseTestData = DOUBLEMATRIX.denseRectArrays(5, 10);
700         TimeMatrix tm = DoubleMatrix.instantiate(
701                 DoubleMatrixData.instantiate(denseTestData, TimeUnit.DEFAULT.getScale(), StorageType.DENSE), TimeUnit.DEFAULT);
702         DurationMatrix dm = DoubleMatrix.instantiate(
703                 DoubleMatrixData.instantiate(denseTestData, DurationUnit.MINUTE.getScale(), StorageType.DENSE),
704                 DurationUnit.SECOND);
705         assertTrue(tm.isAbsolute());
706         assertFalse(dm.isAbsolute());
707         assertFalse(tm.isRelative());
708         assertTrue(dm.isRelative());
709 
710         TimeMatrix absPlusRel = tm.plus(dm);
711         TimeMatrix absMinusRel = tm.minus(dm);
712         double[][] halfDenseData = DOUBLEMATRIX.denseRectArrays(5, 10);
713         for (int row = 0; row < halfDenseData.length; row++)
714         {
715             for (int col = 0; col < halfDenseData[row].length; col++)
716             {
717                 halfDenseData[row][col] *= 0.5;
718             }
719         }
720         TimeMatrix halfTimeMatrix = DoubleMatrix.instantiate(
721                 DoubleMatrixData.instantiate(halfDenseData, TimeUnit.DEFAULT.getScale(), StorageType.DENSE), TimeUnit.DEFAULT);
722         DurationMatrix absMinusAbs = tm.minus(halfTimeMatrix);
723         TimeMatrix absDecByRelS = tm.mutable().decrementBy(Duration.of(1.0d, "min"));
724         TimeMatrix absDecByRelM = tm.mutable().decrementBy(dm.divide(2.0d));
725         TimeMatrix relPlusAbs = dm.plus(tm);
726         for (int row = 0; row < denseTestData.length; row++)
727         {
728             for (int col = 0; col < denseTestData[0].length; col++)
729             {
730                 assertEquals("absPlusRel", 61.0 * denseTestData[row][col], absPlusRel.getSI(row, col), 0.01);
731                 assertEquals("absMinusRel", -59.0 * denseTestData[row][col], absMinusRel.getSI(row, col), 0.01);
732                 assertEquals("absMinusAbs", denseTestData[row][col] / 2.0, absMinusAbs.getSI(row, col), 0.01);
733                 assertEquals("absDecByRelS", denseTestData[row][col] - 60.0, absDecByRelS.getSI(row, col), 0.01);
734                 assertEquals("absDecByRelM", -29.0 * denseTestData[row][col], absDecByRelM.getSI(row, col), 0.01);
735                 assertEquals("relPlusAbs", 61.0 * denseTestData[row][col], relPlusAbs.getSI(row, col), 0.01);
736             }
737         }
738         for (int dRows : new int[] { -1, 0, 1 })
739         {
740             for (int dCols : new int[] { -1, 0, 1 })
741             {
742                 if (dRows == 0 && dCols == 0)
743                 {
744                     continue;
745                 }
746                 double[][] other = DOUBLEMATRIX.denseRectArrays(denseTestData.length + dRows, denseTestData[0].length + dCols);
747                 TimeMatrix wrongTimeMatrix = DoubleMatrix.instantiate(
748                         DoubleMatrixData.instantiate(other, TimeUnit.DEFAULT.getScale(), StorageType.DENSE), TimeUnit.DEFAULT);
749                 try
750                 {
751                     tm.mutable().minus(wrongTimeMatrix);
752                     fail("Mismatching size should have thrown a ValueRuntimeException");
753                 }
754                 catch (ValueRuntimeException vre)
755                 {
756                     // Ignore expected exception
757                 }
758             }
759         }
760         assertTrue("toString returns something informative",
761                 DoubleMatrixData.instantiate(denseTestData, TimeUnit.DEFAULT.getScale(), StorageType.DENSE).toString()
762                         .startsWith("DoubleMatrixData"));
763     }
764 
765     /**
766      * Execute a mats++-like memory test on a sparse matrix. See
767      * <a href="http://www.eng.auburn.edu/~agrawvd/COURSE/E7250_05/REPORTS_TERM/Raghuraman_Mem.doc">Memory Test</a>.
768      */
769     @Test
770     public void memoryTest()
771     {
772         FloatAreaMatrix am = FloatMatrix.instantiate(new float[5][10], AreaUnit.SI, StorageType.SPARSE);
773         am = am.mutable();
774         float nonZeroValue = 123.456f;
775         // Initially the array is filled with zero values; we can skip the initialization phase
776         for (int compoundIndex = 0; compoundIndex < am.cols() * am.rows(); compoundIndex++)
777         {
778             // Let the row count fastest
779             int row = compoundIndex % am.rows();
780             int col = compoundIndex / am.rows();
781             assertEquals("initial value is 0", 0f, am.getSI(row, col), 0.0001);
782             am.setSI(row, col, nonZeroValue);
783             assertEquals("current value is nonZero", nonZeroValue, am.getSI(row, col), 0.0001);
784         }
785         for (int compoundIndex = am.cols() * am.rows(); --compoundIndex >= 0;)
786         {
787             // Let the row count fastest
788             int row = compoundIndex % am.rows();
789             int col = compoundIndex / am.rows();
790             assertEquals("current value is nonZero", nonZeroValue, am.getSI(row, col), 0.0001);
791             am.setSI(row, col, 0f);
792             assertEquals("final value is 0", 0f, am.getSI(row, col), 0.0001);
793         }
794     }
795 
796     /**
797      * Test the instantiateAbs method and instantiateScalarAbsSI method.
798      */
799     @Test
800     public void testInstantiateAbs()
801     {
802         double[][] denseTestData = DOUBLEMATRIX.denseRectArrays(10, 20);
803         TimeMatrix timeMatrix = DoubleMatrix.instantiate(
804                 DoubleMatrixData.instantiate(denseTestData, TimeUnit.DEFAULT.getScale(), StorageType.DENSE), TimeUnit.DEFAULT);
805         DurationMatrix durationMatrix = DoubleMatrix.instantiate(
806                 DoubleMatrixData.instantiate(denseTestData, DurationUnit.MINUTE.getScale(), StorageType.DENSE),
807                 DurationUnit.SECOND);
808 
809         float[] halfDenseData = FLOATVECTOR.denseArray(105);
810         for (int index = 0; index < halfDenseData.length; index++)
811         {
812             halfDenseData[index] *= 0.5;
813         }
814         TimeMatrix relPlusAbsTime = durationMatrix.plus(timeMatrix);
815         for (int row = 0; row < denseTestData.length; row++)
816         {
817             for (int col = 0; col < denseTestData[0].length; col++)
818             {
819                 assertEquals("relPlusAbsTime", 61.0 * denseTestData[row][col], relPlusAbsTime.getSI(row, col), 0.01);
820             }
821         }
822         Time time = durationMatrix.instantiateScalarAbsSI(123.456f, TimeUnit.EPOCH_DAY);
823         assertEquals("Unit of instantiateScalarAbsSI matches", TimeUnit.EPOCH_DAY, time.getDisplayUnit());
824         assertEquals("Value of instantiateScalarAbsSI matches", 123.456f, time.si, 0.1);
825 
826         AngleMatrix angleMatrix = DoubleMatrix.instantiate(
827                 DoubleMatrixData.instantiate(denseTestData, AngleUnit.DEGREE.getScale(), StorageType.DENSE), AngleUnit.DEGREE);
828         DirectionMatrix directionMatrix = DoubleMatrix.instantiate(
829                 DoubleMatrixData.instantiate(denseTestData, DirectionUnit.EAST_DEGREE.getScale(), StorageType.DENSE),
830                 DirectionUnit.EAST_DEGREE);
831 
832         DirectionMatrix relPlusAbsDirection = angleMatrix.plus(directionMatrix);
833         for (int row = 0; row < denseTestData.length; row++)
834         {
835             for (int col = 0; col < denseTestData[0].length; col++)
836             {
837                 assertEquals("relPlusAbsTime", 2.0 / 180 * Math.PI * denseTestData[row][col],
838                         relPlusAbsDirection.getSI(row, col), 0.01);
839             }
840         }
841         Direction direction = angleMatrix.instantiateScalarAbsSI(123.456f, DirectionUnit.NORTH_RADIAN);
842         assertEquals("Unit of instantiateScalarAbsSI matches", DirectionUnit.NORTH_RADIAN, direction.getDisplayUnit());
843         assertEquals("Value of instantiateScalarAbsSI matches", 123.456f, direction.si, 0.1);
844 
845         TemperatureMatrix temperatureMatrix = DoubleMatrix.instantiate(
846                 DoubleMatrixData.instantiate(denseTestData, TemperatureUnit.DEGREE_FAHRENHEIT.getScale(), StorageType.DENSE),
847                 TemperatureUnit.DEGREE_FAHRENHEIT);
848         AbsoluteTemperatureMatrix absoluteTemperatureMatrix = DoubleMatrix.instantiate(
849                 DoubleMatrixData.instantiate(denseTestData, AbsoluteTemperatureUnit.KELVIN.getScale(), StorageType.DENSE),
850                 AbsoluteTemperatureUnit.KELVIN);
851 
852         AbsoluteTemperatureMatrix relPlusAbsTemperature = temperatureMatrix.plus(absoluteTemperatureMatrix);
853         for (int row = 0; row < denseTestData.length; row++)
854         {
855             for (int col = 0; col < denseTestData[0].length; col++)
856             {
857                 assertEquals("relPlusAbsTime", (1.0 + 5.0 / 9.0) * denseTestData[row][col],
858                         relPlusAbsTemperature.getSI(row, col), 0.01);
859             }
860         }
861         AbsoluteTemperature absoluteTemperature =
862                 temperatureMatrix.instantiateScalarAbsSI(123.456f, AbsoluteTemperatureUnit.DEGREE_FAHRENHEIT);
863         assertEquals("Unit of instantiateScalarAbsSI matches", AbsoluteTemperatureUnit.DEGREE_FAHRENHEIT,
864                 absoluteTemperature.getDisplayUnit());
865         assertEquals("Value of instantiateScalarAbsSI matches", 123.456f, absoluteTemperature.si, 0.1);
866 
867         LengthMatrix lengthMatrix = DoubleMatrix.instantiate(
868                 DoubleMatrixData.instantiate(denseTestData, LengthUnit.MILE.getScale(), StorageType.DENSE), LengthUnit.MILE);
869         PositionMatrix positionMatrix = DoubleMatrix.instantiate(
870                 DoubleMatrixData.instantiate(denseTestData, PositionUnit.KILOMETER.getScale(), StorageType.DENSE),
871                 PositionUnit.KILOMETER);
872 
873         PositionMatrix relPlusAbsPosition = lengthMatrix.plus(positionMatrix);
874         for (int row = 0; row < denseTestData.length; row++)
875         {
876             for (int col = 0; col < denseTestData[0].length; col++)
877             {
878                 assertEquals("relPlusAbsTime", 2609.344 * denseTestData[row][col], relPlusAbsPosition.getSI(row, col), 0.1);
879             }
880         }
881         Position position = lengthMatrix.instantiateScalarAbsSI(123.456f, PositionUnit.ANGSTROM);
882         assertEquals("Unit of instantiateScalarAbsSI matches", PositionUnit.ANGSTROM, position.getDisplayUnit());
883         assertEquals("Value of instantiateScalarAbsSI matches", 123.456f, position.si, 0.01);
884     }
885 
886     /**
887      * Test the <code>as</code> method of the SIMatrix class.
888      * @throws SecurityException on error
889      * @throws NoSuchMethodException on error
890      * @throws InvocationTargetException on error
891      * @throws IllegalArgumentException on error
892      * @throws IllegalAccessException on error
893      * @throws ClassNotFoundException on error
894      * @throws UnitException on error
895      * @param <U> the unit type
896      */
897     @SuppressWarnings("unchecked")
898     @Test
899     public <U extends Unit<U>> void testAsUnit() throws ClassNotFoundException, NoSuchMethodException, SecurityException,
900             IllegalAccessException, IllegalArgumentException, InvocationTargetException, UnitException
901     {
902         double[][] testValues = DOUBLEMATRIX.denseRectArrays(10, 20);
903         for (StorageType storageType : new StorageType[] { StorageType.DENSE, StorageType.SPARSE })
904         {
905             for (String type : CLASSNAMES.REL_LIST)
906             {
907                 Class.forName("org.djunits.unit." + type + "Unit");
908                 Quantity<U> quantity = (Quantity<U>) Quantities.INSTANCE.getQuantity(type + "Unit");
909                 for (U unit : quantity.getUnitsById().values())
910                 {
911                     for (StorageType storageType2 : new StorageType[] { StorageType.DENSE, storageType })
912                     {
913                         SIUnit siUnit = SIUnit.of(unit.getQuantity().getSiDimensions());
914                         SIMatrix matrix = SIMatrix.instantiate(testValues, siUnit, storageType2);
915                         Method asMethod = SIMatrix.class.getDeclaredMethod("as", Unit.class);
916                         AbstractDoubleMatrixRel<U, ?, ?, ?> asMatrix =
917                                 (AbstractDoubleMatrixRel<U, ?, ?, ?>) asMethod.invoke(matrix, siUnit);
918                         assertEquals(matrix.getDisplayUnit().getStandardUnit(), asMatrix.getDisplayUnit());
919                         siUnit = SIUnit.of(AbsoluteTemperatureUnit.KELVIN.getQuantity().getSiDimensions());
920                         for (int row = 0; row < testValues.length; row++)
921                         {
922                             for (int col = 0; col < testValues[0].length; col++)
923                             {
924                                 assertEquals("Values should match", testValues[row][col], matrix.getInUnit(row, col), 0.001);
925                             }
926                         }
927                         try
928                         {
929                             asMethod.invoke(matrix, siUnit);
930                             fail("as method should not be able to cast to unrelated (absoluteTemperature) unit");
931                         }
932                         catch (InvocationTargetException ite)
933                         {
934                             Throwable cause = ite.getCause();
935                             assertEquals("cause is UnitRuntimeException", UnitRuntimeException.class, cause.getClass());
936                             // Otherwise ignore expected exception
937                         }
938                     }
939                 }
940             }
941         }
942     }
943 
944     /**
945      * Test the equals method.
946      */
947     @SuppressWarnings("unlikely-arg-type")
948     @Test
949     public void testEquals()
950     {
951         double[][] testData = DOUBLEMATRIX.denseRectArrays(12, 34);
952         testData[2][2] = 0;
953         for (StorageType storageType : new StorageType[] { StorageType.DENSE, StorageType.SPARSE })
954         {
955             DoubleMatrixData dmd = DoubleMatrixData.instantiate(testData, TemperatureUnit.KELVIN.getScale(), storageType);
956             assertTrue("Double matrix is equal to itself", dmd.equals(dmd));
957             assertFalse("Double matrix is not equal to null", dmd.equals(null));
958             assertFalse("Double matrix data is not equal to some string", dmd.equals("some string"));
959             assertTrue("Double matrix is equal to sparse version of itself", dmd.equals(dmd.toSparse()));
960             assertTrue("Double matrix is equal to dense version of itself", dmd.equals(dmd.toDense()));
961             for (StorageType storageType2 : new StorageType[] { StorageType.DENSE, StorageType.SPARSE })
962             {
963                 DoubleMatrixData dvd2 = DoubleMatrixData.instantiate(testData, TemperatureUnit.KELVIN.getScale(), storageType2);
964                 assertEquals(
965                         "Double matrix data is equal to other double vector containing same values regardless of storage type",
966                         dmd, dvd2);
967                 double[][] testData2 = DOUBLEMATRIX.denseRectArrays(12, 33);
968                 testData2[2][2] = 0;
969                 dvd2 = DoubleMatrixData.instantiate(testData2, TemperatureUnit.KELVIN.getScale(), storageType2);
970                 assertFalse("Double matrix data is not equal to other double vector containing same values except last one",
971                         dmd.equals(dvd2));
972                 testData2 = DOUBLEMATRIX.denseRectArrays(13, 34);
973                 testData2[2][2] = 0;
974                 dvd2 = DoubleMatrixData.instantiate(testData2, TemperatureUnit.KELVIN.getScale(), storageType2);
975                 assertFalse("Double matrix data is not equal to other double vector containing same values except last one",
976                         dmd.equals(dvd2));
977                 testData2 = DOUBLEMATRIX.denseRectArrays(12, 34);
978                 dvd2 = DoubleMatrixData.instantiate(testData2, TemperatureUnit.KELVIN.getScale(), storageType2);
979                 assertFalse("Double matrix data is not equal to other double vector containing same values except for one zero",
980                         dmd.equals(dvd2));
981             }
982         }
983     }
984 
985     /**
986      * Test the sparse value class.
987      */
988     @SuppressWarnings({ "rawtypes", "unchecked" })
989     @Test
990     public void sparseValueTest()
991     {
992         try
993         {
994             new DoubleSparseValue(-1, 0, 123.456);
995             fail("Negative row should have caused a ValueRuntimeException");
996         }
997         catch (ValueRuntimeException vre)
998         {
999             // Ignore expected exception
1000         }
1001 
1002         try
1003         {
1004             new DoubleSparseValue(0, -1, 123.456);
1005             fail("Negative column should have caused a ValueRuntimeException");
1006         }
1007         catch (ValueRuntimeException vre)
1008         {
1009             // Ignore expected exception
1010         }
1011 
1012         Length length = Length.valueOf("123 km");
1013         DoubleSparseValue dsv = new DoubleSparseValue(2, 3, length);
1014         assertEquals("row matches", 2, dsv.getRow());
1015         assertEquals("column matches", 3, dsv.getColumn());
1016         assertEquals("value matches", 123000, dsv.getValueSI(), 0.1);
1017         dsv = new DoubleSparseValue(2, 3, 123.000, LengthUnit.KILOMETER);
1018         assertEquals("row matches", 2, dsv.getRow());
1019         assertEquals("column matches", 3, dsv.getColumn());
1020         assertEquals("value matches", 123000, dsv.getValueSI(), 0.1);
1021     }
1022 
1023 }