KSquare Utilities
EigenVector.cpp
Go to the documentation of this file.
1 /* EigenVector.cpp Implements simplified Eigen Vector routine for 2 x 2 matrix
2  * code was derived from "Numerical Recipes in c++"
3  */
4 #include "FirstIncludes.h"
5 
6 #include <stdlib.h>
7 #include <stdio.h>
8 
9 #include <cmath>
10 #include <iostream>
11 #include <vector>
12 
13 #include "MemoryDebug.h"
14 
15 #include "KKBaseTypes.h"
16 
17 using namespace std;
18 
19 #include "EigenVector.h"
20 #include "KKBaseTypes.h"
21 #include "KKException.h"
22 #include "OSservices.h"
23 using namespace KKB;
24 
25 
26 //void Tred2 (Mat_IO_DP &a,
27 // Vec_0_DP &d,
28 // Vec_0_DP, &e
29 // )
30 
31 void KKB::Tred2 (kkint32 n,
32  double a[2][2],
33  double* d,
34  double* e
35  )
36 {
37  if ((n < 1) || (n > 2))
38  throw KKException("KKB::Tred2 n:" + StrFromInt32(n) + " out of range of 1 thru 2"); kkint32 i, j, k, l;
39 
40  double scale, hh, h, g, f;
41 
42  for (i = n - 1; i > 0; i--)
43  {
44  l = i - 1;
45  h = scale = 0.0;
46 
47  if (l > 0)
48  {
49  for (k = 0; k < l + 1; k++)
50  scale += fabs (a[i][k]);
51 
52  if (scale == 0.0)
53  {
54  e[i] = a[i][l];
55  }
56 
57  else
58  {
59  for (k = 0; k < l + 1; k++)
60  {
61  if (scale == 0.0)
62  a[i][k] = 0.0;
63  else
64  a[i][k] /= scale; // Use scaled a's for transformation
65  h+= a[i][k] * a[i][k]; // h = sigma
66  }
67 
68  f = a[i][l];
69  g = (f > 0 ? -sqrt(h) : sqrt(h));
70  e[i] = scale * g;
71  h -= f * g;
72  a[i][l] = f - g;
73  f = 0.0;
74 
75  for (j = 0; j < l + 1; j++)
76  {
77  a[j][i] = a[i][j] / h;
78  g = 0.0;
79  for (k = 0; k < j + 1; k++)
80  g += a[j][k] * a[i][k];
81 
82  for (k = j + 1; k < l + 1; k++)
83  g += a[k][j] * a[i][k];
84 
85  e[j] = g / h;
86 
87  f += e[j] * a[i][j];
88  } /* for (j = 0; */
89 
90  hh = f / (h + h);
91 
92  for (j = 0; j < l + 1; j++)
93  {
94  f = a[i][j];
95  e[j] = g = e[j] - hh * f;
96  for (k = 0; k < j + 1; k++)
97  a[j][k] -= (f * e[k] + g * a[i][k]);
98  }
99  }
100  } /* if (l > 0) */
101  else
102  {
103  e[i] = a[i][l];
104  }
105 
106  d[i] = h;
107  }
108 
109  // We can now calculate Eigen Vectors
110 
111  d[0] = 0.0;
112  e[0] = 0.0;
113 
114  for (i = 0; i < n; i++)
115  {
116  l = i;
117 
118  if (d[i] != 0.0)
119  {
120  for (j = 0; j < l; j++)
121  {
122  g = 0.0;
123  for (k = 0; k < l; k++)
124  g += a[i][k] * a[k][j];
125 
126  for (k = 0; k < l; k++)
127  a[k][j] -= g * a[k][i];
128  }
129  }
130 
131  d[i] = a[i][i];
132 
133  // Reset row and column of 'a' to identity matrix;
134  a[i][i] = 1.0;
135  for (j = 0; j < l; j++)
136  a[j][i] = a[i][j] = 0.0;
137  } /* for (i) */
138 
139 } /* Tred2 */
140 
141 
142 
143 template<class T>
144 inline const T SIGN (const T& a,
145  const T& b
146  )
147 {
148  if (b >= 0)
149  {
150  if (a >= 0)
151  return a;
152  else
153  return -a;
154  }
155 
156  else
157  {
158  if (a >- 0)
159  return -a;
160  else
161  return a;
162  }
163 } /* SIGN */
164 
165 
166 #define SQR(X) ((X) * (X))
167 
168 
169 // Computes sqrt (a^2 + b^2) without destructive underflow or overflow
170 double pythag (const double a,
171  const double b
172  )
173 {
174  double absa, absb;
175 
176  absa = fabs (a);
177  absb = fabs (b);
178 
179  if (absa > absb)
180  {
181  return absa * sqrt (1.0 + SQR (absb / absa));
182  }
183  else
184  {
185  if (absb == 0.0)
186  return 0.0;
187  else
188  return absb * sqrt (1.0 + SQR (absa / absb));
189  }
190 } /* pythag */
191 
192 
193 
194 
195 void KKB::tqli (kkint32 n,
196  double* d,
197  double* e,
198  double z[2][2]
199  )
200 {
201  if ((n < 1) || (n > 2))
202  throw KKException ("KKB::tqli n:" + StrFromInt32(n) + " out of range of 1 thru 2");
203 
204  kkint32 m, l, iter, i, k;
205  double s, r, p,g, f, dd, c, b;
206 
207  for (i = 1; i < n; i++)
208  e[i - 1] = e[i];
209 
210  e[n - 1] = 0.0;
211 
212  for (l = 0; l < n; l++)
213  {
214  iter = 0;
215 
216  do
217  {
218  for (m = l; m < n - 1; m++)
219  {
220  // Looking for a single small sub-diagonal element
221  // to split the matrix
222  dd = fabs (d[m]) + fabs (d[m + 1]);
223  if (fabs (e[m]) + dd == dd)
224  break;
225  }
226 
227  if (m != l)
228  {
229  if (iter == 100)
230  {
231  cerr << std::endl << std::endl
232  << "EigenVector::tqli **** ERROR **** To many iterations in tqli" << std::endl
233  << std::endl;
234  //osWaitForEnter ();
235  //exit (-1);
236  return;
237  }
238  iter++;
239 
240  g = (d[l + 1] - d[l]) / (2.0 * e[1]);
241  r = pythag (g, 1.0);
242  g = d[m] - d[l] + e[l] / (g + SIGN (r, g));
243  s = c = 1.0;
244  p = 0.0;
245 
246  for (i = m - 1; i >= l; i--)
247  {
248  f = s * e[i];
249  b = c * e[i];
250  e[i + 1] = (r = pythag (f, g));
251  if (r == 0.0)
252  {
253  d[i + 1] -= p;
254  e[m] = 0.0;
255  break;
256  }
257 
258  s = f / r;
259  c = g / r;
260  g = d[i + 1] - p;
261  r = (d[i] - g) * s + 2.0 * c * b;
262  d[i + 1] = g + (p = s * r);
263  g = c * r - b;
264 
265  // Next loop can be omitted if eigen vectors not wanted
266 
267  for (k = 0; k < n; k++)
268  {
269  f = z[k][i + 1];
270  z[k][i + 1] = s * z[k][i] + c * f;
271  z[k][i] = c * z[k][i] - s * f;
272  } /* for (k) */
273 
274  } /* for (i) */
275 
276  if ((r == 0.0) && (i >= l))
277  continue;
278 
279  d[l] -= p;
280  e[l] = g;
281  e[m] = 0.0;
282  }
283  }
284  while (m != l);
285 
286  } /* for (l) */
287 
288  return;
289 } /* tqli */
__int32 kkint32
Definition: KKBaseTypes.h:88
#define SQR(X)
KKStr operator+(const char *right) const
Definition: KKStr.cpp:3986
KKTHread * KKTHreadPtr
KKStr operator+(const char *left, const KKStr &right)
Definition: KKStr.cpp:3976
const T SIGN(const T &a, const T &b)
Definition: Matrix.cpp:1196
void tqli(kkint32 n, double *d, double *e, double z[2][2])
void Tred2(kkint32 n, double a[2][2], double *d, double *e)
Definition: EigenVector.cpp:31
KKException(const KKStr &_exceptionStr)
Definition: KKException.cpp:45
double pythag(const double a, const double b)
KKStr StrFromInt32(kkint32 i)
Definition: KKStr.cpp:5175