1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.hipparchus.linear;
24
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.List;
28
29 import org.hipparchus.CalculusFieldElement;
30 import org.hipparchus.Field;
31 import org.hipparchus.FieldElement;
32 import org.hipparchus.exception.LocalizedCoreFormats;
33 import org.hipparchus.exception.MathIllegalArgumentException;
34 import org.hipparchus.exception.MathRuntimeException;
35 import org.hipparchus.exception.NullArgumentException;
36 import org.hipparchus.fraction.BigFraction;
37 import org.hipparchus.fraction.Fraction;
38 import org.hipparchus.util.FastMath;
39 import org.hipparchus.util.MathArrays;
40 import org.hipparchus.util.MathUtils;
41 import org.hipparchus.util.Precision;
42
43
44
45
46
47 public class MatrixUtils {
48
49
50
51
52 public static final RealMatrixFormat DEFAULT_FORMAT = RealMatrixFormat.getRealMatrixFormat();
53
54
55
56
57 public static final RealMatrixFormat OCTAVE_FORMAT = new RealMatrixFormat("[", "]", "", "", "; ", ", ");
58
59
60 private static final double[] PADE_COEFFICIENTS_3 = {
61 120.0,
62 60.0,
63 12.0,
64 1.0
65 };
66
67
68 private static final double[] PADE_COEFFICIENTS_5 = {
69 30240.0,
70 15120.0,
71 3360.0,
72 420.0,
73 30.0,
74 1
75 };
76
77
78 private static final double[] PADE_COEFFICIENTS_7 = {
79 17297280.0,
80 8648640.0,
81 1995840.0,
82 277200.0,
83 25200.0,
84 1512.0,
85 56.0,
86 1.0
87 };
88
89
90 private static final double[] PADE_COEFFICIENTS_9 = {
91 17643225600.0,
92 8821612800.0,
93 2075673600.0,
94 302702400.0,
95 30270240.0,
96 2162160.0,
97 110880.0,
98 3960.0,
99 90.0,
100 1.0
101 };
102
103
104 private static final double[] PADE_COEFFICIENTS_13 = {
105 6.476475253248e+16,
106 3.238237626624e+16,
107 7.7717703038976e+15,
108 1.1873537964288e+15,
109 129060195264000.0,
110 10559470521600.0,
111 670442572800.0,
112 33522128640.0,
113 1323241920.0,
114 40840800.0,
115 960960.0,
116 16380.0,
117 182.0,
118 1.0
119 };
120
121
122
123
124 private MatrixUtils() {
125 super();
126 }
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141 public static RealMatrix createRealMatrix(final int rows, final int columns) {
142 return (rows * columns <= 4096) ?
143 new Array2DRowRealMatrix(rows, columns) : new BlockRealMatrix(rows, columns);
144 }
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160 public static <T extends FieldElement<T>> FieldMatrix<T> createFieldMatrix(final Field<T> field,
161 final int rows,
162 final int columns) {
163 return (rows * columns <= 4096) ?
164 new Array2DRowFieldMatrix<T>(field, rows, columns) : new BlockFieldMatrix<T>(field, rows, columns);
165 }
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187 public static RealMatrix createRealMatrix(double[][] data)
188 throws MathIllegalArgumentException, NullArgumentException {
189 if (data == null ||
190 data[0] == null) {
191 throw new NullArgumentException();
192 }
193 return (data.length * data[0].length <= 4096) ?
194 new Array2DRowRealMatrix(data) : new BlockRealMatrix(data);
195 }
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215 public static <T extends FieldElement<T>> FieldMatrix<T> createFieldMatrix(T[][] data)
216 throws MathIllegalArgumentException, NullArgumentException {
217 if (data == null ||
218 data[0] == null) {
219 throw new NullArgumentException();
220 }
221 return (data.length * data[0].length <= 4096) ?
222 new Array2DRowFieldMatrix<T>(data) : new BlockFieldMatrix<T>(data);
223 }
224
225
226
227
228
229
230
231
232 public static RealMatrix createRealIdentityMatrix(int dimension) {
233 final RealMatrix m = createRealMatrix(dimension, dimension);
234 for (int i = 0; i < dimension; ++i) {
235 m.setEntry(i, i, 1.0);
236 }
237 return m;
238 }
239
240
241
242
243
244
245
246
247
248
249 public static <T extends FieldElement<T>> FieldMatrix<T>
250 createFieldIdentityMatrix(final Field<T> field, final int dimension) {
251 final T zero = field.getZero();
252 final T one = field.getOne();
253 final T[][] d = MathArrays.buildArray(field, dimension, dimension);
254 for (int row = 0; row < dimension; row++) {
255 final T[] dRow = d[row];
256 Arrays.fill(dRow, zero);
257 dRow[row] = one;
258 }
259 return new Array2DRowFieldMatrix<T>(field, d, false);
260 }
261
262
263
264
265
266
267
268
269 public static RealMatrix createRealDiagonalMatrix(final double[] diagonal) {
270 final RealMatrix m = createRealMatrix(diagonal.length, diagonal.length);
271 for (int i = 0; i < diagonal.length; ++i) {
272 m.setEntry(i, i, diagonal[i]);
273 }
274 return m;
275 }
276
277
278
279
280
281
282
283
284
285 public static <T extends FieldElement<T>> FieldMatrix<T>
286 createFieldDiagonalMatrix(final T[] diagonal) {
287 final FieldMatrix<T> m =
288 createFieldMatrix(diagonal[0].getField(), diagonal.length, diagonal.length);
289 for (int i = 0; i < diagonal.length; ++i) {
290 m.setEntry(i, i, diagonal[i]);
291 }
292 return m;
293 }
294
295
296
297
298
299
300
301
302
303 public static RealVector createRealVector(double[] data)
304 throws MathIllegalArgumentException, NullArgumentException {
305 if (data == null) {
306 throw new NullArgumentException();
307 }
308 return new ArrayRealVector(data, true);
309 }
310
311
312
313
314
315
316
317
318 public static RealVector createRealVector(final int dimension) {
319 return new ArrayRealVector(new double[dimension]);
320 }
321
322
323
324
325
326
327
328
329
330
331
332 public static <T extends FieldElement<T>> FieldVector<T> createFieldVector(final T[] data)
333 throws MathIllegalArgumentException, NullArgumentException {
334 if (data == null) {
335 throw new NullArgumentException();
336 }
337 if (data.length == 0) {
338 throw new MathIllegalArgumentException(LocalizedCoreFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
339 }
340 return new ArrayFieldVector<T>(data[0].getField(), data, true);
341 }
342
343
344
345
346
347
348
349
350
351
352 public static <T extends FieldElement<T>> FieldVector<T> createFieldVector(final Field<T> field, final int dimension) {
353 return new ArrayFieldVector<>(MathArrays.buildArray(field, dimension));
354 }
355
356
357
358
359
360
361
362
363
364
365 public static RealMatrix createRowRealMatrix(double[] rowData)
366 throws MathIllegalArgumentException, NullArgumentException {
367 if (rowData == null) {
368 throw new NullArgumentException();
369 }
370 final int nCols = rowData.length;
371 final RealMatrix m = createRealMatrix(1, nCols);
372 for (int i = 0; i < nCols; ++i) {
373 m.setEntry(0, i, rowData[i]);
374 }
375 return m;
376 }
377
378
379
380
381
382
383
384
385
386
387
388 public static <T extends FieldElement<T>> FieldMatrix<T>
389 createRowFieldMatrix(final T[] rowData)
390 throws MathIllegalArgumentException, NullArgumentException {
391 if (rowData == null) {
392 throw new NullArgumentException();
393 }
394 final int nCols = rowData.length;
395 if (nCols == 0) {
396 throw new MathIllegalArgumentException(LocalizedCoreFormats.AT_LEAST_ONE_COLUMN);
397 }
398 final FieldMatrix<T> m = createFieldMatrix(rowData[0].getField(), 1, nCols);
399 for (int i = 0; i < nCols; ++i) {
400 m.setEntry(0, i, rowData[i]);
401 }
402 return m;
403 }
404
405
406
407
408
409
410
411
412
413
414 public static RealMatrix createColumnRealMatrix(double[] columnData)
415 throws MathIllegalArgumentException, NullArgumentException {
416 if (columnData == null) {
417 throw new NullArgumentException();
418 }
419 final int nRows = columnData.length;
420 final RealMatrix m = createRealMatrix(nRows, 1);
421 for (int i = 0; i < nRows; ++i) {
422 m.setEntry(i, 0, columnData[i]);
423 }
424 return m;
425 }
426
427
428
429
430
431
432
433
434
435
436
437 public static <T extends FieldElement<T>> FieldMatrix<T>
438 createColumnFieldMatrix(final T[] columnData)
439 throws MathIllegalArgumentException, NullArgumentException {
440 if (columnData == null) {
441 throw new NullArgumentException();
442 }
443 final int nRows = columnData.length;
444 if (nRows == 0) {
445 throw new MathIllegalArgumentException(LocalizedCoreFormats.AT_LEAST_ONE_ROW);
446 }
447 final FieldMatrix<T> m = createFieldMatrix(columnData[0].getField(), nRows, 1);
448 for (int i = 0; i < nRows; ++i) {
449 m.setEntry(i, 0, columnData[i]);
450 }
451 return m;
452 }
453
454
455
456
457
458
459
460
461
462
463
464
465 private static boolean isSymmetricInternal(RealMatrix matrix,
466 double relativeTolerance,
467 boolean raiseException) {
468 final int rows = matrix.getRowDimension();
469 if (rows != matrix.getColumnDimension()) {
470 if (raiseException) {
471 throw new MathIllegalArgumentException(LocalizedCoreFormats.NON_SQUARE_MATRIX,
472 rows, matrix.getColumnDimension());
473 } else {
474 return false;
475 }
476 }
477 for (int i = 0; i < rows; i++) {
478 for (int j = i + 1; j < rows; j++) {
479 final double mij = matrix.getEntry(i, j);
480 final double mji = matrix.getEntry(j, i);
481 if (FastMath.abs(mij - mji) >
482 FastMath.max(FastMath.abs(mij), FastMath.abs(mji)) * relativeTolerance) {
483 if (raiseException) {
484 throw new MathIllegalArgumentException(LocalizedCoreFormats.NON_SYMMETRIC_MATRIX,
485 i, j, relativeTolerance);
486 } else {
487 return false;
488 }
489 }
490 }
491 }
492 return true;
493 }
494
495
496
497
498
499
500
501
502
503 public static void checkSymmetric(RealMatrix matrix,
504 double eps) {
505 isSymmetricInternal(matrix, eps, true);
506 }
507
508
509
510
511
512
513
514
515 public static boolean isSymmetric(RealMatrix matrix,
516 double eps) {
517 return isSymmetricInternal(matrix, eps, false);
518 }
519
520
521
522
523
524
525
526
527
528
529 public static void checkMatrixIndex(final AnyMatrix m,
530 final int row, final int column)
531 throws MathIllegalArgumentException {
532 checkRowIndex(m, row);
533 checkColumnIndex(m, column);
534 }
535
536
537
538
539
540
541
542
543 public static void checkRowIndex(final AnyMatrix m, final int row)
544 throws MathIllegalArgumentException {
545 if (row < 0 ||
546 row >= m.getRowDimension()) {
547 throw new MathIllegalArgumentException(LocalizedCoreFormats.ROW_INDEX,
548 row, 0, m.getRowDimension() - 1);
549 }
550 }
551
552
553
554
555
556
557
558
559 public static void checkColumnIndex(final AnyMatrix m, final int column)
560 throws MathIllegalArgumentException {
561 if (column < 0 || column >= m.getColumnDimension()) {
562 throw new MathIllegalArgumentException(LocalizedCoreFormats.COLUMN_INDEX,
563 column, 0, m.getColumnDimension() - 1);
564 }
565 }
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580 public static void checkSubMatrixIndex(final AnyMatrix m,
581 final int startRow, final int endRow,
582 final int startColumn, final int endColumn)
583 throws MathIllegalArgumentException {
584 checkRowIndex(m, startRow);
585 checkRowIndex(m, endRow);
586 if (endRow < startRow) {
587 throw new MathIllegalArgumentException(LocalizedCoreFormats.INITIAL_ROW_AFTER_FINAL_ROW,
588 endRow, startRow, false);
589 }
590
591 checkColumnIndex(m, startColumn);
592 checkColumnIndex(m, endColumn);
593 if (endColumn < startColumn) {
594 throw new MathIllegalArgumentException(LocalizedCoreFormats.INITIAL_COLUMN_AFTER_FINAL_COLUMN,
595 endColumn, startColumn, false);
596 }
597
598
599 }
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614 public static void checkSubMatrixIndex(final AnyMatrix m,
615 final int[] selectedRows,
616 final int[] selectedColumns)
617 throws MathIllegalArgumentException, NullArgumentException {
618 if (selectedRows == null) {
619 throw new NullArgumentException();
620 }
621 if (selectedColumns == null) {
622 throw new NullArgumentException();
623 }
624 if (selectedRows.length == 0) {
625 throw new MathIllegalArgumentException(LocalizedCoreFormats.EMPTY_SELECTED_ROW_INDEX_ARRAY);
626 }
627 if (selectedColumns.length == 0) {
628 throw new MathIllegalArgumentException(LocalizedCoreFormats.EMPTY_SELECTED_COLUMN_INDEX_ARRAY);
629 }
630
631 for (final int row : selectedRows) {
632 checkRowIndex(m, row);
633 }
634 for (final int column : selectedColumns) {
635 checkColumnIndex(m, column);
636 }
637 }
638
639
640
641
642
643
644
645
646
647 public static void checkAdditionCompatible(final AnyMatrix left, final AnyMatrix right)
648 throws MathIllegalArgumentException {
649 if ((left.getRowDimension() != right.getRowDimension()) ||
650 (left.getColumnDimension() != right.getColumnDimension())) {
651 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH_2x2,
652 left.getRowDimension(), left.getColumnDimension(),
653 right.getRowDimension(), right.getColumnDimension());
654 }
655 }
656
657
658
659
660
661
662
663
664
665 public static void checkSubtractionCompatible(final AnyMatrix left, final AnyMatrix right)
666 throws MathIllegalArgumentException {
667 if ((left.getRowDimension() != right.getRowDimension()) ||
668 (left.getColumnDimension() != right.getColumnDimension())) {
669 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH_2x2,
670 left.getRowDimension(), left.getColumnDimension(),
671 right.getRowDimension(), right.getColumnDimension());
672 }
673 }
674
675
676
677
678
679
680
681
682
683 public static void checkMultiplicationCompatible(final AnyMatrix left, final AnyMatrix right)
684 throws MathIllegalArgumentException {
685 if (left.getColumnDimension() != right.getRowDimension()) {
686 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
687 left.getColumnDimension(), right.getRowDimension());
688 }
689 }
690
691
692
693
694
695
696
697
698
699 public static void checkSameColumnDimension(final AnyMatrix left, final AnyMatrix right)
700 throws MathIllegalArgumentException {
701 if (left.getColumnDimension() != right.getColumnDimension()) {
702 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
703 left.getColumnDimension(), right.getColumnDimension());
704 }
705 }
706
707
708
709
710
711
712
713
714
715 public static void checkSameRowDimension(final AnyMatrix left, final AnyMatrix right)
716 throws MathIllegalArgumentException {
717 if (left.getRowDimension() != right.getRowDimension()) {
718 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
719 left.getRowDimension(), right.getRowDimension());
720 }
721 }
722
723
724
725
726
727
728 public static Array2DRowRealMatrix fractionMatrixToRealMatrix(final FieldMatrix<Fraction> m) {
729 final FractionMatrixConverter converter = new FractionMatrixConverter();
730 m.walkInOptimizedOrder(converter);
731 return converter.getConvertedMatrix();
732 }
733
734
735 private static class FractionMatrixConverter extends DefaultFieldMatrixPreservingVisitor<Fraction> {
736
737 private double[][] data;
738
739 FractionMatrixConverter() {
740 super(Fraction.ZERO);
741 }
742
743
744 @Override
745 public void start(int rows, int columns,
746 int startRow, int endRow, int startColumn, int endColumn) {
747 data = new double[rows][columns];
748 }
749
750
751 @Override
752 public void visit(int row, int column, Fraction value) {
753 data[row][column] = value.doubleValue();
754 }
755
756
757
758
759
760
761 Array2DRowRealMatrix getConvertedMatrix() {
762 return new Array2DRowRealMatrix(data, false);
763 }
764
765 }
766
767
768
769
770
771
772
773 public static Array2DRowRealMatrix bigFractionMatrixToRealMatrix(final FieldMatrix<BigFraction> m) {
774 final BigFractionMatrixConverter converter = new BigFractionMatrixConverter();
775 m.walkInOptimizedOrder(converter);
776 return converter.getConvertedMatrix();
777 }
778
779
780 private static class BigFractionMatrixConverter extends DefaultFieldMatrixPreservingVisitor<BigFraction> {
781
782 private double[][] data;
783
784 BigFractionMatrixConverter() {
785 super(BigFraction.ZERO);
786 }
787
788
789 @Override
790 public void start(int rows, int columns,
791 int startRow, int endRow, int startColumn, int endColumn) {
792 data = new double[rows][columns];
793 }
794
795
796 @Override
797 public void visit(int row, int column, BigFraction value) {
798 data[row][column] = value.doubleValue();
799 }
800
801
802
803
804
805
806 Array2DRowRealMatrix getConvertedMatrix() {
807 return new Array2DRowRealMatrix(data, false);
808 }
809 }
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829 public static void solveLowerTriangularSystem(RealMatrix rm, RealVector b)
830 throws MathIllegalArgumentException, MathRuntimeException {
831 if ((rm == null) || (b == null) || ( rm.getRowDimension() != b.getDimension())) {
832 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
833 (rm == null) ? 0 : rm.getRowDimension(),
834 (b == null) ? 0 : b.getDimension());
835 }
836 if( rm.getColumnDimension() != rm.getRowDimension() ){
837 throw new MathIllegalArgumentException(LocalizedCoreFormats.NON_SQUARE_MATRIX,
838 rm.getRowDimension(), rm.getColumnDimension());
839 }
840 int rows = rm.getRowDimension();
841 for( int i = 0 ; i < rows ; i++ ){
842 double diag = rm.getEntry(i, i);
843 if( FastMath.abs(diag) < Precision.SAFE_MIN ){
844 throw new MathRuntimeException(LocalizedCoreFormats.ZERO_DENOMINATOR);
845 }
846 double bi = b.getEntry(i)/diag;
847 b.setEntry(i, bi );
848 for( int j = i+1; j< rows; j++ ){
849 b.setEntry(j, b.getEntry(j)-bi*rm.getEntry(j,i) );
850 }
851 }
852 }
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873 public static void solveUpperTriangularSystem(RealMatrix rm, RealVector b)
874 throws MathIllegalArgumentException, MathRuntimeException {
875 if ((rm == null) || (b == null) || ( rm.getRowDimension() != b.getDimension())) {
876 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
877 (rm == null) ? 0 : rm.getRowDimension(),
878 (b == null) ? 0 : b.getDimension());
879 }
880 if( rm.getColumnDimension() != rm.getRowDimension() ){
881 throw new MathIllegalArgumentException(LocalizedCoreFormats.NON_SQUARE_MATRIX,
882 rm.getRowDimension(), rm.getColumnDimension());
883 }
884 int rows = rm.getRowDimension();
885 for( int i = rows-1 ; i >-1 ; i-- ){
886 double diag = rm.getEntry(i, i);
887 if( FastMath.abs(diag) < Precision.SAFE_MIN ){
888 throw new MathRuntimeException(LocalizedCoreFormats.ZERO_DENOMINATOR);
889 }
890 double bi = b.getEntry(i)/diag;
891 b.setEntry(i, bi );
892 for( int j = i-1; j>-1; j-- ){
893 b.setEntry(j, b.getEntry(j)-bi*rm.getEntry(j,i) );
894 }
895 }
896 }
897
898
899
900
901
902
903
904
905
906
907
908
909
910 public static RealMatrix blockInverse(RealMatrix m,
911 int splitIndex) {
912 final int n = m.getRowDimension();
913 if (m.getColumnDimension() != n) {
914 throw new MathIllegalArgumentException(LocalizedCoreFormats.NON_SQUARE_MATRIX,
915 m.getRowDimension(), m.getColumnDimension());
916 }
917
918 final int splitIndex1 = splitIndex + 1;
919
920 final RealMatrix a = m.getSubMatrix(0, splitIndex, 0, splitIndex);
921 final RealMatrix b = m.getSubMatrix(0, splitIndex, splitIndex1, n - 1);
922 final RealMatrix c = m.getSubMatrix(splitIndex1, n - 1, 0, splitIndex);
923 final RealMatrix d = m.getSubMatrix(splitIndex1, n - 1, splitIndex1, n - 1);
924
925 final SingularValueDecomposition aDec = new SingularValueDecomposition(a);
926 final DecompositionSolver aSolver = aDec.getSolver();
927 if (!aSolver.isNonSingular()) {
928 throw new MathIllegalArgumentException(LocalizedCoreFormats.SINGULAR_MATRIX);
929 }
930 final RealMatrix aInv = aSolver.getInverse();
931
932 final SingularValueDecomposition dDec = new SingularValueDecomposition(d);
933 final DecompositionSolver dSolver = dDec.getSolver();
934 if (!dSolver.isNonSingular()) {
935 throw new MathIllegalArgumentException(LocalizedCoreFormats.SINGULAR_MATRIX);
936 }
937 final RealMatrix dInv = dSolver.getInverse();
938
939 final RealMatrix tmp1 = a.subtract(b.multiply(dInv).multiply(c));
940 final SingularValueDecomposition tmp1Dec = new SingularValueDecomposition(tmp1);
941 final DecompositionSolver tmp1Solver = tmp1Dec.getSolver();
942 if (!tmp1Solver.isNonSingular()) {
943 throw new MathIllegalArgumentException(LocalizedCoreFormats.SINGULAR_MATRIX);
944 }
945 final RealMatrix result00 = tmp1Solver.getInverse();
946
947 final RealMatrix tmp2 = d.subtract(c.multiply(aInv).multiply(b));
948 final SingularValueDecomposition tmp2Dec = new SingularValueDecomposition(tmp2);
949 final DecompositionSolver tmp2Solver = tmp2Dec.getSolver();
950 if (!tmp2Solver.isNonSingular()) {
951 throw new MathIllegalArgumentException(LocalizedCoreFormats.SINGULAR_MATRIX);
952 }
953 final RealMatrix result11 = tmp2Solver.getInverse();
954
955 final RealMatrix result01 = aInv.multiply(b).multiply(result11).scalarMultiply(-1);
956 final RealMatrix result10 = dInv.multiply(c).multiply(result00).scalarMultiply(-1);
957
958 final RealMatrix result = new Array2DRowRealMatrix(n, n);
959 result.setSubMatrix(result00.getData(), 0, 0);
960 result.setSubMatrix(result01.getData(), 0, splitIndex1);
961 result.setSubMatrix(result10.getData(), splitIndex1, 0);
962 result.setSubMatrix(result11.getData(), splitIndex1, splitIndex1);
963
964 return result;
965 }
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982 public static RealMatrix inverse(RealMatrix matrix)
983 throws MathIllegalArgumentException, NullArgumentException {
984 return inverse(matrix, 0);
985 }
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000 public static RealMatrix inverse(RealMatrix matrix, double threshold)
1001 throws MathIllegalArgumentException, NullArgumentException {
1002
1003 MathUtils.checkNotNull(matrix);
1004
1005 if (!matrix.isSquare()) {
1006 throw new MathIllegalArgumentException(LocalizedCoreFormats.NON_SQUARE_MATRIX,
1007 matrix.getRowDimension(), matrix.getColumnDimension());
1008 }
1009
1010 if (matrix instanceof DiagonalMatrix) {
1011 return ((DiagonalMatrix) matrix).inverse(threshold);
1012 } else {
1013 QRDecomposition decomposition = new QRDecomposition(matrix, threshold);
1014 return decomposition.getSolver().getInverse();
1015 }
1016 }
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030 public static RealMatrix matrixExponential(final RealMatrix rm) {
1031
1032
1033 if (!rm.isSquare()) {
1034 throw new MathIllegalArgumentException(LocalizedCoreFormats.NON_SQUARE_MATRIX,
1035 rm.getRowDimension(), rm.getColumnDimension());
1036 }
1037
1038
1039 int dim = rm.getRowDimension();
1040 final RealMatrix identity = MatrixUtils.createRealIdentityMatrix(dim);
1041 RealMatrix scaledMatrix = rm.copy();
1042
1043
1044 final double l1Norm = rm.getNorm1();
1045 double[] padeCoefficients;
1046 int squaringCount = 0;
1047
1048 if (l1Norm < 1.495585217958292e-2) {
1049 padeCoefficients = PADE_COEFFICIENTS_3;
1050 } else if (l1Norm < 2.539398330063230e-1) {
1051 padeCoefficients = PADE_COEFFICIENTS_5;
1052 } else if (l1Norm < 9.504178996162932e-1) {
1053 padeCoefficients = PADE_COEFFICIENTS_7;
1054 } else if (l1Norm < 2.097847961257068) {
1055 padeCoefficients = PADE_COEFFICIENTS_9;
1056 } else {
1057 padeCoefficients = PADE_COEFFICIENTS_13;
1058
1059
1060 final double normScale = 5.371920351148152;
1061 squaringCount = Math.max(0, Math.getExponent(l1Norm / normScale));
1062
1063
1064 final int finalSquaringCount = squaringCount;
1065 scaledMatrix.mapToSelf(x -> Math.scalb(x, -finalSquaringCount));
1066 }
1067
1068
1069
1070
1071 final RealMatrix scaledMatrix2 = scaledMatrix.multiply(scaledMatrix);
1072 final int coeffLength = padeCoefficients.length;
1073
1074
1075 RealMatrix padeV = MatrixUtils.createRealMatrix(dim, dim);
1076 for (int i = coeffLength - 1; i > 1; i -= 2) {
1077 padeV = scaledMatrix2.multiply(padeV.add(identity.scalarMultiply(padeCoefficients[i])));
1078 }
1079 padeV = scaledMatrix.multiply(padeV.add(identity.scalarMultiply(padeCoefficients[1])));
1080
1081
1082 RealMatrix padeU = MatrixUtils.createRealMatrix(dim, dim);
1083 for (int i = coeffLength - 2; i > 1; i -= 2) {
1084 padeU = scaledMatrix2.multiply(padeU.add(identity.scalarMultiply(padeCoefficients[i])));
1085 }
1086 padeU = padeU.add(identity.scalarMultiply(padeCoefficients[0]));
1087
1088
1089 RealMatrix padeNumer = padeU.add(padeV);
1090 RealMatrix padeDenom = padeU.subtract(padeV);
1091
1092
1093 QRDecomposition decomposition = new QRDecomposition(padeDenom);
1094 RealMatrix result = decomposition.getSolver().solve(padeNumer);
1095
1096
1097 for (int i = 0; i < squaringCount; i++) {
1098 result = result.multiply(result);
1099 }
1100
1101 return result;
1102 }
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116 public static List<RealVector> orthonormalize(final List<RealVector> independent,
1117 final double threshold, final DependentVectorsHandler handler) {
1118
1119
1120 final List<RealVector> basis = new ArrayList<>(independent);
1121
1122
1123 int index = 0;
1124 while (index < basis.size()) {
1125
1126
1127 final RealVector vi = basis.get(index);
1128 final double norm = vi.getNorm();
1129 if (norm <= threshold) {
1130
1131 index = handler.manageDependent(index, basis);
1132 } else {
1133
1134
1135 vi.mapDivideToSelf(vi.getNorm());
1136
1137
1138 for (int j = index + 1; j < basis.size(); ++j) {
1139 final RealVector vj = basis.get(j);
1140 final double dot = vi.dotProduct(vj);
1141 for (int k = 0; k < vj.getDimension(); ++k) {
1142 vj.setEntry(k, vj.getEntry(k) - dot * vi.getEntry(k));
1143 }
1144 }
1145
1146 ++index;
1147
1148 }
1149
1150 }
1151
1152 return basis;
1153
1154 }
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170 public static <T extends CalculusFieldElement<T>> List<FieldVector<T>> orthonormalize(final Field<T> field,
1171 final List<FieldVector<T>> independent,
1172 final T threshold,
1173 final DependentVectorsHandler handler) {
1174
1175
1176 final List<FieldVector<T>> basis = new ArrayList<>(independent);
1177
1178
1179 int index = 0;
1180 while (index < basis.size()) {
1181
1182
1183 final FieldVector<T> vi = basis.get(index);
1184 final T norm = vi.dotProduct(vi).sqrt();
1185 if (norm.subtract(threshold).getReal() <= 0) {
1186
1187 index = handler.manageDependent(field, index, basis);
1188 } else {
1189
1190
1191 vi.mapDivideToSelf(norm);
1192
1193
1194 for (int j = index + 1; j < basis.size(); ++j) {
1195 final FieldVector<T> vj = basis.get(j);
1196 final T dot = vi.dotProduct(vj);
1197 for (int k = 0; k < vj.getDimension(); ++k) {
1198 vj.setEntry(k, vj.getEntry(k).subtract(dot.multiply(vi.getEntry(k))));
1199 }
1200 }
1201
1202 ++index;
1203
1204 }
1205 }
1206
1207 return basis;
1208
1209 }
1210
1211 }