rheolef  6.3
tensor-eig3.cc
Go to the documentation of this file.
1 // http://barnesc.blogspot.com/2007/02/eigenvectors-of-3x3-symmetric-matrix.html
2 // http://www.connellybarnes.com/code/c/eig3-1.0.0.zip
3 // A C++ source and header file to compute eigenvectors/values of a 3x3 symmetric
4 #include "rheolef/tensor.h"
5 namespace rheolef {
6 
7 template<class T>
8 static
9 inline
10 T hypot2(const T& x, const T& y) { return sqrt(x*x+y*y); }
11 
12 template<class T>
13 static
14 void
16 {
17  const int n = 3;
18 
19 
20  for (int j = 0; j < n; j++) {
21  d[j] = V(n-1,j);
22  }
23 
24 
25  for (int i = n-1; i > 0; i--) {
26 
27  // Scale to avoid under/overflow.
28 
29  T scale = 0.0;
30  T h = 0.0;
31  for (int k = 0; k < i; k++) {
32  scale = scale + fabs(d[k]);
33  }
34  if (scale == 0.0) {
35  e[i] = d[i-1];
36  for (int j = 0; j < i; j++) {
37  d[j] = V(i-1,j);
38  V(i,j) = 0.0;
39  V(j,i) = 0.0;
40  }
41  } else {
42 
43 
44  for (int k = 0; k < i; k++) {
45  d[k] /= scale;
46  h += d[k] * d[k];
47  }
48  T f = d[i-1];
49  T g = sqrt(h);
50  if (f > 0) {
51  g = -g;
52  }
53  e[i] = scale * g;
54  h = h - f * g;
55  d[i-1] = f - g;
56  for (int j = 0; j < i; j++) {
57  e[j] = 0.0;
58  }
59 
60 
61  for (int j = 0; j < i; j++) {
62  f = d[j];
63  V(j,i) = f;
64  g = e[j] + V(j,j) * f;
65  for (int k = j+1; k <= i-1; k++) {
66  g += V(k,j) * d[k];
67  e[k] += V(k,j) * f;
68  }
69  e[j] = g;
70  }
71  f = 0.0;
72  for (int j = 0; j < i; j++) {
73  e[j] /= h;
74  f += e[j] * d[j];
75  }
76  T hh = f / (h + h);
77  for (int j = 0; j < i; j++) {
78  e[j] -= hh * d[j];
79  }
80  for (int j = 0; j < i; j++) {
81  f = d[j];
82  g = e[j];
83  for (int k = j; k <= i-1; k++) {
84  V(k,j) -= (f * e[k] + g * d[k]);
85  }
86  d[j] = V(i-1,j);
87  V(i,j) = 0.0;
88  }
89  }
90  d[i] = h;
91  }
92 
93 
94  for (int i = 0; i < n-1; i++) {
95  V(n-1,i) = V(i,i);
96  V(i,i) = 1.0;
97  T h = d[i+1];
98  if (h != 0.0) {
99  for (int k = 0; k <= i; k++) {
100  d[k] = V(k,i+1) / h;
101  }
102  for (int j = 0; j <= i; j++) {
103  T g = 0.0;
104  for (int k = 0; k <= i; k++) {
105  g += V(k,i+1) * V(k,j);
106  }
107  for (int k = 0; k <= i; k++) {
108  V(k,j) -= g * d[k];
109  }
110  }
111  }
112  for (int k = 0; k <= i; k++) {
113  V(k,i+1) = 0.0;
114  }
115  }
116  for (int j = 0; j < n; j++) {
117  d[j] = V(n-1,j);
118  V(n-1,j) = 0.0;
119  }
120  V(n-1,n-1) = 1.0;
121  e[0] = 0.0;
122 }
123 template<class T>
124 static
125 void
127 {
128  const int n = 3;
129 
130 
131  for (int i = 1; i < n; i++) {
132  e[i-1] = e[i];
133  }
134  e[n-1] = 0.0;
135 
136  T f = 0.0;
137  T tst1 = 0.0;
138  T eps = pow(2.0,-52.0);
139  for (int l = 0; l < n; l++) {
140 
141 
142  tst1 = std::max (tst1, fabs(d[l]) + fabs(e[l]));
143  int m = l;
144  while (m < n) {
145  if (fabs(e[m]) <= eps*tst1) {
146  break;
147  }
148  m++;
149  }
150 
151 
152  if (m > l) {
153  int iter = 0;
154  do {
155  iter = iter + 1; // (Could check iteration count here.)
156 
157 
158  T g = d[l];
159  T p = (d[l+1] - g) / (2.0 * e[l]);
160  T r = hypot2(p,1.0);
161  if (p < 0) {
162  r = -r;
163  }
164  d[l] = e[l] / (p + r);
165  d[l+1] = e[l] * (p + r);
166  T dl1 = d[l+1];
167  T h = g - d[l];
168  for (int i = l+2; i < n; i++) {
169  d[i] -= h;
170  }
171  f = f + h;
172 
173 
174  p = d[m];
175  T c = 1.0;
176  T c2 = c;
177  T c3 = c;
178  T el1 = e[l+1];
179  T s = 0.0;
180  T s2 = 0.0;
181  for (int i = m-1; i >= l; i--) {
182  c3 = c2;
183  c2 = c;
184  s2 = s;
185  g = c * e[i];
186  h = c * p;
187  r = hypot2(p,e[i]);
188  e[i+1] = s * r;
189  s = e[i] / r;
190  c = p / r;
191  p = c * d[i] - s * g;
192  d[i+1] = h + s * (c * g + s * d[i]);
193 
194 
195  for (int k = 0; k < n; k++) {
196  h = V(k,i+1);
197  V(k,i+1) = s * V(k,i) + c * h;
198  V(k,i) = c * V(k,i) - s * h;
199  }
200  }
201  p = -s * s2 * c3 * el1 * e[l] / dl1;
202  e[l] = s * p;
203  d[l] = c * p;
204 
205 
206  } while (fabs(e[l]) > eps*tst1);
207  }
208  d[l] = d[l] + f;
209  e[l] = 0.0;
210  }
211 
212 
213  for (int i = 0; i < n-1; i++) {
214  int k = i;
215  T p = d[i];
216  for (int j = i+1; j < n; j++) {
217  if (d[j] > p) {
218  k = j;
219  p = d[j];
220  }
221  }
222  if (k != i) {
223  d[k] = d[i];
224  d[i] = p;
225  for (int j = 0; j < n; j++) {
226  p = V(j,i);
227  V(j,i) = V(j,k);
228  V(j,k) = p;
229  }
230  }
231  }
232 }
233 template<class T>
234 void
236 {
237  V = A;
238  point_basic<T> e;
239  tred2 (V, d, e);
240  tql2 (V, d, e);
241 }
242 #define _RHEOLEF_instanciation(T) \
243 template void eigen_decomposition (const tensor_basic<T>& A, tensor_basic<T>& V, point_basic<T>& d);
244 
246 
247 }// namespace rheolef
248