CGR Localization
 All Classes Namespaces Files Functions Variables Macros Pages
eig3.cpp
1 
2 /* Eigen decomposition code for symmetric 3x3 matrices, copied from the public
3 domain Java Matrix library JAMA. */
4 
5 #include <math.h>
6 
7 #ifdef MAX
8 #undef MAX
9 #endif
10 
11 #define MAX(a, b) ((a)>(b)?(a):(b))
12 
13 #define n 3
14 
15 static double hypot2(double x, double y) {
16  return sqrt(x*x+y*y);
17 }
18 
20 static void tred2(double V[n][n], double d[n], double e[n]) {
21 
22  // This is derived from the Algol procedures tred2 by
23  // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
24  // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
25  // Fortran subroutine in EISPACK.
26 
27  for (int j = 0; j < n; j++) {
28  d[j] = V[n-1][j];
29  }
30 
31  // Householder reduction to tridiagonal form.
32 
33  for (int i = n-1; i > 0; i--) {
34 
35  // Scale to avoid under/overflow.
36 
37  double scale = 0.0;
38  double h = 0.0;
39  for (int k = 0; k < i; k++) {
40  scale = scale + fabs(d[k]);
41  }
42  if (scale == 0.0) {
43  e[i] = d[i-1];
44  for (int j = 0; j < i; j++) {
45  d[j] = V[i-1][j];
46  V[i][j] = 0.0;
47  V[j][i] = 0.0;
48  }
49  } else {
50 
51  // Generate Householder vector.
52 
53  for (int k = 0; k < i; k++) {
54  d[k] /= scale;
55  h += d[k] * d[k];
56  }
57  double f = d[i-1];
58  double g = sqrt(h);
59  if (f > 0) {
60  g = -g;
61  }
62  e[i] = scale * g;
63  h = h - f * g;
64  d[i-1] = f - g;
65  for (int j = 0; j < i; j++) {
66  e[j] = 0.0;
67  }
68 
69  // Apply similarity transformation to remaining columns.
70 
71  for (int j = 0; j < i; j++) {
72  f = d[j];
73  V[j][i] = f;
74  g = e[j] + V[j][j] * f;
75  for (int k = j+1; k <= i-1; k++) {
76  g += V[k][j] * d[k];
77  e[k] += V[k][j] * f;
78  }
79  e[j] = g;
80  }
81  f = 0.0;
82  for (int j = 0; j < i; j++) {
83  e[j] /= h;
84  f += e[j] * d[j];
85  }
86  double hh = f / (h + h);
87  for (int j = 0; j < i; j++) {
88  e[j] -= hh * d[j];
89  }
90  for (int j = 0; j < i; j++) {
91  f = d[j];
92  g = e[j];
93  for (int k = j; k <= i-1; k++) {
94  V[k][j] -= (f * e[k] + g * d[k]);
95  }
96  d[j] = V[i-1][j];
97  V[i][j] = 0.0;
98  }
99  }
100  d[i] = h;
101  }
102 
103  // Accumulate transformations.
104 
105  for (int i = 0; i < n-1; i++) {
106  V[n-1][i] = V[i][i];
107  V[i][i] = 1.0;
108  double h = d[i+1];
109  if (h != 0.0) {
110  for (int k = 0; k <= i; k++) {
111  d[k] = V[k][i+1] / h;
112  }
113  for (int j = 0; j <= i; j++) {
114  double g = 0.0;
115  for (int k = 0; k <= i; k++) {
116  g += V[k][i+1] * V[k][j];
117  }
118  for (int k = 0; k <= i; k++) {
119  V[k][j] -= g * d[k];
120  }
121  }
122  }
123  for (int k = 0; k <= i; k++) {
124  V[k][i+1] = 0.0;
125  }
126  }
127  for (int j = 0; j < n; j++) {
128  d[j] = V[n-1][j];
129  V[n-1][j] = 0.0;
130  }
131  V[n-1][n-1] = 1.0;
132  e[0] = 0.0;
133 }
134 
136 static void tql2(double V[n][n], double d[n], double e[n]) {
137 
138  // This is derived from the Algol procedures tql2, by
139  // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
140  // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
141  // Fortran subroutine in EISPACK.
142 
143  for (int i = 1; i < n; i++) {
144  e[i-1] = e[i];
145  }
146  e[n-1] = 0.0;
147 
148  double f = 0.0;
149  double tst1 = 0.0;
150  double eps = pow(2.0,-52.0);
151  for (int l = 0; l < n; l++) {
152 
153  // Find small subdiagonal element
154 
155  tst1 = MAX(tst1,fabs(d[l]) + fabs(e[l]));
156  int m = l;
157  while (m < n) {
158  if (fabs(e[m]) <= eps*tst1) {
159  break;
160  }
161  m++;
162  }
163 
164  // If m == l, d[l] is an eigenvalue,
165  // otherwise, iterate.
166 
167  if (m > l) {
168  int iter = 0;
169  do {
170  iter = iter + 1; // (Could check iteration count here.)
171 
172  // Compute implicit shift
173 
174  double g = d[l];
175  double p = (d[l+1] - g) / (2.0 * e[l]);
176  double r = hypot2(p,1.0);
177  if (p < 0) {
178  r = -r;
179  }
180  d[l] = e[l] / (p + r);
181  d[l+1] = e[l] * (p + r);
182  double dl1 = d[l+1];
183  double h = g - d[l];
184  for (int i = l+2; i < n; i++) {
185  d[i] -= h;
186  }
187  f = f + h;
188 
189  // Implicit QL transformation.
190 
191  p = d[m];
192  double c = 1.0;
193  double c2 = c;
194  double c3 = c;
195  double el1 = e[l+1];
196  double s = 0.0;
197  double s2 = 0.0;
198  for (int i = m-1; i >= l; i--) {
199  c3 = c2;
200  c2 = c;
201  s2 = s;
202  g = c * e[i];
203  h = c * p;
204  r = hypot2(p,e[i]);
205  e[i+1] = s * r;
206  s = e[i] / r;
207  c = p / r;
208  p = c * d[i] - s * g;
209  d[i+1] = h + s * (c * g + s * d[i]);
210 
211  // Accumulate transformation.
212 
213  for (int k = 0; k < n; k++) {
214  h = V[k][i+1];
215  V[k][i+1] = s * V[k][i] + c * h;
216  V[k][i] = c * V[k][i] - s * h;
217  }
218  }
219  p = -s * s2 * c3 * el1 * e[l] / dl1;
220  e[l] = s * p;
221  d[l] = c * p;
222 
223  // Check for convergence.
224 
225  } while (fabs(e[l]) > eps*tst1);
226  }
227  d[l] = d[l] + f;
228  e[l] = 0.0;
229  }
230 
231  // Sort eigenvalues and corresponding vectors.
232 
233  for (int i = 0; i < n-1; i++) {
234  int k = i;
235  double p = d[i];
236  for (int j = i+1; j < n; j++) {
237  if (d[j] < p) {
238  k = j;
239  p = d[j];
240  }
241  }
242  if (k != i) {
243  d[k] = d[i];
244  d[i] = p;
245  for (int j = 0; j < n; j++) {
246  p = V[j][i];
247  V[j][i] = V[j][k];
248  V[j][k] = p;
249  }
250  }
251  }
252 }
253 
254 void eigen_decomposition(double A[n][n], double V[n][n], double d[n]) {
255  double e[n];
256  for (int i = 0; i < n; i++) {
257  for (int j = 0; j < n; j++) {
258  V[i][j] = A[i][j];
259  }
260  }
261  tred2(V, d, e);
262  tql2(V, d, e);
263 }