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


amcl
Author(s): Brian P. Gerkey, contradict@gmail.com
autogenerated on Mon Mar 6 2023 03:50:13