1 package Jama;
2
3 import java.io.BufferedReader;
4 import java.io.PrintWriter;
5 import java.io.StreamTokenizer;
6 import java.text.DecimalFormat;
7 import java.text.DecimalFormatSymbols;
8 import java.text.NumberFormat;
9 import java.util.Locale;
10
11 import Jama.util.Maths;
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 public class Matrix implements Cloneable, java.io.Serializable {
57
58
59
60
61
62
63
64
65 private double[][] A;
66
67
68
69
70
71 private int m, n;
72
73
74
75
76
77
78
79
80
81
82 public Matrix (int m, int n) {
83 this.m = m;
84 this.n = n;
85 A = new double[m][n];
86 }
87
88
89
90
91
92
93
94 public Matrix (int m, int n, double s) {
95 this.m = m;
96 this.n = n;
97 A = new double[m][n];
98 for (int i = 0; i < m; i++) {
99 for (int j = 0; j < n; j++) {
100 A[i][j] = s;
101 }
102 }
103 }
104
105
106
107
108
109
110
111 public Matrix (double[][] A) {
112 m = A.length;
113 n = A[0].length;
114 for (int i = 0; i < m; i++) {
115 if (A[i].length != n) {
116 throw new IllegalArgumentException("All rows must have the same length.");
117 }
118 }
119 this.A = A;
120 }
121
122
123
124
125
126
127
128 public Matrix (double[][] A, int m, int n) {
129 this.A = A;
130 this.m = m;
131 this.n = n;
132 }
133
134
135
136
137
138
139
140 public Matrix (double vals[], int m) {
141 this.m = m;
142 n = (m != 0 ? vals.length/m : 0);
143 if (m*n != vals.length) {
144 throw new IllegalArgumentException("Array length must be a multiple of m.");
145 }
146 A = new double[m][n];
147 for (int i = 0; i < m; i++) {
148 for (int j = 0; j < n; j++) {
149 A[i][j] = vals[i+j*m];
150 }
151 }
152 }
153
154
155
156
157
158
159
160
161
162
163 public static Matrix constructWithCopy(double[][] A) {
164 int m = A.length;
165 int n = A[0].length;
166 Matrix X = new Matrix(m,n);
167 double[][] C = X.getArray();
168 for (int i = 0; i < m; i++) {
169 if (A[i].length != n) {
170 throw new IllegalArgumentException
171 ("All rows must have the same length.");
172 }
173 for (int j = 0; j < n; j++) {
174 C[i][j] = A[i][j];
175 }
176 }
177 return X;
178 }
179
180
181
182
183 public Matrix copy () {
184 Matrix X = new Matrix(m,n);
185 double[][] C = X.getArray();
186 for (int i = 0; i < m; i++) {
187 for (int j = 0; j < n; j++) {
188 C[i][j] = A[i][j];
189 }
190 }
191 return X;
192 }
193
194
195
196
197 public Object clone () {
198 return this.copy();
199 }
200
201
202
203
204
205 public double[][] getArray () {
206 return A;
207 }
208
209
210
211
212
213 public double[][] getArrayCopy () {
214 double[][] C = new double[m][n];
215 for (int i = 0; i < m; i++) {
216 for (int j = 0; j < n; j++) {
217 C[i][j] = A[i][j];
218 }
219 }
220 return C;
221 }
222
223
224
225
226
227 public double[] getColumnPackedCopy () {
228 double[] vals = new double[m*n];
229 for (int i = 0; i < m; i++) {
230 for (int j = 0; j < n; j++) {
231 vals[i+j*m] = A[i][j];
232 }
233 }
234 return vals;
235 }
236
237
238
239
240
241 public double[] getRowPackedCopy () {
242 double[] vals = new double[m*n];
243 for (int i = 0; i < m; i++) {
244 for (int j = 0; j < n; j++) {
245 vals[i*n+j] = A[i][j];
246 }
247 }
248 return vals;
249 }
250
251
252
253
254
255 public int getRowDimension () {
256 return m;
257 }
258
259
260
261
262
263 public int getColumnDimension () {
264 return n;
265 }
266
267
268
269
270
271
272
273
274 public double get (int i, int j) {
275 return A[i][j];
276 }
277
278
279
280
281
282
283
284
285
286
287 public Matrix getMatrix (int i0, int i1, int j0, int j1) {
288 Matrix X = new Matrix(i1-i0+1,j1-j0+1);
289 double[][] B = X.getArray();
290 try {
291 for (int i = i0; i <= i1; i++) {
292 for (int j = j0; j <= j1; j++) {
293 B[i-i0][j-j0] = A[i][j];
294 }
295 }
296 } catch(ArrayIndexOutOfBoundsException e) {
297 throw new ArrayIndexOutOfBoundsException("Submatrix indices");
298 }
299 return X;
300 }
301
302
303
304
305
306
307
308
309 public Matrix getMatrix (int[] r, int[] c) {
310 Matrix X = new Matrix(r.length,c.length);
311 double[][] B = X.getArray();
312 try {
313 for (int i = 0; i < r.length; i++) {
314 for (int j = 0; j < c.length; j++) {
315 B[i][j] = A[r[i]][c[j]];
316 }
317 }
318 } catch(ArrayIndexOutOfBoundsException e) {
319 throw new ArrayIndexOutOfBoundsException("Submatrix indices");
320 }
321 return X;
322 }
323
324
325
326
327
328
329
330
331
332 public Matrix getMatrix (int i0, int i1, int[] c) {
333 Matrix X = new Matrix(i1-i0+1,c.length);
334 double[][] B = X.getArray();
335 try {
336 for (int i = i0; i <= i1; i++) {
337 for (int j = 0; j < c.length; j++) {
338 B[i-i0][j] = A[i][c[j]];
339 }
340 }
341 } catch(ArrayIndexOutOfBoundsException e) {
342 throw new ArrayIndexOutOfBoundsException("Submatrix indices");
343 }
344 return X;
345 }
346
347
348
349
350
351
352
353
354
355 public Matrix getMatrix (int[] r, int j0, int j1) {
356 Matrix X = new Matrix(r.length,j1-j0+1);
357 double[][] B = X.getArray();
358 try {
359 for (int i = 0; i < r.length; i++) {
360 for (int j = j0; j <= j1; j++) {
361 B[i][j-j0] = A[r[i]][j];
362 }
363 }
364 } catch(ArrayIndexOutOfBoundsException e) {
365 throw new ArrayIndexOutOfBoundsException("Submatrix indices");
366 }
367 return X;
368 }
369
370
371
372
373
374
375
376
377 public void set (int i, int j, double s) {
378 A[i][j] = s;
379 }
380
381
382
383
384
385
386
387
388
389
390 public void setMatrix (int i0, int i1, int j0, int j1, Matrix X) {
391 try {
392 for (int i = i0; i <= i1; i++) {
393 for (int j = j0; j <= j1; j++) {
394 A[i][j] = X.get(i-i0,j-j0);
395 }
396 }
397 } catch(ArrayIndexOutOfBoundsException e) {
398 throw new ArrayIndexOutOfBoundsException("Submatrix indices");
399 }
400 }
401
402
403
404
405
406
407
408
409 public void setMatrix (int[] r, int[] c, Matrix X) {
410 try {
411 for (int i = 0; i < r.length; i++) {
412 for (int j = 0; j < c.length; j++) {
413 A[r[i]][c[j]] = X.get(i,j);
414 }
415 }
416 } catch(ArrayIndexOutOfBoundsException e) {
417 throw new ArrayIndexOutOfBoundsException("Submatrix indices");
418 }
419 }
420
421
422
423
424
425
426
427
428
429 public void setMatrix (int[] r, int j0, int j1, Matrix X) {
430 try {
431 for (int i = 0; i < r.length; i++) {
432 for (int j = j0; j <= j1; j++) {
433 A[r[i]][j] = X.get(i,j-j0);
434 }
435 }
436 } catch(ArrayIndexOutOfBoundsException e) {
437 throw new ArrayIndexOutOfBoundsException("Submatrix indices");
438 }
439 }
440
441
442
443
444
445
446
447
448
449 public void setMatrix (int i0, int i1, int[] c, Matrix X) {
450 try {
451 for (int i = i0; i <= i1; i++) {
452 for (int j = 0; j < c.length; j++) {
453 A[i][c[j]] = X.get(i-i0,j);
454 }
455 }
456 } catch(ArrayIndexOutOfBoundsException e) {
457 throw new ArrayIndexOutOfBoundsException("Submatrix indices");
458 }
459 }
460
461
462
463
464
465
466 public Matrix transpose () {
467 Matrix X = new Matrix(n,m);
468 double[][] C = X.getArray();
469 for (int i = 0; i < m; i++) {
470 for (int j = 0; j < n; j++) {
471 C[j][i] = A[i][j];
472 }
473 }
474 return X;
475 }
476
477
478
479
480
481 public double norm1 () {
482 double f = 0;
483 for (int j = 0; j < n; j++) {
484 double s = 0;
485 for (int i = 0; i < m; i++) {
486 s += Math.abs(A[i][j]);
487 }
488 f = Math.max(f,s);
489 }
490 return f;
491 }
492
493
494
495
496
497 public double norm2 () {
498 return (new SingularValueDecomposition(this).norm2());
499 }
500
501
502
503
504
505 public double normInf () {
506 double f = 0;
507 for (int i = 0; i < m; i++) {
508 double s = 0;
509 for (int j = 0; j < n; j++) {
510 s += Math.abs(A[i][j]);
511 }
512 f = Math.max(f,s);
513 }
514 return f;
515 }
516
517
518
519
520
521 public double normF () {
522 double f = 0;
523 for (int i = 0; i < m; i++) {
524 for (int j = 0; j < n; j++) {
525 f = Maths.hypot(f,A[i][j]);
526 }
527 }
528 return f;
529 }
530
531
532
533
534
535 public Matrix uminus () {
536 Matrix X = new Matrix(m,n);
537 double[][] C = X.getArray();
538 for (int i = 0; i < m; i++) {
539 for (int j = 0; j < n; j++) {
540 C[i][j] = -A[i][j];
541 }
542 }
543 return X;
544 }
545
546
547
548
549
550
551 public Matrix plus (Matrix B) {
552 checkMatrixDimensions(B);
553 Matrix X = new Matrix(m,n);
554 double[][] C = X.getArray();
555 for (int i = 0; i < m; i++) {
556 for (int j = 0; j < n; j++) {
557 C[i][j] = A[i][j] + B.A[i][j];
558 }
559 }
560 return X;
561 }
562
563
564
565
566
567
568 public Matrix plusEquals (Matrix B) {
569 checkMatrixDimensions(B);
570 for (int i = 0; i < m; i++) {
571 for (int j = 0; j < n; j++) {
572 A[i][j] = A[i][j] + B.A[i][j];
573 }
574 }
575 return this;
576 }
577
578
579
580
581
582
583 public Matrix minus (Matrix B) {
584 checkMatrixDimensions(B);
585 Matrix X = new Matrix(m,n);
586 double[][] C = X.getArray();
587 for (int i = 0; i < m; i++) {
588 for (int j = 0; j < n; j++) {
589 C[i][j] = A[i][j] - B.A[i][j];
590 }
591 }
592 return X;
593 }
594
595
596
597
598
599
600 public Matrix minusEquals (Matrix B) {
601 checkMatrixDimensions(B);
602 for (int i = 0; i < m; i++) {
603 for (int j = 0; j < n; j++) {
604 A[i][j] = A[i][j] - B.A[i][j];
605 }
606 }
607 return this;
608 }
609
610
611
612
613
614
615 public Matrix arrayTimes (Matrix B) {
616 checkMatrixDimensions(B);
617 Matrix X = new Matrix(m,n);
618 double[][] C = X.getArray();
619 for (int i = 0; i < m; i++) {
620 for (int j = 0; j < n; j++) {
621 C[i][j] = A[i][j] * B.A[i][j];
622 }
623 }
624 return X;
625 }
626
627
628
629
630
631
632 public Matrix arrayTimesEquals (Matrix B) {
633 checkMatrixDimensions(B);
634 for (int i = 0; i < m; i++) {
635 for (int j = 0; j < n; j++) {
636 A[i][j] = A[i][j] * B.A[i][j];
637 }
638 }
639 return this;
640 }
641
642
643
644
645
646
647 public Matrix arrayRightDivide (Matrix B) {
648 checkMatrixDimensions(B);
649 Matrix X = new Matrix(m,n);
650 double[][] C = X.getArray();
651 for (int i = 0; i < m; i++) {
652 for (int j = 0; j < n; j++) {
653 C[i][j] = A[i][j] / B.A[i][j];
654 }
655 }
656 return X;
657 }
658
659
660
661
662
663
664 public Matrix arrayRightDivideEquals (Matrix B) {
665 checkMatrixDimensions(B);
666 for (int i = 0; i < m; i++) {
667 for (int j = 0; j < n; j++) {
668 A[i][j] = A[i][j] / B.A[i][j];
669 }
670 }
671 return this;
672 }
673
674
675
676
677
678
679 public Matrix arrayLeftDivide (Matrix B) {
680 checkMatrixDimensions(B);
681 Matrix X = new Matrix(m,n);
682 double[][] C = X.getArray();
683 for (int i = 0; i < m; i++) {
684 for (int j = 0; j < n; j++) {
685 C[i][j] = B.A[i][j] / A[i][j];
686 }
687 }
688 return X;
689 }
690
691
692
693
694
695
696 public Matrix arrayLeftDivideEquals (Matrix B) {
697 checkMatrixDimensions(B);
698 for (int i = 0; i < m; i++) {
699 for (int j = 0; j < n; j++) {
700 A[i][j] = B.A[i][j] / A[i][j];
701 }
702 }
703 return this;
704 }
705
706
707
708
709
710
711 public Matrix times (double s) {
712 Matrix X = new Matrix(m,n);
713 double[][] C = X.getArray();
714 for (int i = 0; i < m; i++) {
715 for (int j = 0; j < n; j++) {
716 C[i][j] = s*A[i][j];
717 }
718 }
719 return X;
720 }
721
722
723
724
725
726
727 public Matrix timesEquals (double s) {
728 for (int i = 0; i < m; i++) {
729 for (int j = 0; j < n; j++) {
730 A[i][j] = s*A[i][j];
731 }
732 }
733 return this;
734 }
735
736
737
738
739
740
741
742 public Matrix times (Matrix B) {
743 if (B.m != n) {
744 throw new IllegalArgumentException("Matrix inner dimensions must agree.");
745 }
746 Matrix X = new Matrix(m,B.n);
747 double[][] C = X.getArray();
748 double[] Bcolj = new double[n];
749 for (int j = 0; j < B.n; j++) {
750 for (int k = 0; k < n; k++) {
751 Bcolj[k] = B.A[k][j];
752 }
753 for (int i = 0; i < m; i++) {
754 double[] Arowi = A[i];
755 double s = 0;
756 for (int k = 0; k < n; k++) {
757 s += Arowi[k]*Bcolj[k];
758 }
759 C[i][j] = s;
760 }
761 }
762 return X;
763 }
764
765
766
767
768
769
770 public double[] times(double[] x) {
771 if (n != x.length)
772 throw new IllegalArgumentException("dimensions do not match");
773 double[] result = new double[m];
774
775 for (int i=0; i<m; i++) {
776 for (int j=0; j<n; j++) {
777 result[i] += A[i][j] * x[j];
778 }
779 }
780 return result;
781 }
782
783
784
785
786
787
788 public LUDecomposition lu () {
789 return new LUDecomposition(this);
790 }
791
792
793
794
795
796
797 public QRDecomposition qr () {
798 return new QRDecomposition(this);
799 }
800
801
802
803
804
805
806 public CholeskyDecomposition chol () {
807 return new CholeskyDecomposition(this);
808 }
809
810
811
812
813
814
815 public SingularValueDecomposition svd () {
816 return new SingularValueDecomposition(this);
817 }
818
819
820
821
822
823
824 public EigenvalueDecomposition eig () {
825 return new EigenvalueDecomposition(this);
826 }
827
828
829
830
831
832
833 public Matrix solve (Matrix B) {
834 return (m == n ? (new LUDecomposition(this)).solve(B) :
835 (new QRDecomposition(this)).solve(B));
836 }
837
838
839
840
841
842
843 public Matrix solveTranspose (Matrix B) {
844 return transpose().solve(B.transpose());
845 }
846
847
848
849
850
851 public Matrix inverse () {
852 return solve(identity(m,m));
853 }
854
855
856
857
858
859 public double det () {
860 return new LUDecomposition(this).det();
861 }
862
863
864
865
866
867 public int rank () {
868 return new SingularValueDecomposition(this).rank();
869 }
870
871
872
873
874
875 public double cond () {
876 return new SingularValueDecomposition(this).cond();
877 }
878
879
880
881
882
883 public double trace () {
884 double t = 0;
885 for (int i = 0; i < Math.min(m,n); i++) {
886 t += A[i][i];
887 }
888 return t;
889 }
890
891
892
893
894
895 public double amax () {
896 double amax = Math.abs(A[0][0]);
897 for (int i = 0; i < m; ++i)
898 {
899 for (int j = 0; j < n; ++j)
900 {
901 if ( Math.abs(A[i][j])>amax ) amax = Math.abs(A[i][j]);
902 }
903 }
904 return amax;
905 }
906
907
908
909
910
911 public double amin() {
912 double amin = Math.abs(A[0][0]);
913 for (int i = 0; i < m; ++i)
914 {
915 for (int j = 0; j < n; ++j)
916 {
917 if ( Math.abs(A[i][j])<amin ) amin = Math.abs(A[i][j]);
918 }
919 }
920 return amin;
921 }
922
923
924
925
926
927 public double max () {
928 double max = A[0][0];
929 for (int i = 0; i < m; ++i)
930 {
931 for (int j = 0; j < n; ++j)
932 {
933 if ( A[i][j]>max ) max = A[i][j];
934 }
935 }
936 return max;
937 }
938
939
940
941
942
943 public double min () {
944 double min = A[0][0];
945 for (int i = 0; i < m; ++i)
946 {
947 for (int j = 0; j < n; ++j)
948 {
949 if ( A[i][j]<min ) min = A[i][j];
950 }
951 }
952 return min;
953 }
954
955
956
957
958
959
960
961 public static Matrix random (int m, int n) {
962 Matrix A = new Matrix(m,n);
963 double[][] X = A.getArray();
964 for (int i = 0; i < m; i++) {
965 for (int j = 0; j < n; j++) {
966 X[i][j] = Math.random();
967 }
968 }
969 return A;
970 }
971
972
973
974
975
976
977
978 public static Matrix identity (int m, int n) {
979 Matrix A = new Matrix(m,n);
980 double[][] X = A.getArray();
981 for (int i = 0; i < m; i++) {
982 for (int j = 0; j < n; j++) {
983 X[i][j] = (i == j ? 1.0 : 0.0);
984 }
985 }
986 return A;
987 }
988
989
990
991
992
993
994
995
996 public void print (int w, int d) {
997 print(new PrintWriter(System.out,true),w,d); }
998
999
1000
1001
1002
1003
1004
1005
1006 public void print (PrintWriter output, int w, int d) {
1007 DecimalFormat format = new DecimalFormat();
1008 format.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US));
1009 format.setMinimumIntegerDigits(1);
1010 format.setMaximumFractionDigits(d);
1011 format.setMinimumFractionDigits(d);
1012 format.setGroupingUsed(false);
1013 print(output,format,w+2);
1014 }
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026 public void print (NumberFormat format, int width) {
1027 print(new PrintWriter(System.out,true),format,width); }
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045 public void print (PrintWriter output, NumberFormat format, int width) {
1046 output.println();
1047 for (int i = 0; i < m; i++) {
1048 for (int j = 0; j < n; j++) {
1049 String s = format.format(A[i][j]);
1050 int padding = Math.max(1,width-s.length());
1051 for (int k = 0; k < padding; k++)
1052 output.print(' ');
1053 output.print(s);
1054 }
1055 output.println();
1056 }
1057 output.println();
1058 }
1059
1060
1061
1062
1063
1064 public String toString()
1065 {
1066 StringBuffer tmp = new StringBuffer();
1067 for(int i = 0; i<m; ++i)
1068 {
1069 for(int j = 0; j<n; ++j)
1070 {
1071 tmp.append(" "+A[i][j]);
1072 }
1073 tmp.append("\n");
1074 }
1075 tmp.append("\n");
1076 return tmp.toString();
1077 }
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088 public static Matrix read (BufferedReader input) throws java.io.IOException {
1089 StreamTokenizer tokenizer= new StreamTokenizer(input);
1090
1091
1092
1093
1094
1095
1096
1097 tokenizer.resetSyntax();
1098 tokenizer.wordChars(0,255);
1099 tokenizer.whitespaceChars(0, ' ');
1100 tokenizer.eolIsSignificant(true);
1101 java.util.Vector v = new java.util.Vector();
1102
1103
1104 while (tokenizer.nextToken() == StreamTokenizer.TT_EOL);
1105 if (tokenizer.ttype == StreamTokenizer.TT_EOF)
1106 throw new java.io.IOException("Unexpected EOF on matrix read.");
1107 do {
1108 v.addElement(Double.valueOf(tokenizer.sval));
1109 } while (tokenizer.nextToken() == StreamTokenizer.TT_WORD);
1110
1111 int n = v.size();
1112 double row[] = new double[n];
1113 for (int j=0; j<n; j++)
1114 row[j]=((Double)v.elementAt(j)).doubleValue();
1115 v.removeAllElements();
1116 v.addElement(row);
1117 while (tokenizer.nextToken() == StreamTokenizer.TT_WORD) {
1118
1119 v.addElement(row = new double[n]);
1120 int j = 0;
1121 do {
1122 if (j >= n) throw new java.io.IOException
1123 ("Row " + v.size() + " is too long.");
1124 row[j++] = Double.valueOf(tokenizer.sval).doubleValue();
1125 } while (tokenizer.nextToken() == StreamTokenizer.TT_WORD);
1126 if (j < n) throw new java.io.IOException
1127 ("Row " + v.size() + " is too short.");
1128 }
1129 int m = v.size();
1130 double[][] A = new double[m][];
1131 v.copyInto(A);
1132 return new Matrix(A);
1133 }
1134
1135
1136
1137
1138
1139
1140
1141
1142 private void checkMatrixDimensions (Matrix B) {
1143 if (B.m != m || B.n != n) {
1144 throw new IllegalArgumentException("Matrix dimensions must agree.");
1145 }
1146 }
1147
1148 }