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