View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.linear;
23  
24  import org.hipparchus.UnitTestUtils;
25  import org.hipparchus.exception.LocalizedCoreFormats;
26  import org.hipparchus.exception.MathIllegalArgumentException;
27  import org.hipparchus.exception.MathIllegalStateException;
28  import org.hipparchus.exception.NullArgumentException;
29  import org.hipparchus.random.RandomGenerator;
30  import org.hipparchus.random.Well1024a;
31  import org.hipparchus.util.FastMath;
32  import org.junit.jupiter.api.Test;
33  
34  import java.text.DecimalFormat;
35  
36  import static org.junit.jupiter.api.Assertions.assertEquals;
37  import static org.junit.jupiter.api.Assertions.assertFalse;
38  import static org.junit.jupiter.api.Assertions.assertNotEquals;
39  import static org.junit.jupiter.api.Assertions.assertNotNull;
40  import static org.junit.jupiter.api.Assertions.assertNotSame;
41  import static org.junit.jupiter.api.Assertions.assertThrows;
42  import static org.junit.jupiter.api.Assertions.assertTrue;
43  import static org.junit.jupiter.api.Assertions.fail;
44  
45  /**
46   * Test cases for the {@link Array2DRowRealMatrix} class.
47   *
48   */
49  
50  final class Array2DRowRealMatrixTest {
51  
52      // 3 x 3 identity matrix
53      protected double[][] id = { {1d,0d,0d}, {0d,1d,0d}, {0d,0d,1d} };
54  
55      // Test data for group operations
56      protected double[][] testData = { {1d,2d,3d}, {2d,5d,3d}, {1d,0d,8d} };
57      protected double[][] testDataLU = {{2d, 5d, 3d}, {.5d, -2.5d, 6.5d}, {0.5d, 0.2d, .2d}};
58      protected double[][] testDataPlus2 = { {3d,4d,5d}, {4d,7d,5d}, {3d,2d,10d} };
59      protected double[][] testDataMinus = { {-1d,-2d,-3d}, {-2d,-5d,-3d},
60         {-1d,0d,-8d} };
61      protected double[] testDataRow1 = {1d,2d,3d};
62      protected double[] testDataCol3 = {3d,3d,8d};
63      protected double[][] testDataInv =
64          { {-40d,16d,9d}, {13d,-5d,-3d}, {5d,-2d,-1d} };
65      protected double[] preMultTest = {8,12,33};
66      protected double[][] testData2 ={ {1d,2d,3d}, {2d,5d,3d}};
67      protected double[][] testData2T = { {1d,2d}, {2d,5d}, {3d,3d}};
68      protected double[][] testDataPlusInv =
69          { {-39d,18d,12d}, {15d,0d,0d}, {6d,-2d,7d} };
70  
71      // lu decomposition tests
72      protected double[][] luData = { {2d,3d,3d}, {0d,5d,7d}, {6d,9d,8d} };
73      protected double[][] luDataLUDecomposition = { {6d,9d,8d}, {0d,5d,7d},
74              {0.33333333333333,0d,0.33333333333333} };
75  
76      // singular matrices
77      protected double[][] singular = { {2d,3d}, {2d,3d} };
78      protected double[][] bigSingular = {{1d,2d,3d,4d}, {2d,5d,3d,4d},
79          {7d,3d,256d,1930d}, {3d,7d,6d,8d}}; // 4th row = 1st + 2nd
80      protected double[][] detData = { {1d,2d,3d}, {4d,5d,6d}, {7d,8d,10d} };
81      protected double[][] detData2 = { {1d, 3d}, {2d, 4d}};
82  
83      // vectors
84      protected double[] testVector = {1,2,3};
85      protected double[] testVector2 = {1,2,3,4};
86  
87      // submatrix accessor tests
88      protected double[][] subTestData = {{1, 2, 3, 4}, {1.5, 2.5, 3.5, 4.5},
89              {2, 4, 6, 8}, {4, 5, 6, 7}};
90      // array selections
91      protected double[][] subRows02Cols13 = { {2, 4}, {4, 8}};
92      protected double[][] subRows03Cols12 = { {2, 3}, {5, 6}};
93      protected double[][] subRows03Cols123 = { {2, 3, 4} , {5, 6, 7}};
94      // effective permutations
95      protected double[][] subRows20Cols123 = { {4, 6, 8} , {2, 3, 4}};
96      protected double[][] subRows31Cols31 = {{7, 5}, {4.5, 2.5}};
97      // contiguous ranges
98      protected double[][] subRows01Cols23 = {{3,4} , {3.5, 4.5}};
99      protected double[][] subRows23Cols00 = {{2} , {4}};
100     protected double[][] subRows00Cols33 = {{4}};
101     // row matrices
102     protected double[][] subRow0 = {{1,2,3,4}};
103     protected double[][] subRow3 = {{4,5,6,7}};
104     // column matrices
105     protected double[][] subColumn1 = {{2}, {2.5}, {4}, {5}};
106     protected double[][] subColumn3 = {{4}, {4.5}, {8}, {7}};
107 
108     // tolerances
109     protected double entryTolerance = 10E-16;
110     protected double normTolerance = 10E-14;
111     protected double powerTolerance = 10E-16;
112 
113     /** test dimensions */
114     @Test
115     void testDimensions() {
116         Array2DRowRealMatrix m = new Array2DRowRealMatrix(testData);
117         Array2DRowRealMatrix m2 = new Array2DRowRealMatrix(testData2);
118         assertEquals(3,m.getRowDimension(),"testData row dimension");
119         assertEquals(3,m.getColumnDimension(),"testData column dimension");
120         assertTrue(m.isSquare(),"testData is square");
121         assertEquals(2, m2.getRowDimension(), "testData2 row dimension");
122         assertEquals(3, m2.getColumnDimension(), "testData2 column dimension");
123         assertFalse(m2.isSquare(), "testData2 is not square");
124     }
125 
126     /** test copy functions */
127     @Test
128     void testCopyFunctions() {
129         Array2DRowRealMatrix m1 = new Array2DRowRealMatrix(testData);
130         Array2DRowRealMatrix m2 = new Array2DRowRealMatrix(m1.getData());
131         assertEquals(m2,m1);
132         Array2DRowRealMatrix m3 = new Array2DRowRealMatrix(testData);
133         Array2DRowRealMatrix m4 = new Array2DRowRealMatrix(m3.getData(), false);
134         assertEquals(m4,m3);
135     }
136 
137     /** test add */
138     @Test
139     void testAdd() {
140         Array2DRowRealMatrix m = new Array2DRowRealMatrix(testData);
141         Array2DRowRealMatrix mInv = new Array2DRowRealMatrix(testDataInv);
142         RealMatrix mPlusMInv = m.add(mInv);
143         double[][] sumEntries = mPlusMInv.getData();
144         for (int row = 0; row < m.getRowDimension(); row++) {
145             for (int col = 0; col < m.getColumnDimension(); col++) {
146                 assertEquals(testDataPlusInv[row][col],sumEntries[row][col],
147                         entryTolerance,
148                         "sum entry entry");
149             }
150         }
151     }
152 
153     /** test add failure */
154     @Test
155     void testAddFail() {
156         Array2DRowRealMatrix m = new Array2DRowRealMatrix(testData);
157         Array2DRowRealMatrix m2 = new Array2DRowRealMatrix(testData2);
158         try {
159             m.add(m2);
160             fail("MathIllegalArgumentException expected");
161         } catch (MathIllegalArgumentException ex) {
162             // ignored
163         }
164     }
165 
166     /** test norm */
167     @Test
168     void testNorm() {
169         Array2DRowRealMatrix m = new Array2DRowRealMatrix(testData);
170         Array2DRowRealMatrix m2 = new Array2DRowRealMatrix(testData2);
171         assertEquals(10d,m.getNormInfty(),entryTolerance,"testData norm");
172         assertEquals(10d,m2.getNormInfty(),entryTolerance,"testData2 norm");
173         assertEquals(14d,m.getNorm1(),entryTolerance,"testData norm");
174         assertEquals(7d,m2.getNorm1(),entryTolerance,"testData2 norm");
175     }
176 
177     /** test Frobenius norm */
178     @Test
179     void testFrobeniusNorm() {
180         Array2DRowRealMatrix m = new Array2DRowRealMatrix(testData);
181         Array2DRowRealMatrix m2 = new Array2DRowRealMatrix(testData2);
182         assertEquals(FastMath.sqrt(117.0), m.getFrobeniusNorm(), entryTolerance, "testData Frobenius norm");
183         assertEquals(FastMath.sqrt(52.0), m2.getFrobeniusNorm(), entryTolerance, "testData2 Frobenius norm");
184     }
185 
186     /** test m-n = m + -n */
187     @Test
188     void testPlusMinus() {
189         Array2DRowRealMatrix m = new Array2DRowRealMatrix(testData);
190         Array2DRowRealMatrix m2 = new Array2DRowRealMatrix(testDataInv);
191         UnitTestUtils.customAssertEquals("m-n = m + -n", m.subtract(m2),
192                                          m2.scalarMultiply(-1d).add(m), entryTolerance);
193         try {
194             m.subtract(new Array2DRowRealMatrix(testData2));
195             fail("Expecting illegalArgumentException");
196         } catch (MathIllegalArgumentException ex) {
197             // ignored
198         }
199     }
200 
201     /** test multiply */
202     @Test
203     void testMultiply() {
204         Array2DRowRealMatrix m = new Array2DRowRealMatrix(testData);
205         Array2DRowRealMatrix mInv = new Array2DRowRealMatrix(testDataInv);
206         Array2DRowRealMatrix identity = new Array2DRowRealMatrix(id);
207         Array2DRowRealMatrix m2 = new Array2DRowRealMatrix(testData2);
208         UnitTestUtils.customAssertEquals("inverse multiply", m.multiply(mInv),
209                                          identity, entryTolerance);
210         UnitTestUtils.customAssertEquals("inverse multiply", mInv.multiply(m),
211                                          identity, entryTolerance);
212         UnitTestUtils.customAssertEquals("identity multiply", m.multiply(identity),
213                                          m, entryTolerance);
214         UnitTestUtils.customAssertEquals("identity multiply", identity.multiply(mInv),
215                                          mInv, entryTolerance);
216         UnitTestUtils.customAssertEquals("identity multiply", m2.multiply(identity),
217                                          m2, entryTolerance);
218         try {
219             m.multiply(new Array2DRowRealMatrix(bigSingular));
220             fail("Expecting illegalArgumentException");
221         } catch (MathIllegalArgumentException ex) {
222             // ignored
223         }
224     }
225 
226     //Additional Test for Array2DRowRealMatrixTest.testMultiply
227 
228     private final double[][] d3 = new double[][] {{1,2,3,4},{5,6,7,8}};
229     private final double[][] d4 = new double[][] {{1},{2},{3},{4}};
230     private final double[][] d5 = new double[][] {{30},{70}};
231 
232     @Test
233     void testMultiply2() {
234        RealMatrix m3 = new Array2DRowRealMatrix(d3);
235        RealMatrix m4 = new Array2DRowRealMatrix(d4);
236        RealMatrix m5 = new Array2DRowRealMatrix(d5);
237        UnitTestUtils.customAssertEquals("m3*m4=m5", m3.multiply(m4), m5, entryTolerance);
238     }
239 
240     @Test
241     void testMultiplyTransposedArray2DRowRealMatrix() {
242         RandomGenerator randomGenerator = new Well1024a(0xdeff3d383a112763l);
243         final RealMatrixChangingVisitor randomSetter = new DefaultRealMatrixChangingVisitor() {
244             public double visit(final int row, final int column, final double value) {
245                 return randomGenerator.nextDouble();
246             }
247         };
248         for (int rows = 1; rows <= 64; rows += 7) {
249             for (int cols = 1; cols <= 64; cols += 7) {
250                 final Array2DRowRealMatrix a = new Array2DRowRealMatrix(rows, cols);
251                 a.walkInOptimizedOrder(randomSetter);
252                 for (int interm = 1; interm <= 64; interm += 7) {
253                     final Array2DRowRealMatrix b = new Array2DRowRealMatrix(interm, cols);
254                     b.walkInOptimizedOrder(randomSetter);
255                     assertEquals(0.0,
256                                         a.multiplyTransposed(b).subtract(a.multiply(b.transpose())).getNorm1(),
257                                         1.0e-15);
258                 }
259             }
260         }
261     }
262 
263     @Test
264     void testMultiplyTransposedBlockRealMatrix() {
265         RandomGenerator randomGenerator = new Well1024a(0x463e54fb50b900fel);
266         final RealMatrixChangingVisitor randomSetter = new DefaultRealMatrixChangingVisitor() {
267             public double visit(final int row, final int column, final double value) {
268                 return randomGenerator.nextDouble();
269             }
270         };
271         for (int rows = 1; rows <= 64; rows += 7) {
272             for (int cols = 1; cols <= 64; cols += 7) {
273                 final Array2DRowRealMatrix a = new Array2DRowRealMatrix(rows, cols);
274                 a.walkInOptimizedOrder(randomSetter);
275                 for (int interm = 1; interm <= 64; interm += 7) {
276                     final BlockRealMatrix b = new BlockRealMatrix(interm, cols);
277                     b.walkInOptimizedOrder(randomSetter);
278                     assertEquals(0.0,
279                                         a.multiplyTransposed(b).subtract(a.multiply(b.transpose())).getNorm1(),
280                                         1.0e-15);
281                 }
282             }
283         }
284     }
285 
286     @Test
287     void testMultiplyTransposedWrongDimensions() {
288         try {
289             new Array2DRowRealMatrix(2, 3).multiplyTransposed(new Array2DRowRealMatrix(3, 2));
290             fail("an exception should have been thrown");
291         } catch (MathIllegalArgumentException miae) {
292             assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, miae.getSpecifier());
293             assertEquals(3, ((Integer) miae.getParts()[0]).intValue());
294             assertEquals(2, ((Integer) miae.getParts()[1]).intValue());
295         }
296     }
297 
298     @Test
299     void testTransposeMultiplyArray2DRowRealMatrix() {
300         RandomGenerator randomGenerator = new Well1024a(0xdeff3d383a112763l);
301         final RealMatrixChangingVisitor randomSetter = new DefaultRealMatrixChangingVisitor() {
302             public double visit(final int row, final int column, final double value) {
303                 return randomGenerator.nextDouble();
304             }
305         };
306         for (int rows = 1; rows <= 64; rows += 7) {
307             for (int cols = 1; cols <= 64; cols += 7) {
308                 final Array2DRowRealMatrix a = new Array2DRowRealMatrix(rows, cols);
309                 a.walkInOptimizedOrder(randomSetter);
310                 for (int interm = 1; interm <= 64; interm += 7) {
311                     final Array2DRowRealMatrix b = new Array2DRowRealMatrix(rows, interm);
312                     b.walkInOptimizedOrder(randomSetter);
313                     assertEquals(0.0,
314                                         a.transposeMultiply(b).subtract(a.transpose().multiply(b)).getNorm1(),
315                                         1.0e-15);
316                 }
317             }
318         }
319     }
320 
321     @Test
322     void testTransposeMultiplyBlockRealMatrix() {
323         RandomGenerator randomGenerator = new Well1024a(0x463e54fb50b900fel);
324         final RealMatrixChangingVisitor randomSetter = new DefaultRealMatrixChangingVisitor() {
325             public double visit(final int row, final int column, final double value) {
326                 return randomGenerator.nextDouble();
327             }
328         };
329         for (int rows = 1; rows <= 64; rows += 7) {
330             for (int cols = 1; cols <= 64; cols += 7) {
331                 final Array2DRowRealMatrix a = new Array2DRowRealMatrix(rows, cols);
332                 a.walkInOptimizedOrder(randomSetter);
333                 for (int interm = 1; interm <= 64; interm += 7) {
334                     final BlockRealMatrix b = new BlockRealMatrix(rows, interm);
335                     b.walkInOptimizedOrder(randomSetter);
336                     assertEquals(0.0,
337                                         a.transposeMultiply(b).subtract(a.transpose().multiply(b)).getNorm1(),
338                                         1.0e-15);
339                 }
340             }
341         }
342     }
343 
344     @Test
345     void testTransposeMultiplyWrongDimensions() {
346         try {
347             new Array2DRowRealMatrix(2, 3).transposeMultiply(new Array2DRowRealMatrix(3, 2));
348             fail("an exception should have been thrown");
349         } catch (MathIllegalArgumentException miae) {
350             assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, miae.getSpecifier());
351             assertEquals(2, ((Integer) miae.getParts()[0]).intValue());
352             assertEquals(3, ((Integer) miae.getParts()[1]).intValue());
353         }
354     }
355 
356     @Test
357     void testPower() {
358         Array2DRowRealMatrix m = new Array2DRowRealMatrix(testData);
359         Array2DRowRealMatrix mInv = new Array2DRowRealMatrix(testDataInv);
360         Array2DRowRealMatrix mPlusInv = new Array2DRowRealMatrix(testDataPlusInv);
361         Array2DRowRealMatrix identity = new Array2DRowRealMatrix(id);
362 
363         UnitTestUtils.customAssertEquals("m^0", m.power(0),
364                                          identity, entryTolerance);
365         UnitTestUtils.customAssertEquals("mInv^0", mInv.power(0),
366                                          identity, entryTolerance);
367         UnitTestUtils.customAssertEquals("mPlusInv^0", mPlusInv.power(0),
368                                          identity, entryTolerance);
369 
370         UnitTestUtils.customAssertEquals("m^1", m.power(1),
371                                          m, entryTolerance);
372         UnitTestUtils.customAssertEquals("mInv^1", mInv.power(1),
373                                          mInv, entryTolerance);
374         UnitTestUtils.customAssertEquals("mPlusInv^1", mPlusInv.power(1),
375                                          mPlusInv, entryTolerance);
376 
377         RealMatrix C1 = m.copy();
378         RealMatrix C2 = mInv.copy();
379         RealMatrix C3 = mPlusInv.copy();
380 
381         for (int i = 2; i <= 10; ++i) {
382             C1 = C1.multiply(m);
383             C2 = C2.multiply(mInv);
384             C3 = C3.multiply(mPlusInv);
385 
386             UnitTestUtils.customAssertEquals("m^" + i, m.power(i),
387                                              C1, entryTolerance);
388             UnitTestUtils.customAssertEquals("mInv^" + i, mInv.power(i),
389                                              C2, entryTolerance);
390             UnitTestUtils.customAssertEquals("mPlusInv^" + i, mPlusInv.power(i),
391                                              C3, entryTolerance);
392         }
393 
394         try {
395             Array2DRowRealMatrix mNotSquare = new Array2DRowRealMatrix(testData2T);
396             mNotSquare.power(2);
397             fail("Expecting MathIllegalArgumentException");
398         } catch (MathIllegalArgumentException ex) {
399             // ignored
400         }
401 
402         try {
403             m.power(-1);
404             fail("Expecting MathIllegalArgumentException");
405         } catch (MathIllegalArgumentException ex) {
406             // ignored
407         }
408     }
409 
410     /** test trace */
411     @Test
412     void testTrace() {
413         RealMatrix m = new Array2DRowRealMatrix(id);
414         assertEquals(3d,m.getTrace(),entryTolerance,"identity trace");
415         m = new Array2DRowRealMatrix(testData2);
416         try {
417             m.getTrace();
418             fail("Expecting MathIllegalArgumentException");
419         } catch (MathIllegalArgumentException ex) {
420             // ignored
421         }
422     }
423 
424     /** test sclarAdd */
425     @Test
426     void testScalarAdd() {
427         RealMatrix m = new Array2DRowRealMatrix(testData);
428         UnitTestUtils.customAssertEquals("scalar add", new Array2DRowRealMatrix(testDataPlus2),
429                                          m.scalarAdd(2d), entryTolerance);
430     }
431 
432     /** test operate */
433     @Test
434     void testOperate() {
435         RealMatrix m = new Array2DRowRealMatrix(id);
436         UnitTestUtils.customAssertEquals("identity operate", testVector,
437                                          m.operate(testVector), entryTolerance);
438         UnitTestUtils.customAssertEquals("identity operate", testVector,
439                                          m.operate(new ArrayRealVector(testVector)).toArray(), entryTolerance);
440         m = new Array2DRowRealMatrix(bigSingular);
441         try {
442             m.operate(testVector);
443             fail("Expecting illegalArgumentException");
444         } catch (MathIllegalArgumentException ex) {
445             // ignored
446         }
447     }
448 
449     /** test issue MATH-209 */
450     @Test
451     void testMath209() {
452         RealMatrix a = new Array2DRowRealMatrix(new double[][] {
453                 { 1, 2 }, { 3, 4 }, { 5, 6 }
454         }, false);
455         double[] b = a.operate(new double[] { 1, 1 });
456         assertEquals(a.getRowDimension(), b.length);
457         assertEquals( 3.0, b[0], 1.0e-12);
458         assertEquals( 7.0, b[1], 1.0e-12);
459         assertEquals(11.0, b[2], 1.0e-12);
460     }
461 
462     /** test transpose */
463     @Test
464     void testTranspose() {
465         RealMatrix m = new Array2DRowRealMatrix(testData);
466         RealMatrix mIT = new LUDecomposition(m).getSolver().getInverse().transpose();
467         RealMatrix mTI = new LUDecomposition(m.transpose()).getSolver().getInverse();
468         UnitTestUtils.customAssertEquals("inverse-transpose", mIT, mTI, normTolerance);
469         m = new Array2DRowRealMatrix(testData2);
470         RealMatrix mt = new Array2DRowRealMatrix(testData2T);
471         UnitTestUtils.customAssertEquals("transpose", mt, m.transpose(), normTolerance);
472     }
473 
474     /** test preMultiply by vector */
475     @Test
476     void testPremultiplyVector() {
477         RealMatrix m = new Array2DRowRealMatrix(testData);
478         UnitTestUtils.customAssertEquals("premultiply", m.preMultiply(testVector),
479                                          preMultTest, normTolerance);
480         UnitTestUtils.customAssertEquals("premultiply", m.preMultiply(new ArrayRealVector(testVector).toArray()),
481                                          preMultTest, normTolerance);
482         m = new Array2DRowRealMatrix(bigSingular);
483         try {
484             m.preMultiply(testVector);
485             fail("expecting MathIllegalArgumentException");
486         } catch (MathIllegalArgumentException ex) {
487             // ignored
488         }
489     }
490 
491     @Test
492     void testPremultiply() {
493         RealMatrix m3 = new Array2DRowRealMatrix(d3);
494         RealMatrix m4 = new Array2DRowRealMatrix(d4);
495         RealMatrix m5 = new Array2DRowRealMatrix(d5);
496         UnitTestUtils.customAssertEquals("m3*m4=m5", m4.preMultiply(m3), m5, entryTolerance);
497 
498         Array2DRowRealMatrix m = new Array2DRowRealMatrix(testData);
499         Array2DRowRealMatrix mInv = new Array2DRowRealMatrix(testDataInv);
500         Array2DRowRealMatrix identity = new Array2DRowRealMatrix(id);
501         UnitTestUtils.customAssertEquals("inverse multiply", m.preMultiply(mInv),
502                                          identity, entryTolerance);
503         UnitTestUtils.customAssertEquals("inverse multiply", mInv.preMultiply(m),
504                                          identity, entryTolerance);
505         UnitTestUtils.customAssertEquals("identity multiply", m.preMultiply(identity),
506                                          m, entryTolerance);
507         UnitTestUtils.customAssertEquals("identity multiply", identity.preMultiply(mInv),
508                                          mInv, entryTolerance);
509         try {
510             m.preMultiply(new Array2DRowRealMatrix(bigSingular));
511             fail("Expecting illegalArgumentException");
512         } catch (MathIllegalArgumentException ex) {
513             // ignored
514         }
515     }
516 
517     @Test
518     void testGetVectors() {
519         RealMatrix m = new Array2DRowRealMatrix(testData);
520         UnitTestUtils.customAssertEquals("get row", m.getRow(0), testDataRow1, entryTolerance);
521         UnitTestUtils.customAssertEquals("get col", m.getColumn(2), testDataCol3, entryTolerance);
522         try {
523             m.getRow(10);
524             fail("expecting MathIllegalArgumentException");
525         } catch (MathIllegalArgumentException ex) {
526             // ignored
527         }
528         try {
529             m.getColumn(-1);
530             fail("expecting MathIllegalArgumentException");
531         } catch (MathIllegalArgumentException ex) {
532             // ignored
533         }
534     }
535 
536     @Test
537     void testGetEntry() {
538         RealMatrix m = new Array2DRowRealMatrix(testData);
539         assertEquals(2d, m.getEntry(0, 1), entryTolerance, "get entry");
540         try {
541             m.getEntry(10, 4);
542             fail("Expecting MathIllegalArgumentException");
543         } catch (MathIllegalArgumentException ex) {
544             // expected
545         }
546     }
547 
548     /** test examples in user guide */
549     @Test
550     void testExamples() {
551         // Create a real matrix with two rows and three columns
552         double[][] matrixData = { {1d,2d,3d}, {2d,5d,3d}};
553         RealMatrix m = new Array2DRowRealMatrix(matrixData);
554         // One more with three rows, two columns
555         double[][] matrixData2 = { {1d,2d}, {2d,5d}, {1d, 7d}};
556         RealMatrix n = new Array2DRowRealMatrix(matrixData2);
557         // Now multiply m by n
558         RealMatrix p = m.multiply(n);
559         assertEquals(2, p.getRowDimension());
560         assertEquals(2, p.getColumnDimension());
561         // Invert p
562         RealMatrix pInverse = new LUDecomposition(p).getSolver().getInverse();
563         assertEquals(2, pInverse.getRowDimension());
564         assertEquals(2, pInverse.getColumnDimension());
565 
566         // Solve example
567         double[][] coefficientsData = {{2, 3, -2}, {-1, 7, 6}, {4, -3, -5}};
568         RealMatrix coefficients = new Array2DRowRealMatrix(coefficientsData);
569         RealVector constants = new ArrayRealVector(new double[]{1, -2, 1}, false);
570         RealVector solution = new LUDecomposition(coefficients).getSolver().solve(constants);
571         final double cst0 = constants.getEntry(0);
572         final double cst1 = constants.getEntry(1);
573         final double cst2 = constants.getEntry(2);
574         final double sol0 = solution.getEntry(0);
575         final double sol1 = solution.getEntry(1);
576         final double sol2 = solution.getEntry(2);
577         assertEquals(2 * sol0 + 3 * sol1 -2 * sol2, cst0, 1E-12);
578         assertEquals(-1 * sol0 + 7 * sol1 + 6 * sol2, cst1, 1E-12);
579         assertEquals(4 * sol0 - 3 * sol1 -5 * sol2, cst2, 1E-12);
580     }
581 
582     // test submatrix accessors
583     @Test
584     void testGetSubMatrix() {
585         RealMatrix m = new Array2DRowRealMatrix(subTestData);
586         checkGetSubMatrix(m, subRows23Cols00,  2 , 3 , 0, 0, false);
587         checkGetSubMatrix(m, subRows00Cols33,  0 , 0 , 3, 3, false);
588         checkGetSubMatrix(m, subRows01Cols23,  0 , 1 , 2, 3, false);
589         checkGetSubMatrix(m, subRows02Cols13,  new int[] { 0, 2 }, new int[] { 1, 3 },    false);
590         checkGetSubMatrix(m, subRows03Cols12,  new int[] { 0, 3 }, new int[] { 1, 2 },    false);
591         checkGetSubMatrix(m, subRows03Cols123, new int[] { 0, 3 }, new int[] { 1, 2, 3 }, false);
592         checkGetSubMatrix(m, subRows20Cols123, new int[] { 2, 0 }, new int[] { 1, 2, 3 }, false);
593         checkGetSubMatrix(m, subRows31Cols31,  new int[] { 3, 1 }, new int[] { 3, 1 },    false);
594         checkGetSubMatrix(m, subRows31Cols31,  new int[] { 3, 1 }, new int[] { 3, 1 },    false);
595         checkGetSubMatrix(m, null,  1, 0, 2, 4, true);
596         checkGetSubMatrix(m, null, -1, 1, 2, 2, true);
597         checkGetSubMatrix(m, null,  1, 0, 2, 2, true);
598         checkGetSubMatrix(m, null,  1, 0, 2, 4, true);
599         checkGetSubMatrix(m, null, new int[] {},    new int[] { 0 }, true);
600         checkGetSubMatrix(m, null, new int[] { 0 }, new int[] { 4 }, true);
601     }
602 
603     private void checkGetSubMatrix(RealMatrix m, double[][] reference,
604                                    int startRow, int endRow, int startColumn, int endColumn,
605                                    boolean mustFail) {
606         try {
607             RealMatrix sub = m.getSubMatrix(startRow, endRow, startColumn, endColumn);
608             assertEquals(new Array2DRowRealMatrix(reference), sub);
609             if (mustFail) {
610                 fail("Expecting MathIllegalArgumentException or MathIllegalArgumentException or MathIllegalArgumentException");
611             }
612         } catch (MathIllegalArgumentException e) {
613             if (!mustFail) {
614                 throw e;
615             }
616         }
617     }
618 
619     private void checkGetSubMatrix(RealMatrix m, double[][] reference,
620                                    int[] selectedRows, int[] selectedColumns,
621                                    boolean mustFail) {
622         try {
623             RealMatrix sub = m.getSubMatrix(selectedRows, selectedColumns);
624             assertEquals(new Array2DRowRealMatrix(reference), sub);
625             if (mustFail) {
626                 fail("Expecting MathIllegalArgumentException or MathIllegalArgumentException or MathIllegalArgumentException");
627             }
628         } catch (MathIllegalArgumentException e) {
629             if (!mustFail) {
630                 throw e;
631             }
632         }
633     }
634 
635     @Test
636     void testCopySubMatrix() {
637         RealMatrix m = new Array2DRowRealMatrix(subTestData);
638         checkCopy(m, subRows23Cols00,  2 , 3 , 0, 0, false);
639         checkCopy(m, subRows00Cols33,  0 , 0 , 3, 3, false);
640         checkCopy(m, subRows01Cols23,  0 , 1 , 2, 3, false);
641         checkCopy(m, subRows02Cols13,  new int[] { 0, 2 }, new int[] { 1, 3 },    false);
642         checkCopy(m, subRows03Cols12,  new int[] { 0, 3 }, new int[] { 1, 2 },    false);
643         checkCopy(m, subRows03Cols123, new int[] { 0, 3 }, new int[] { 1, 2, 3 }, false);
644         checkCopy(m, subRows20Cols123, new int[] { 2, 0 }, new int[] { 1, 2, 3 }, false);
645         checkCopy(m, subRows31Cols31,  new int[] { 3, 1 }, new int[] { 3, 1 },    false);
646         checkCopy(m, subRows31Cols31,  new int[] { 3, 1 }, new int[] { 3, 1 },    false);
647 
648         checkCopy(m, null,  1, 0, 2, 4, true);
649         checkCopy(m, null, -1, 1, 2, 2, true);
650         checkCopy(m, null,  1, 0, 2, 2, true);
651         checkCopy(m, null,  1, 0, 2, 4, true);
652         checkCopy(m, null, new int[] {},    new int[] { 0 }, true);
653         checkCopy(m, null, new int[] { 0 }, new int[] { 4 }, true);
654 
655         // rectangular check
656         double[][] copy = new double[][] { { 0, 0, 0 }, { 0, 0 } };
657         checkCopy(m, copy, 0, 1, 0, 2, true);
658         checkCopy(m, copy, new int[] { 0, 1 }, new int[] { 0, 1, 2 }, true);
659     }
660 
661     private void checkCopy(RealMatrix m, double[][] reference,
662                            int startRow, int endRow, int startColumn, int endColumn,
663                            boolean mustFail) {
664         try {
665             double[][] sub = (reference == null) ?
666                              new double[1][1] : createIdenticalCopy(reference);
667             m.copySubMatrix(startRow, endRow, startColumn, endColumn, sub);
668             assertEquals(new Array2DRowRealMatrix(reference), new Array2DRowRealMatrix(sub));
669             if (mustFail) {
670                 fail("Expecting MathIllegalArgumentException or MathIllegalArgumentException or MathIllegalArgumentException");
671             }
672         } catch (MathIllegalArgumentException e) {
673             if (!mustFail) {
674                 throw e;
675             }
676         }
677     }
678 
679     private void checkCopy(RealMatrix m, double[][] reference,
680                            int[] selectedRows, int[] selectedColumns,
681                            boolean mustFail) {
682         try {
683             double[][] sub = (reference == null) ?
684                     new double[1][1] : createIdenticalCopy(reference);
685             m.copySubMatrix(selectedRows, selectedColumns, sub);
686             assertEquals(new Array2DRowRealMatrix(reference), new Array2DRowRealMatrix(sub));
687             if (mustFail) {
688                 fail("Expecting MathIllegalArgumentException or MathIllegalArgumentException or MathIllegalArgumentException");
689             }
690         } catch (MathIllegalArgumentException e) {
691             if (!mustFail) {
692                 throw e;
693             }
694         }
695     }
696 
697     private double[][] createIdenticalCopy(final double[][] matrix) {
698         final double[][] matrixCopy = new double[matrix.length][];
699         for (int i = 0; i < matrixCopy.length; i++) {
700             matrixCopy[i] = new double[matrix[i].length];
701         }
702         return matrixCopy;
703     }
704 
705     @Test
706     void testGetRowMatrix() {
707         RealMatrix m = new Array2DRowRealMatrix(subTestData);
708         RealMatrix mRow0 = new Array2DRowRealMatrix(subRow0);
709         RealMatrix mRow3 = new Array2DRowRealMatrix(subRow3);
710         assertEquals(mRow0,
711                 m.getRowMatrix(0),
712                 "Row0");
713         assertEquals(mRow3,
714                 m.getRowMatrix(3),
715                 "Row3");
716         try {
717             m.getRowMatrix(-1);
718             fail("Expecting MathIllegalArgumentException");
719         } catch (MathIllegalArgumentException ex) {
720             // expected
721         }
722         try {
723             m.getRowMatrix(4);
724             fail("Expecting MathIllegalArgumentException");
725         } catch (MathIllegalArgumentException ex) {
726             // expected
727         }
728     }
729 
730     @Test
731     void testSetRowMatrix() {
732         RealMatrix m = new Array2DRowRealMatrix(subTestData);
733         RealMatrix mRow3 = new Array2DRowRealMatrix(subRow3);
734         assertNotSame(mRow3, m.getRowMatrix(0));
735         m.setRowMatrix(0, mRow3);
736         assertEquals(mRow3, m.getRowMatrix(0));
737         try {
738             m.setRowMatrix(-1, mRow3);
739             fail("Expecting MathIllegalArgumentException");
740         } catch (MathIllegalArgumentException ex) {
741             // expected
742         }
743         try {
744             m.setRowMatrix(0, m);
745             fail("Expecting MathIllegalArgumentException");
746         } catch (MathIllegalArgumentException ex) {
747             // expected
748         }
749     }
750 
751     @Test
752     void testGetColumnMatrix() {
753         RealMatrix m = new Array2DRowRealMatrix(subTestData);
754         RealMatrix mColumn1 = new Array2DRowRealMatrix(subColumn1);
755         RealMatrix mColumn3 = new Array2DRowRealMatrix(subColumn3);
756         assertEquals(mColumn1,
757                 m.getColumnMatrix(1),
758                 "Column1");
759         assertEquals(mColumn3,
760                 m.getColumnMatrix(3),
761                 "Column3");
762         try {
763             m.getColumnMatrix(-1);
764             fail("Expecting MathIllegalArgumentException");
765         } catch (MathIllegalArgumentException ex) {
766             // expected
767         }
768         try {
769             m.getColumnMatrix(4);
770             fail("Expecting MathIllegalArgumentException");
771         } catch (MathIllegalArgumentException ex) {
772             // expected
773         }
774     }
775 
776     @Test
777     void testSetColumnMatrix() {
778         RealMatrix m = new Array2DRowRealMatrix(subTestData);
779         RealMatrix mColumn3 = new Array2DRowRealMatrix(subColumn3);
780         assertNotSame(mColumn3, m.getColumnMatrix(1));
781         m.setColumnMatrix(1, mColumn3);
782         assertEquals(mColumn3, m.getColumnMatrix(1));
783         try {
784             m.setColumnMatrix(-1, mColumn3);
785             fail("Expecting MathIllegalArgumentException");
786         } catch (MathIllegalArgumentException ex) {
787             // expected
788         }
789         try {
790             m.setColumnMatrix(0, m);
791             fail("Expecting MathIllegalArgumentException");
792         } catch (MathIllegalArgumentException ex) {
793             // expected
794         }
795     }
796 
797     @Test
798     void testGetRowVector() {
799         RealMatrix m = new Array2DRowRealMatrix(subTestData);
800         RealVector mRow0 = new ArrayRealVector(subRow0[0]);
801         RealVector mRow3 = new ArrayRealVector(subRow3[0]);
802         assertEquals(mRow0, m.getRowVector(0), "Row0");
803         assertEquals(mRow3, m.getRowVector(3), "Row3");
804         try {
805             m.getRowVector(-1);
806             fail("Expecting MathIllegalArgumentException");
807         } catch (MathIllegalArgumentException ex) {
808             // expected
809         }
810         try {
811             m.getRowVector(4);
812             fail("Expecting MathIllegalArgumentException");
813         } catch (MathIllegalArgumentException ex) {
814             // expected
815         }
816     }
817 
818     @Test
819     void testSetRowVector() {
820         RealMatrix m = new Array2DRowRealMatrix(subTestData);
821         RealVector mRow3 = new ArrayRealVector(subRow3[0]);
822         assertNotSame(mRow3, m.getRowMatrix(0));
823         m.setRowVector(0, mRow3);
824         assertEquals(mRow3, m.getRowVector(0));
825         try {
826             m.setRowVector(-1, mRow3);
827             fail("Expecting MathIllegalArgumentException");
828         } catch (MathIllegalArgumentException ex) {
829             // expected
830         }
831         try {
832             m.setRowVector(0, new ArrayRealVector(5));
833             fail("Expecting MathIllegalArgumentException");
834         } catch (MathIllegalArgumentException ex) {
835             // expected
836         }
837     }
838 
839     @Test
840     void testGetColumnVector() {
841         RealMatrix m = new Array2DRowRealMatrix(subTestData);
842         RealVector mColumn1 = columnToVector(subColumn1);
843         RealVector mColumn3 = columnToVector(subColumn3);
844         assertEquals(mColumn1, m.getColumnVector(1), "Column1");
845         assertEquals(mColumn3, m.getColumnVector(3), "Column3");
846         try {
847             m.getColumnVector(-1);
848             fail("Expecting MathIllegalArgumentException");
849         } catch (MathIllegalArgumentException ex) {
850             // expected
851         }
852         try {
853             m.getColumnVector(4);
854             fail("Expecting MathIllegalArgumentException");
855         } catch (MathIllegalArgumentException ex) {
856             // expected
857         }
858     }
859 
860     @Test
861     void testSetColumnVector() {
862         RealMatrix m = new Array2DRowRealMatrix(subTestData);
863         RealVector mColumn3 = columnToVector(subColumn3);
864         assertNotSame(mColumn3, m.getColumnVector(1));
865         m.setColumnVector(1, mColumn3);
866         assertEquals(mColumn3, m.getColumnVector(1));
867         try {
868             m.setColumnVector(-1, mColumn3);
869             fail("Expecting MathIllegalArgumentException");
870         } catch (MathIllegalArgumentException ex) {
871             // expected
872         }
873         try {
874             m.setColumnVector(0, new ArrayRealVector(5));
875             fail("Expecting MathIllegalArgumentException");
876         } catch (MathIllegalArgumentException ex) {
877             // expected
878         }
879     }
880 
881     private RealVector columnToVector(double[][] column) {
882         double[] data = new double[column.length];
883         for (int i = 0; i < data.length; ++i) {
884             data[i] = column[i][0];
885         }
886         return new ArrayRealVector(data, false);
887     }
888 
889     @Test
890     void testGetRow() {
891         RealMatrix m = new Array2DRowRealMatrix(subTestData);
892         checkArrays(subRow0[0], m.getRow(0));
893         checkArrays(subRow3[0], m.getRow(3));
894         try {
895             m.getRow(-1);
896             fail("Expecting MathIllegalArgumentException");
897         } catch (MathIllegalArgumentException ex) {
898             // expected
899         }
900         try {
901             m.getRow(4);
902             fail("Expecting MathIllegalArgumentException");
903         } catch (MathIllegalArgumentException ex) {
904             // expected
905         }
906     }
907 
908     @Test
909     void testSetRow() {
910         RealMatrix m = new Array2DRowRealMatrix(subTestData);
911         assertTrue(subRow3[0][0] != m.getRow(0)[0]);
912         m.setRow(0, subRow3[0]);
913         checkArrays(subRow3[0], m.getRow(0));
914         try {
915             m.setRow(-1, subRow3[0]);
916             fail("Expecting MathIllegalArgumentException");
917         } catch (MathIllegalArgumentException ex) {
918             // expected
919         }
920         try {
921             m.setRow(0, new double[5]);
922             fail("Expecting MathIllegalArgumentException");
923         } catch (MathIllegalArgumentException ex) {
924             // expected
925         }
926     }
927 
928     @Test
929     void testGetColumn() {
930         RealMatrix m = new Array2DRowRealMatrix(subTestData);
931         double[] mColumn1 = columnToArray(subColumn1);
932         double[] mColumn3 = columnToArray(subColumn3);
933         checkArrays(mColumn1, m.getColumn(1));
934         checkArrays(mColumn3, m.getColumn(3));
935         try {
936             m.getColumn(-1);
937             fail("Expecting MathIllegalArgumentException");
938         } catch (MathIllegalArgumentException ex) {
939             // expected
940         }
941         try {
942             m.getColumn(4);
943             fail("Expecting MathIllegalArgumentException");
944         } catch (MathIllegalArgumentException ex) {
945             // expected
946         }
947     }
948 
949     @Test
950     void testSetColumn() {
951         RealMatrix m = new Array2DRowRealMatrix(subTestData);
952         double[] mColumn3 = columnToArray(subColumn3);
953         assertTrue(mColumn3[0] != m.getColumn(1)[0]);
954         m.setColumn(1, mColumn3);
955         checkArrays(mColumn3, m.getColumn(1));
956         try {
957             m.setColumn(-1, mColumn3);
958             fail("Expecting MathIllegalArgumentException");
959         } catch (MathIllegalArgumentException ex) {
960             // expected
961         }
962         try {
963             m.setColumn(0, new double[5]);
964             fail("Expecting MathIllegalArgumentException");
965         } catch (MathIllegalArgumentException ex) {
966             // expected
967         }
968     }
969 
970     private double[] columnToArray(double[][] column) {
971         double[] data = new double[column.length];
972         for (int i = 0; i < data.length; ++i) {
973             data[i] = column[i][0];
974         }
975         return data;
976     }
977 
978     private void checkArrays(double[] expected, double[] actual) {
979         assertEquals(expected.length, actual.length);
980         for (int i = 0; i < expected.length; ++i) {
981             assertEquals(expected[i], actual[i], 0);
982         }
983     }
984 
985     @Test
986     void testEqualsAndHashCode() {
987         Array2DRowRealMatrix m = new Array2DRowRealMatrix(testData);
988         Array2DRowRealMatrix m1 = (Array2DRowRealMatrix) m.copy();
989         Array2DRowRealMatrix mt = (Array2DRowRealMatrix) m.transpose();
990         assertTrue(m.hashCode() != mt.hashCode());
991         assertEquals(m.hashCode(), m1.hashCode());
992         assertEquals(m, m);
993         assertEquals(m, m1);
994         assertNotEquals(null, m);
995         assertNotEquals(m, mt);
996         assertNotEquals(m, new Array2DRowRealMatrix(bigSingular));
997     }
998 
999     @Test
1000     void testToString() {
1001         Array2DRowRealMatrix m = new Array2DRowRealMatrix(testData);
1002         assertEquals("Array2DRowRealMatrix{{1.0,2.0,3.0},{2.0,5.0,3.0},{1.0,0.0,8.0}}",
1003                 m.toString());
1004         m = new Array2DRowRealMatrix();
1005         assertEquals("Array2DRowRealMatrix{}",
1006                 m.toString());
1007     }
1008 
1009     @Test
1010     void testSetSubMatrix() {
1011         Array2DRowRealMatrix m = new Array2DRowRealMatrix(testData);
1012         m.setSubMatrix(detData2,1,1);
1013         RealMatrix expected = MatrixUtils.createRealMatrix
1014             (new double[][] {{1.0,2.0,3.0},{2.0,1.0,3.0},{1.0,2.0,4.0}});
1015         assertEquals(expected, m);
1016 
1017         m.setSubMatrix(detData2,0,0);
1018         expected = MatrixUtils.createRealMatrix
1019             (new double[][] {{1.0,3.0,3.0},{2.0,4.0,3.0},{1.0,2.0,4.0}});
1020         assertEquals(expected, m);
1021 
1022         m.setSubMatrix(testDataPlus2,0,0);
1023         expected = MatrixUtils.createRealMatrix
1024             (new double[][] {{3.0,4.0,5.0},{4.0,7.0,5.0},{3.0,2.0,10.0}});
1025         assertEquals(expected, m);
1026 
1027         // dimension overflow
1028         try {
1029             m.setSubMatrix(testData,1,1);
1030             fail("expecting MathIllegalArgumentException");
1031         } catch (MathIllegalArgumentException e) {
1032             // expected
1033         }
1034         // dimension underflow
1035         try {
1036             m.setSubMatrix(testData,-1,1);
1037             fail("expecting MathIllegalArgumentException");
1038         } catch (MathIllegalArgumentException e) {
1039             // expected
1040         }
1041         try {
1042             m.setSubMatrix(testData,1,-1);
1043             fail("expecting MathIllegalArgumentException");
1044         } catch (MathIllegalArgumentException e) {
1045             // expected
1046         }
1047 
1048         // null
1049         try {
1050             m.setSubMatrix(null,1,1);
1051             fail("expecting NullArgumentException");
1052         } catch (NullArgumentException e) {
1053             // expected
1054         }
1055         Array2DRowRealMatrix m2 = new Array2DRowRealMatrix();
1056         try {
1057             m2.setSubMatrix(testData,0,1);
1058             fail("expecting MathIllegalStateException");
1059         } catch (MathIllegalStateException e) {
1060             // expected
1061         }
1062         try {
1063             m2.setSubMatrix(testData,1,0);
1064             fail("expecting MathIllegalStateException");
1065         } catch (MathIllegalStateException e) {
1066             // expected
1067         }
1068 
1069         // ragged
1070         try {
1071             m.setSubMatrix(new double[][] {{1}, {2, 3}}, 0, 0);
1072             fail("expecting MathIllegalArgumentException");
1073         } catch (MathIllegalArgumentException e) {
1074             // expected
1075         }
1076 
1077         // empty
1078         try {
1079             m.setSubMatrix(new double[][] {{}}, 0, 0);
1080             fail("expecting MathIllegalArgumentException");
1081         } catch (MathIllegalArgumentException e) {
1082             // expected
1083         }
1084     }
1085 
1086     @Test
1087     void testWalk() {
1088         int rows    = 150;
1089         int columns = 75;
1090 
1091         RealMatrix m = new Array2DRowRealMatrix(rows, columns);
1092         m.walkInRowOrder(new SetVisitor());
1093         GetVisitor getVisitor = new GetVisitor();
1094         m.walkInOptimizedOrder(getVisitor);
1095         assertEquals(rows * columns, getVisitor.getCount());
1096 
1097         m = new Array2DRowRealMatrix(rows, columns);
1098         m.walkInRowOrder(new SetVisitor(), 1, rows - 2, 1, columns - 2);
1099         getVisitor = new GetVisitor();
1100         m.walkInOptimizedOrder(getVisitor, 1, rows - 2, 1, columns - 2);
1101         assertEquals((rows - 2) * (columns - 2), getVisitor.getCount());
1102         for (int i = 0; i < rows; ++i) {
1103             assertEquals(0.0, m.getEntry(i, 0), 0);
1104             assertEquals(0.0, m.getEntry(i, columns - 1), 0);
1105         }
1106         for (int j = 0; j < columns; ++j) {
1107             assertEquals(0.0, m.getEntry(0, j), 0);
1108             assertEquals(0.0, m.getEntry(rows - 1, j), 0);
1109         }
1110 
1111         m = new Array2DRowRealMatrix(rows, columns);
1112         m.walkInColumnOrder(new SetVisitor());
1113         getVisitor = new GetVisitor();
1114         m.walkInOptimizedOrder(getVisitor);
1115         assertEquals(rows * columns, getVisitor.getCount());
1116 
1117         m = new Array2DRowRealMatrix(rows, columns);
1118         m.walkInColumnOrder(new SetVisitor(), 1, rows - 2, 1, columns - 2);
1119         getVisitor = new GetVisitor();
1120         m.walkInOptimizedOrder(getVisitor, 1, rows - 2, 1, columns - 2);
1121         assertEquals((rows - 2) * (columns - 2), getVisitor.getCount());
1122         for (int i = 0; i < rows; ++i) {
1123             assertEquals(0.0, m.getEntry(i, 0), 0);
1124             assertEquals(0.0, m.getEntry(i, columns - 1), 0);
1125         }
1126         for (int j = 0; j < columns; ++j) {
1127             assertEquals(0.0, m.getEntry(0, j), 0);
1128             assertEquals(0.0, m.getEntry(rows - 1, j), 0);
1129         }
1130 
1131         m = new Array2DRowRealMatrix(rows, columns);
1132         m.walkInOptimizedOrder(new SetVisitor());
1133         getVisitor = new GetVisitor();
1134         m.walkInRowOrder(getVisitor);
1135         assertEquals(rows * columns, getVisitor.getCount());
1136 
1137         m = new Array2DRowRealMatrix(rows, columns);
1138         m.walkInOptimizedOrder(new SetVisitor(), 1, rows - 2, 1, columns - 2);
1139         getVisitor = new GetVisitor();
1140         m.walkInRowOrder(getVisitor, 1, rows - 2, 1, columns - 2);
1141         assertEquals((rows - 2) * (columns - 2), getVisitor.getCount());
1142         for (int i = 0; i < rows; ++i) {
1143             assertEquals(0.0, m.getEntry(i, 0), 0);
1144             assertEquals(0.0, m.getEntry(i, columns - 1), 0);
1145         }
1146         for (int j = 0; j < columns; ++j) {
1147             assertEquals(0.0, m.getEntry(0, j), 0);
1148             assertEquals(0.0, m.getEntry(rows - 1, j), 0);
1149         }
1150 
1151         m = new Array2DRowRealMatrix(rows, columns);
1152         m.walkInOptimizedOrder(new SetVisitor());
1153         getVisitor = new GetVisitor();
1154         m.walkInColumnOrder(getVisitor);
1155         assertEquals(rows * columns, getVisitor.getCount());
1156 
1157         m = new Array2DRowRealMatrix(rows, columns);
1158         m.walkInOptimizedOrder(new SetVisitor(), 1, rows - 2, 1, columns - 2);
1159         getVisitor = new GetVisitor();
1160         m.walkInColumnOrder(getVisitor, 1, rows - 2, 1, columns - 2);
1161         assertEquals((rows - 2) * (columns - 2), getVisitor.getCount());
1162         for (int i = 0; i < rows; ++i) {
1163             assertEquals(0.0, m.getEntry(i, 0), 0);
1164             assertEquals(0.0, m.getEntry(i, columns - 1), 0);
1165         }
1166         for (int j = 0; j < columns; ++j) {
1167             assertEquals(0.0, m.getEntry(0, j), 0);
1168             assertEquals(0.0, m.getEntry(rows - 1, j), 0);
1169         }
1170     }
1171 
1172     @Test
1173     void testSerial()  {
1174         Array2DRowRealMatrix m = new Array2DRowRealMatrix(testData);
1175         assertEquals(m,UnitTestUtils.serializeAndRecover(m));
1176     }
1177 
1178 
1179     private static class SetVisitor extends DefaultRealMatrixChangingVisitor {
1180         @Override
1181         public double visit(int i, int j, double value) {
1182             return i + j / 1024.0;
1183         }
1184     }
1185 
1186     private static class GetVisitor extends DefaultRealMatrixPreservingVisitor {
1187         private int count = 0;
1188         @Override
1189         public void visit(int i, int j, double value) {
1190             ++count;
1191             assertEquals(i + j / 1024.0, value, 0.0);
1192         }
1193         public int getCount() {
1194             return count;
1195         }
1196     }
1197 
1198     //--------------- -----------------Protected methods
1199 
1200     /** extracts the l  and u matrices from compact lu representation */
1201     protected void splitLU(RealMatrix lu, double[][] lowerData, double[][] upperData) {
1202         if (!lu.isSquare()) {
1203             throw new MathIllegalArgumentException(LocalizedCoreFormats.NON_SQUARE_MATRIX,
1204                                                    lu.getRowDimension(), lu.getColumnDimension());
1205         }
1206         if (lowerData.length != lowerData[0].length) {
1207             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
1208                                                    lowerData.length, lowerData[0].length);
1209         }
1210         if (upperData.length != upperData[0].length) {
1211             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
1212                                                    upperData.length, upperData[0].length);
1213         }
1214         if (lowerData.length != upperData.length) {
1215             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
1216                                                    lowerData.length, upperData.length);
1217         }
1218         if (lowerData.length != lu.getRowDimension()) {
1219             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
1220                                                    lowerData.length, lu.getRowDimension());
1221         }
1222 
1223         int n = lu.getRowDimension();
1224         for (int i = 0; i < n; i++) {
1225             for (int j = 0; j < n; j++) {
1226                 if (j < i) {
1227                     lowerData[i][j] = lu.getEntry(i, j);
1228                     upperData[i][j] = 0d;
1229                 } else if (i == j) {
1230                     lowerData[i][j] = 1d;
1231                     upperData[i][j] = lu.getEntry(i, j);
1232                 } else {
1233                     lowerData[i][j] = 0d;
1234                     upperData[i][j] = lu.getEntry(i, j);
1235                 }
1236             }
1237         }
1238     }
1239 
1240     /** Returns the result of applying the given row permutation to the matrix */
1241     protected RealMatrix permuteRows(RealMatrix matrix, int[] permutation) {
1242         if (!matrix.isSquare()) {
1243             throw new MathIllegalArgumentException(LocalizedCoreFormats.NON_SQUARE_MATRIX,
1244                                                    matrix.getRowDimension(), matrix.getColumnDimension());
1245         }
1246         if (matrix.getRowDimension() != permutation.length) {
1247             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
1248                                                    matrix.getRowDimension(), permutation.length);
1249         }
1250 
1251         int n = matrix.getRowDimension();
1252         int m = matrix.getColumnDimension();
1253         double[][] out = new double[m][n];
1254         for (int i = 0; i < n; i++) {
1255             for (int j = 0; j < m; j++) {
1256                 out[i][j] = matrix.getEntry(permutation[i], j);
1257             }
1258         }
1259         return new Array2DRowRealMatrix(out);
1260     }
1261 
1262 //    /** Useful for debugging */
1263 //    private void dumpMatrix(RealMatrix m) {
1264 //          for (int i = 0; i < m.getRowDimension(); i++) {
1265 //              String os = "";
1266 //              for (int j = 0; j < m.getColumnDimension(); j++) {
1267 //                  os += m.getEntry(i, j) + " ";
1268 //              }
1269 //              System.out.println(os);
1270 //          }
1271 //    }
1272 
1273     static private final RealMatrixFormat f = new RealMatrixFormat("", "",
1274                                                                    "\n", "", "", "\t\t", new DecimalFormat(
1275                                                                                    " ##############0.0000;-##############0.0000"));
1276 
1277     @Test
1278     void testKroneckerProduct() {
1279         // AA = [-3 2;1 1];
1280         // BB = [1 0;0 1];
1281 
1282         RealMatrix A = MatrixUtils.createRealMatrix(new double[][] { { -3, 2 },
1283             { 1, 1 } });
1284         Array2DRowRealMatrix A_ = (Array2DRowRealMatrix) A;
1285 
1286         RealMatrix B = MatrixUtils.createRealMatrix(new double[][] { { 1, 0 },
1287             { 0, 1 } });
1288 
1289         RealMatrix C = A_.kroneckerProduct(B);
1290 
1291         assertNotNull(C);
1292 
1293         RealMatrix C_expected = MatrixUtils.createRealMatrix(new double[][] {
1294             { -3, 0, 2, 0 }, { -0, -3, 0, 2 }, { 1, 0, 1, 0 },
1295             { 0, 1, 0, 1 } });
1296         assertEquals(f.format(C_expected), f.format(C.scalarAdd(0)));
1297 
1298     }
1299 
1300     @Test
1301     void testStack() {
1302         // AA = [-3 2;1 1];
1303 
1304         RealMatrix A = MatrixUtils.createRealMatrix(new double[][] { { -3, 2 },
1305             { 1, 1 } });
1306         Array2DRowRealMatrix A_ = (Array2DRowRealMatrix) A;
1307 
1308         RealMatrix C = A_.stack();
1309 
1310         assertNotNull(C);
1311 
1312         RealMatrix C_expected = MatrixUtils.createRealMatrix(new double[][] {
1313             { -3 }, { 1 }, { 2 }, { 1 } });
1314         assertEquals(f.format(C_expected), f.format(C));
1315 
1316     }
1317 
1318     @Test
1319     void testUnstackSquare() {
1320         // AA = [-3 ;2;1; 1];
1321 
1322         RealMatrix A = MatrixUtils.createRealMatrix(new double[][] { { -3 },
1323             { 1 }, { 2 }, { 1 } });
1324         Array2DRowRealMatrix A_ = (Array2DRowRealMatrix) A;
1325 
1326         RealMatrix C = A_.unstackSquare();
1327 
1328         assertNotNull(C);
1329 
1330         RealMatrix C_expected = MatrixUtils.createRealMatrix(new double[][] {
1331             { -3, 2 }, { 1, 1 } });
1332         assertEquals(f.format(C_expected), f.format(C));
1333 
1334     }
1335 
1336     @Test
1337     void testUnstackNotsquare() {
1338         assertThrows(MathIllegalArgumentException.class, () -> {
1339             // AA = [-3 ;2;1; 1;1];
1340 
1341             RealMatrix A = MatrixUtils.createRealMatrix(new double[][]{{-3},
1342                 {1}, {2}, {1}, {1}});
1343             Array2DRowRealMatrix A_ = (Array2DRowRealMatrix) A;
1344 
1345             A_.unstackSquare();
1346         });
1347     }
1348 }
1349