1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.math4.legacy.linear;
18
19 import java.math.BigDecimal;
20
21 import org.apache.commons.math4.legacy.TestUtils;
22 import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
23 import org.apache.commons.math4.legacy.exception.NotStrictlyPositiveException;
24 import org.apache.commons.math4.legacy.exception.NullArgumentException;
25 import org.apache.commons.math4.legacy.exception.OutOfRangeException;
26 import org.apache.commons.math4.legacy.core.dfp.Dfp;
27 import org.junit.Assert;
28 import org.junit.Test;
29
30
31
32
33
34
35 public final class MatrixUtilsTest {
36
37 protected double[][] testData = { {1d,2d,3d}, {2d,5d,3d}, {1d,0d,8d} };
38 protected double[][] testData3x3Singular = { { 1, 4, 7, }, { 2, 5, 8, }, { 3, 6, 9, } };
39 protected double[][] testData3x4 = { { 12, -51, 4, 1 }, { 6, 167, -68, 2 }, { -4, 24, -41, 3 } };
40 protected double[][] nullMatrix = null;
41 protected double[] row = {1,2,3};
42 protected BigDecimal[] bigRow =
43 {new BigDecimal(1),new BigDecimal(2),new BigDecimal(3)};
44 protected String[] stringRow = {"1", "2", "3"};
45 protected Dfp[] fractionRow =
46 {Dfp25.of(1),Dfp25.of(2),Dfp25.of(3)};
47 protected double[][] rowMatrix = {{1,2,3}};
48 protected BigDecimal[][] bigRowMatrix =
49 {{new BigDecimal(1), new BigDecimal(2), new BigDecimal(3)}};
50 protected String[][] stringRowMatrix = {{"1", "2", "3"}};
51 protected Dfp[][] fractionRowMatrix =
52 {{Dfp25.of(1), Dfp25.of(2), Dfp25.of(3)}};
53 protected double[] col = {0,4,6};
54 protected BigDecimal[] bigCol =
55 {new BigDecimal(0),new BigDecimal(4),new BigDecimal(6)};
56 protected String[] stringCol = {"0","4","6"};
57 protected Dfp[] fractionCol =
58 {Dfp25.of(0),Dfp25.of(4),Dfp25.of(6)};
59 protected double[] nullDoubleArray = null;
60 protected double[][] colMatrix = {{0},{4},{6}};
61 protected BigDecimal[][] bigColMatrix =
62 {{new BigDecimal(0)},{new BigDecimal(4)},{new BigDecimal(6)}};
63 protected String[][] stringColMatrix = {{"0"}, {"4"}, {"6"}};
64 protected Dfp[][] fractionColMatrix =
65 {{Dfp25.of(0)},{Dfp25.of(4)},{Dfp25.of(6)}};
66
67 @Test
68 public void testCreateRealMatrix() {
69 Assert.assertEquals(new BlockRealMatrix(testData),
70 MatrixUtils.createRealMatrix(testData));
71 try {
72 MatrixUtils.createRealMatrix(new double[][] {{1}, {1,2}});
73 Assert.fail("Expecting MathIllegalArgumentException");
74 } catch (MathIllegalArgumentException ex) {
75
76 }
77 try {
78 MatrixUtils.createRealMatrix(new double[][] {{}, {}});
79 Assert.fail("Expecting MathIllegalArgumentException");
80 } catch (MathIllegalArgumentException ex) {
81
82 }
83 try {
84 MatrixUtils.createRealMatrix(null);
85 Assert.fail("Expecting NullArgumentException");
86 } catch (NullArgumentException ex) {
87
88 }
89 }
90
91 @Test
92 public void testcreateFieldMatrix() {
93 Assert.assertEquals(new Array2DRowFieldMatrix<>(asDfp(testData)),
94 MatrixUtils.createFieldMatrix(asDfp(testData)));
95 Assert.assertEquals(new Array2DRowFieldMatrix<>(Dfp25.getField(), fractionColMatrix),
96 MatrixUtils.createFieldMatrix(fractionColMatrix));
97 try {
98 MatrixUtils.createFieldMatrix(asDfp(new double[][] {{1}, {1,2}}));
99 Assert.fail("Expecting MathIllegalArgumentException");
100 } catch (MathIllegalArgumentException ex) {
101
102 }
103 try {
104 MatrixUtils.createFieldMatrix(asDfp(new double[][] {{}, {}}));
105 Assert.fail("Expecting MathIllegalArgumentException");
106 } catch (MathIllegalArgumentException ex) {
107
108 }
109 try {
110 MatrixUtils.createFieldMatrix((Dfp[][])null);
111 Assert.fail("Expecting NullArgumentException");
112 } catch (NullArgumentException ex) {
113
114 }
115 }
116
117 @Test
118 public void testCreateRowRealMatrix() {
119 Assert.assertEquals(MatrixUtils.createRowRealMatrix(row),
120 new BlockRealMatrix(rowMatrix));
121 try {
122 MatrixUtils.createRowRealMatrix(new double[] {});
123 Assert.fail("Expecting NotStrictlyPositiveException");
124 } catch (NotStrictlyPositiveException ex) {
125
126 }
127 try {
128 MatrixUtils.createRowRealMatrix(null);
129 Assert.fail("Expecting NullArgumentException");
130 } catch (NullArgumentException ex) {
131
132 }
133 }
134
135 @Test
136 public void testCreateRowFieldMatrix() {
137 Assert.assertEquals(MatrixUtils.createRowFieldMatrix(asDfp(row)),
138 new Array2DRowFieldMatrix<>(asDfp(rowMatrix)));
139 Assert.assertEquals(MatrixUtils.createRowFieldMatrix(fractionRow),
140 new Array2DRowFieldMatrix<>(fractionRowMatrix));
141 try {
142 MatrixUtils.createRowFieldMatrix(new Dfp[] {});
143 Assert.fail("Expecting MathIllegalArgumentException");
144 } catch (MathIllegalArgumentException ex) {
145
146 }
147 try {
148 MatrixUtils.createRowFieldMatrix((Dfp[]) null);
149 Assert.fail("Expecting NullArgumentException");
150 } catch (NullArgumentException ex) {
151
152 }
153 }
154
155 @Test
156 public void testCreateColumnRealMatrix() {
157 Assert.assertEquals(MatrixUtils.createColumnRealMatrix(col),
158 new BlockRealMatrix(colMatrix));
159 try {
160 MatrixUtils.createColumnRealMatrix(new double[] {});
161 Assert.fail("Expecting MathIllegalArgumentException");
162 } catch (MathIllegalArgumentException ex) {
163
164 }
165 try {
166 MatrixUtils.createColumnRealMatrix(null);
167 Assert.fail("Expecting NullArgumentException");
168 } catch (NullArgumentException ex) {
169
170 }
171 }
172
173 @Test
174 public void testCreateColumnFieldMatrix() {
175 Assert.assertEquals(MatrixUtils.createColumnFieldMatrix(asDfp(col)),
176 new Array2DRowFieldMatrix<>(asDfp(colMatrix)));
177 Assert.assertEquals(MatrixUtils.createColumnFieldMatrix(fractionCol),
178 new Array2DRowFieldMatrix<>(fractionColMatrix));
179
180 try {
181 MatrixUtils.createColumnFieldMatrix(new Dfp[] {});
182 Assert.fail("Expecting MathIllegalArgumentException");
183 } catch (MathIllegalArgumentException ex) {
184
185 }
186 try {
187 MatrixUtils.createColumnFieldMatrix((Dfp[]) null);
188 Assert.fail("Expecting NullArgumentException");
189 } catch (NullArgumentException ex) {
190
191 }
192 }
193
194
195
196
197 protected void checkIdentityMatrix(RealMatrix m) {
198 for (int i = 0; i < m.getRowDimension(); i++) {
199 for (int j =0; j < m.getColumnDimension(); j++) {
200 if (i == j) {
201 Assert.assertEquals(m.getEntry(i, j), 1d, 0);
202 } else {
203 Assert.assertEquals(m.getEntry(i, j), 0d, 0);
204 }
205 }
206 }
207 }
208
209 @Test
210 public void testCreateIdentityMatrix() {
211 checkIdentityMatrix(MatrixUtils.createRealIdentityMatrix(3));
212 checkIdentityMatrix(MatrixUtils.createRealIdentityMatrix(2));
213 checkIdentityMatrix(MatrixUtils.createRealIdentityMatrix(1));
214 try {
215 MatrixUtils.createRealIdentityMatrix(0);
216 Assert.fail("Expecting MathIllegalArgumentException");
217 } catch (MathIllegalArgumentException ex) {
218
219 }
220 }
221
222
223
224
225 protected void checkIdentityFieldMatrix(FieldMatrix<Dfp> m) {
226 for (int i = 0; i < m.getRowDimension(); i++) {
227 for (int j =0; j < m.getColumnDimension(); j++) {
228 if (i == j) {
229 Assert.assertEquals(m.getEntry(i, j), Dfp25.ONE);
230 } else {
231 Assert.assertEquals(m.getEntry(i, j), Dfp25.ZERO);
232 }
233 }
234 }
235 }
236
237 @Test
238 public void testcreateFieldIdentityMatrix() {
239 checkIdentityFieldMatrix(MatrixUtils.createFieldIdentityMatrix(Dfp25.getField(), 3));
240 checkIdentityFieldMatrix(MatrixUtils.createFieldIdentityMatrix(Dfp25.getField(), 2));
241 checkIdentityFieldMatrix(MatrixUtils.createFieldIdentityMatrix(Dfp25.getField(), 1));
242 try {
243 MatrixUtils.createRealIdentityMatrix(0);
244 Assert.fail("Expecting MathIllegalArgumentException");
245 } catch (MathIllegalArgumentException ex) {
246
247 }
248 }
249
250 public static Dfp[][] asDfp(double[][] data) {
251 Dfp d[][] = new Dfp[data.length][];
252 for (int i = 0; i < data.length; ++i) {
253 double[] dataI = data[i];
254 Dfp[] dI = new Dfp[dataI.length];
255 for (int j = 0; j < dataI.length; ++j) {
256 dI[j] = Dfp25.of(dataI[j]);
257 }
258 d[i] = dI;
259 }
260 return d;
261 }
262
263 public static Dfp[] asDfp(double[] data) {
264 Dfp d[] = new Dfp[data.length];
265 for (int i = 0; i < data.length; ++i) {
266 d[i] = Dfp25.of(data[i]);
267 }
268
269 return d;
270 }
271
272 @Test
273 public void testSolveLowerTriangularSystem(){
274 RealMatrix rm = new Array2DRowRealMatrix(
275 new double[][] { {2,0,0,0 }, { 1,1,0,0 }, { 3,3,3,0 }, { 3,3,3,4 } },
276 false);
277 RealVector b = new ArrayRealVector(new double[] { 2,3,4,8 }, false);
278 MatrixUtils.solveLowerTriangularSystem(rm, b);
279 TestUtils.assertEquals( new double[]{1,2,-1.66666666666667, 1.0} , b.toArray() , 1.0e-12);
280 }
281
282
283
284
285
286 @Test
287 public void testSolveUpperTriangularSystem(){
288 RealMatrix rm = new Array2DRowRealMatrix(
289 new double[][] { {1,2,3 }, { 0,1,1 }, { 0,0,2 } },
290 false);
291 RealVector b = new ArrayRealVector(new double[] { 8,4,2 }, false);
292 MatrixUtils.solveUpperTriangularSystem(rm, b);
293 TestUtils.assertEquals( new double[]{-1,3,1} , b.toArray() , 1.0e-12);
294 }
295
296
297
298
299
300
301 @Test
302 public void testBlockInverse() {
303 final double[][] data = {
304 { -1, 0, 123, 4 },
305 { -56, 78.9, -0.1, -23.4 },
306 { 5.67, 8, -9, 1011 },
307 { 12, 345, -67.8, 9 },
308 };
309
310 final RealMatrix m = new Array2DRowRealMatrix(data);
311 final int len = data.length;
312 final double tol = 1e-14;
313
314 for (int splitIndex = 0; splitIndex < 3; splitIndex++) {
315 final RealMatrix mInv = MatrixUtils.blockInverse(m, splitIndex);
316 final RealMatrix id = m.multiply(mInv);
317
318
319 for (int i = 0; i < len; i++) {
320 for (int j = 0; j < len; j++) {
321 final double entry = id.getEntry(i, j);
322 if (i == j) {
323 Assert.assertEquals("[" + i + "][" + j + "]",
324 1, entry, tol);
325 } else {
326 Assert.assertEquals("[" + i + "][" + j + "]",
327 0, entry, tol);
328 }
329 }
330 }
331 }
332 }
333
334 @Test(expected=SingularMatrixException.class)
335 public void testBlockInverseNonInvertible() {
336 final double[][] data = {
337 { -1, 0, 123, 4 },
338 { -56, 78.9, -0.1, -23.4 },
339 { 5.67, 8, -9, 1011 },
340 { 5.67, 8, -9, 1011 },
341 };
342
343 MatrixUtils.blockInverse(new Array2DRowRealMatrix(data), 2);
344 }
345
346 @Test
347 public void testIsSymmetric() {
348 final double eps = Math.ulp(1d);
349
350 final double[][] dataSym = {
351 { 1, 2, 3 },
352 { 2, 2, 5 },
353 { 3, 5, 6 },
354 };
355 Assert.assertTrue(MatrixUtils.isSymmetric(MatrixUtils.createRealMatrix(dataSym), eps));
356
357 final double[][] dataNonSym = {
358 { 1, 2, -3 },
359 { 2, 2, 5 },
360 { 3, 5, 6 },
361 };
362 Assert.assertFalse(MatrixUtils.isSymmetric(MatrixUtils.createRealMatrix(dataNonSym), eps));
363 }
364
365 @Test
366 public void testIsSymmetricTolerance() {
367 final double eps = 1e-4;
368
369 final double[][] dataSym1 = {
370 { 1, 1, 1.00009 },
371 { 1, 1, 1 },
372 { 1.0, 1, 1 },
373 };
374 Assert.assertTrue(MatrixUtils.isSymmetric(MatrixUtils.createRealMatrix(dataSym1), eps));
375 final double[][] dataSym2 = {
376 { 1, 1, 0.99990 },
377 { 1, 1, 1 },
378 { 1.0, 1, 1 },
379 };
380 Assert.assertTrue(MatrixUtils.isSymmetric(MatrixUtils.createRealMatrix(dataSym2), eps));
381
382 final double[][] dataNonSym1 = {
383 { 1, 1, 1.00011 },
384 { 1, 1, 1 },
385 { 1.0, 1, 1 },
386 };
387 Assert.assertFalse(MatrixUtils.isSymmetric(MatrixUtils.createRealMatrix(dataNonSym1), eps));
388 final double[][] dataNonSym2 = {
389 { 1, 1, 0.99989 },
390 { 1, 1, 1 },
391 { 1.0, 1, 1 },
392 };
393 Assert.assertFalse(MatrixUtils.isSymmetric(MatrixUtils.createRealMatrix(dataNonSym2), eps));
394 }
395
396 @Test
397 public void testCheckSymmetric1() {
398 final double[][] dataSym = {
399 { 1, 2, 3 },
400 { 2, 2, 5 },
401 { 3, 5, 6 },
402 };
403 MatrixUtils.checkSymmetric(MatrixUtils.createRealMatrix(dataSym), Math.ulp(1d));
404 }
405
406 @Test(expected=NonSymmetricMatrixException.class)
407 public void testCheckSymmetric2() {
408 final double[][] dataNonSym = {
409 { 1, 2, -3 },
410 { 2, 2, 5 },
411 { 3, 5, 6 },
412 };
413 MatrixUtils.checkSymmetric(MatrixUtils.createRealMatrix(dataNonSym), Math.ulp(1d));
414 }
415
416 @Test(expected=SingularMatrixException.class)
417 public void testInverseSingular() {
418 RealMatrix m = MatrixUtils.createRealMatrix(testData3x3Singular);
419 MatrixUtils.inverse(m);
420 }
421
422 @Test(expected=NonSquareMatrixException.class)
423 public void testInverseNonSquare() {
424 RealMatrix m = MatrixUtils.createRealMatrix(testData3x4);
425 MatrixUtils.inverse(m);
426 }
427
428 @Test
429 public void testInverseDiagonalMatrix() {
430 final double[] data = { 1, 2, 3 };
431 final RealMatrix m = new DiagonalMatrix(data);
432 final RealMatrix inverse = MatrixUtils.inverse(m);
433
434 final RealMatrix result = m.multiply(inverse);
435 TestUtils.assertEquals("MatrixUtils.inverse() returns wrong result",
436 MatrixUtils.createRealIdentityMatrix(data.length), result, Math.ulp(1d));
437 }
438
439 @Test
440 public void testInverseRealMatrix() {
441 RealMatrix m = MatrixUtils.createRealMatrix(testData);
442 final RealMatrix inverse = MatrixUtils.inverse(m);
443
444 final RealMatrix result = m.multiply(inverse);
445 TestUtils.assertEquals("MatrixUtils.inverse() returns wrong result",
446 MatrixUtils.createRealIdentityMatrix(testData.length), result, 1e-12);
447 }
448
449 @Test
450 public void testCheckMatrixRowIndexError() {
451 try {
452 AnyMatrix m = MatrixUtils.createRealMatrix(new double[][] {{9,9}, {9,9}, {9,9}});
453 MatrixUtils.checkRowIndex(m, 4);
454 Assert.fail("expected an OutOfRangeException");
455 } catch (OutOfRangeException e) {
456 String s = e.getMessage();
457 int topIx = s.indexOf('2');
458 int botIx = s.indexOf('0');
459 int rowIx = s.indexOf('4');
460 if (topIx < 0 || botIx < 0 || rowIx < 0) {
461 Assert.fail("expected a message like index 4 is not in 0..3, not: " + s);
462 }
463 } catch (Exception e) {
464 Assert.fail("expected an OutOfRange exception, not: " +
465 e.getClass().getName() + ": " + e.getMessage());
466 }
467 }
468
469 @Test
470 public void testCheckMatrixColIndexError() {
471 try {
472 AnyMatrix m = MatrixUtils.createRealMatrix(new double[][] {{9,9}, {9,9}, {9,9}});
473 MatrixUtils.checkColumnIndex(m, 4);
474 Assert.fail("expected an OutOfRangeException");
475 } catch (OutOfRangeException e) {
476 String s = e.getMessage();
477 int topIx = s.indexOf('1');
478 int botIx = s.indexOf('0');
479 int rowIx = s.indexOf('4');
480 if (topIx < 0 || botIx < 0 || rowIx < 0) {
481 Assert.fail("expected a message like index 4 is not in 0..3, not: " + s);
482 }
483 } catch (Exception e) {
484 Assert.fail("expected an OutOfRange exception, not: " +
485 e.getClass().getName() + ": " + e.getMessage());
486 }
487 }
488 }