1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.math4.legacy.linear;
19
20 import org.apache.commons.math4.core.jdkmath.JdkMath;
21 import org.apache.commons.numbers.core.Precision;
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 class HessenbergTransformer {
42
43 private final double[][] householderVectors;
44
45 private final double[] ort;
46
47 private RealMatrix cachedP;
48
49 private RealMatrix cachedPt;
50
51 private RealMatrix cachedH;
52
53
54
55
56
57
58
59 HessenbergTransformer(final RealMatrix matrix) {
60 if (!matrix.isSquare()) {
61 throw new NonSquareMatrixException(matrix.getRowDimension(),
62 matrix.getColumnDimension());
63 }
64
65 final int m = matrix.getRowDimension();
66 householderVectors = matrix.getData();
67 ort = new double[m];
68 cachedP = null;
69 cachedPt = null;
70 cachedH = null;
71
72
73 transform();
74 }
75
76
77
78
79
80
81
82 public RealMatrix getP() {
83 if (cachedP == null) {
84 final int n = householderVectors.length;
85 final int high = n - 1;
86 final double[][] pa = new double[n][n];
87
88 for (int i = 0; i < n; i++) {
89 for (int j = 0; j < n; j++) {
90 pa[i][j] = (i == j) ? 1 : 0;
91 }
92 }
93
94 for (int m = high - 1; m >= 1; m--) {
95 if (householderVectors[m][m - 1] != 0.0) {
96 for (int i = m + 1; i <= high; i++) {
97 ort[i] = householderVectors[i][m - 1];
98 }
99
100 for (int j = m; j <= high; j++) {
101 double g = 0.0;
102
103 for (int i = m; i <= high; i++) {
104 g += ort[i] * pa[i][j];
105 }
106
107
108 g = (g / ort[m]) / householderVectors[m][m - 1];
109
110 for (int i = m; i <= high; i++) {
111 pa[i][j] += g * ort[i];
112 }
113 }
114 }
115 }
116
117 cachedP = MatrixUtils.createRealMatrix(pa);
118 }
119 return cachedP;
120 }
121
122
123
124
125
126
127
128 public RealMatrix getPT() {
129 if (cachedPt == null) {
130 cachedPt = getP().transpose();
131 }
132
133
134 return cachedPt;
135 }
136
137
138
139
140
141
142 public RealMatrix getH() {
143 if (cachedH == null) {
144 final int m = householderVectors.length;
145 final double[][] h = new double[m][m];
146 for (int i = 0; i < m; ++i) {
147 if (i > 0) {
148
149 h[i][i - 1] = householderVectors[i][i - 1];
150 }
151
152
153 System.arraycopy(householderVectors[i], i, h[i], i, m - i);
154 }
155 cachedH = MatrixUtils.createRealMatrix(h);
156 }
157
158
159 return cachedH;
160 }
161
162
163
164
165
166
167
168
169 double[][] getHouseholderVectorsRef() {
170 return householderVectors;
171 }
172
173
174
175
176
177 private void transform() {
178 final int n = householderVectors.length;
179 final int high = n - 1;
180
181 for (int m = 1; m <= high - 1; m++) {
182
183 double scale = 0;
184 for (int i = m; i <= high; i++) {
185 scale += JdkMath.abs(householderVectors[i][m - 1]);
186 }
187
188 if (!Precision.equals(scale, 0)) {
189
190 double h = 0;
191 for (int i = high; i >= m; i--) {
192 ort[i] = householderVectors[i][m - 1] / scale;
193 h += ort[i] * ort[i];
194 }
195 final double g = (ort[m] > 0) ? -JdkMath.sqrt(h) : JdkMath.sqrt(h);
196
197 h -= ort[m] * g;
198 ort[m] -= g;
199
200
201
202
203 for (int j = m; j < n; j++) {
204 double f = 0;
205 for (int i = high; i >= m; i--) {
206 f += ort[i] * householderVectors[i][j];
207 }
208 f /= h;
209 for (int i = m; i <= high; i++) {
210 householderVectors[i][j] -= f * ort[i];
211 }
212 }
213
214 for (int i = 0; i <= high; i++) {
215 double f = 0;
216 for (int j = high; j >= m; j--) {
217 f += ort[j] * householderVectors[i][j];
218 }
219 f /= h;
220 for (int j = m; j <= high; j++) {
221 householderVectors[i][j] -= f * ort[j];
222 }
223 }
224
225 ort[m] = scale * ort[m];
226 householderVectors[m][m - 1] = scale * g;
227 }
228 }
229 }
230 }