1 package Jama;
2 import Jama.util.*;
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 public class QRDecomposition implements java.io.Serializable {
19
20
21
22
23
24
25
26
27 private double[][] QR;
28
29
30
31
32
33 private int m, n;
34
35
36
37
38 private double[] Rdiag;
39
40
41
42
43
44
45
46
47
48 public QRDecomposition (Matrix A) {
49
50 QR = A.getArrayCopy();
51 m = A.getRowDimension();
52 n = A.getColumnDimension();
53 Rdiag = new double[n];
54
55
56 for (int k = 0; k < n; k++) {
57
58 double nrm = 0;
59 for (int i = k; i < m; i++) {
60 nrm = Maths.hypot(nrm,QR[i][k]);
61 }
62
63 if (nrm != 0.0) {
64
65 if (QR[k][k] < 0) {
66 nrm = -nrm;
67 }
68 for (int i = k; i < m; i++) {
69 QR[i][k] /= nrm;
70 }
71 QR[k][k] += 1.0;
72
73
74 for (int j = k+1; j < n; j++) {
75 double s = 0.0;
76 for (int i = k; i < m; i++) {
77 s += QR[i][k]*QR[i][j];
78 }
79 s = -s/QR[k][k];
80 for (int i = k; i < m; i++) {
81 QR[i][j] += s*QR[i][k];
82 }
83 }
84 }
85 Rdiag[k] = -nrm;
86 }
87 }
88
89
90
91
92
93
94
95
96
97 public boolean isFullRank () {
98 for (int j = 0; j < n; j++) {
99 if (Rdiag[j] == 0)
100 return false;
101 }
102 return true;
103 }
104
105
106
107
108
109 public Matrix getH () {
110 Matrix X = new Matrix(m,n);
111 double[][] H = X.getArray();
112 for (int i = 0; i < m; i++) {
113 for (int j = 0; j < n; j++) {
114 if (i >= j) {
115 H[i][j] = QR[i][j];
116 } else {
117 H[i][j] = 0.0;
118 }
119 }
120 }
121 return X;
122 }
123
124
125
126
127
128 public Matrix getR () {
129 Matrix X = new Matrix(n,n);
130 double[][] R = X.getArray();
131 for (int i = 0; i < n; i++) {
132 for (int j = 0; j < n; j++) {
133 if (i < j) {
134 R[i][j] = QR[i][j];
135 } else if (i == j) {
136 R[i][j] = Rdiag[i];
137 } else {
138 R[i][j] = 0.0;
139 }
140 }
141 }
142 return X;
143 }
144
145
146
147
148
149 public Matrix getQ () {
150 Matrix X = new Matrix(m,n);
151 double[][] Q = X.getArray();
152 for (int k = n-1; k >= 0; k--) {
153 for (int i = 0; i < m; i++) {
154 Q[i][k] = 0.0;
155 }
156 Q[k][k] = 1.0;
157 for (int j = k; j < n; j++) {
158 if (QR[k][k] != 0) {
159 double s = 0.0;
160 for (int i = k; i < m; i++) {
161 s += QR[i][k]*Q[i][j];
162 }
163 s = -s/QR[k][k];
164 for (int i = k; i < m; i++) {
165 Q[i][j] += s*QR[i][k];
166 }
167 }
168 }
169 }
170 return X;
171 }
172
173
174
175
176
177
178
179
180 public Matrix solve (Matrix B) {
181 if (B.getRowDimension() != m) {
182 throw new IllegalArgumentException("Matrix row dimensions must agree.");
183 }
184 if (!this.isFullRank()) {
185 throw new RuntimeException("Matrix is rank deficient.");
186 }
187
188
189 int nx = B.getColumnDimension();
190 double[][] X = B.getArrayCopy();
191
192
193 for (int k = 0; k < n; k++) {
194 for (int j = 0; j < nx; j++) {
195 double s = 0.0;
196 for (int i = k; i < m; i++) {
197 s += QR[i][k]*X[i][j];
198 }
199 s = -s/QR[k][k];
200 for (int i = k; i < m; i++) {
201 X[i][j] += s*QR[i][k];
202 }
203 }
204 }
205
206 for (int k = n-1; k >= 0; k--) {
207 for (int j = 0; j < nx; j++) {
208 X[k][j] /= Rdiag[k];
209 }
210 for (int i = 0; i < k; i++) {
211 for (int j = 0; j < nx; j++) {
212 X[i][j] -= X[k][j]*QR[i][k];
213 }
214 }
215 }
216 return (new Matrix(X,n,nx).getMatrix(0,n-1,0,nx-1));
217 }
218 }