GestureRecognitionToolkit  Version: 0.1.0
The Gesture Recognition Toolkit (GRT) is a cross-platform, open-source, c++ machine learning library for real-time gesture recognition.
EigenvalueDecomposition.cpp
1 /*
2  This code is based on EigenvalueDecomposition.java from http://math.nist.gov/javanumerics/jama/
3  The license below is from that file.
4  */
5 
6 /*
7  * This software is a cooperative product of The MathWorks and the National
8  * Institute of Standards and Technology (NIST) which has been released to the
9  * public domain. Neither The MathWorks nor NIST assumes any responsibility
10  * whatsoever for its use by other parties, and makes no guarantees, expressed
11  * or implied, about its quality, reliability, or any other characteristic.
12 
13  * EigenvalueDecomposition.java
14  * Copyright (C) 1999 The Mathworks and NIST
15  *
16  */
17 
18 #include "EigenvalueDecomposition.h"
19 
20 GRT_BEGIN_NAMESPACE
21 
22 EigenvalueDecomposition::EigenvalueDecomposition(){
23  warningLog.setProceedingText("[WARNING EigenvalueDecomposition]");
24 }
25 
26 EigenvalueDecomposition::~EigenvalueDecomposition(){
27 
28 }
29 
30 bool EigenvalueDecomposition::decompose(const MatrixFloat &a){
31 
32  n = a.getNumCols();
33  eigenvectors.resize(n,n);
34  realEigenvalues.resize(n);
35  complexEigenvalues.resize(n);
36 
37  issymmetric = true;
38  for(int j = 0; (j < n) & issymmetric; j++) {
39  for(int i = 0; (i < n) & issymmetric; i++) {
40  issymmetric = (a[i][j] == a[j][i]);
41  }
42  }
43 
44  if (issymmetric) {
45  for(int i = 0; i < n; i++) {
46  for(int j = 0; j < n; j++) {
47  eigenvectors[i][j] = a[i][j];
48  }
49  }
50 
51  // Tridiagonalize.
52  tred2();
53 
54  // Diagonalize.
55  tql2();
56 
57  } else {
58  h.resize(n,n);
59  ort.resize(n);
60 
61  for(int j = 0; j < n; j++) {
62  for(int i = 0; i < n; i++) {
63  h[i][j] = a[i][j];
64  }
65  }
66 
67  // Reduce to Hessenberg form.
68  orthes();
69 
70  // Reduce Hessenberg to real Schur form.
71  hqr2();
72  }
73 
74  return true;
75 }
76 
78 
79  for(int j = 0; j < n; j++) {
80  realEigenvalues[j] = eigenvectors[n-1][j];
81  }
82 
83  // Householder reduction to tridiagonal form.
84  for(int i = n-1; i > 0; i--) {
85 
86  // Scale to avoid under/overflow.
87  Float scale = 0.0;
88  Float h = 0.0;
89  for (int k = 0; k < i; k++) {
90  scale = scale + fabs(realEigenvalues[k]);
91  }
92  if (scale == 0.0) {
93  complexEigenvalues[i] = realEigenvalues[i-1];
94  for (int j = 0; j < i; j++) {
95  realEigenvalues[j] = eigenvectors[i-1][j];
96  eigenvectors[i][j] = 0.0;
97  eigenvectors[j][i] = 0.0;
98  }
99  } else {
100 
101  // Generate Householder vector.
102  for (int k = 0; k < i; k++) {
103  realEigenvalues[k] /= scale;
104  h += realEigenvalues[k] * realEigenvalues[k];
105  }
106  Float f = realEigenvalues[i-1];
107  Float g = sqrt(h);
108  if (f > 0) {
109  g = -g;
110  }
111  complexEigenvalues[i] = scale * g;
112  h = h - f * g;
113  realEigenvalues[i-1] = f - g;
114  for (int j = 0; j < i; j++) {
115  complexEigenvalues[j] = 0.0;
116  }
117 
118  // Apply similarity transformation to remaining columns.
119  for (int j = 0; j < i; j++) {
120  f = realEigenvalues[j];
121  eigenvectors[j][i] = f;
122  g = complexEigenvalues[j] + eigenvectors[j][j] * f;
123  for (int k = j+1; k <= i-1; k++) {
124  g += eigenvectors[k][j] * realEigenvalues[k];
125  complexEigenvalues[k] += eigenvectors[k][j] * f;
126  }
127  complexEigenvalues[j] = g;
128  }
129  f = 0.0;
130  for (int j = 0; j < i; j++) {
131  complexEigenvalues[j] /= h;
132  f += complexEigenvalues[j] * realEigenvalues[j];
133  }
134  Float hh = f / (h + h);
135  for (int j = 0; j < i; j++) {
136  complexEigenvalues[j] -= hh * realEigenvalues[j];
137  }
138  for (int j = 0; j < i; j++) {
139  f = realEigenvalues[j];
140  g = complexEigenvalues[j];
141  for (int k = j; k <= i-1; k++) {
142  eigenvectors[k][j] -= (f * complexEigenvalues[k] + g * realEigenvalues[k]);
143  }
144  realEigenvalues[j] = eigenvectors[i-1][j];
145  eigenvectors[i][j] = 0.0;
146  }
147  }
148  realEigenvalues[i] = h;
149  }
150 
151  // Accumulate transformations.
152  for(int i = 0; i < n-1; i++) {
153  eigenvectors[n-1][i] = eigenvectors[i][i];
154  eigenvectors[i][i] = 1.0;
155  Float h = realEigenvalues[i+1];
156  if (h != 0.0) {
157  for (int k = 0; k <= i; k++) {
158  realEigenvalues[k] = eigenvectors[k][i+1] / h;
159  }
160  for (int j = 0; j <= i; j++) {
161  Float g = 0.0;
162  for (int k = 0; k <= i; k++) {
163  g += eigenvectors[k][i+1] * eigenvectors[k][j];
164  }
165  for (int k = 0; k <= i; k++) {
166  eigenvectors[k][j] -= g * realEigenvalues[k];
167  }
168  }
169  }
170  for(int k = 0; k <= i; k++) {
171  eigenvectors[k][i+1] = 0.0;
172  }
173  }
174  for(int j = 0; j < n; j++) {
175  realEigenvalues[j] = eigenvectors[n-1][j];
176  eigenvectors[n-1][j] = 0.0;
177  }
178  eigenvectors[n-1][n-1] = 1.0;
179  complexEigenvalues[0] = 0.0;
180 
181  return;
182 }
183 
185 
186  for(int i = 1; i < n; i++) {
187  complexEigenvalues[i-1] = complexEigenvalues[i];
188  }
189  complexEigenvalues[n-1] = 0.0;
190 
191  Float f = 0.0;
192  Float tst1 = 0.0;
193  Float eps = pow(2.0,-52.0);
194  for (int l = 0; l < n; l++) {
195 
196  // Find small subdiagonal element
197  tst1 = findMax(tst1,fabs(realEigenvalues[l]) + fabs(complexEigenvalues[l]));
198  int m = l;
199  while (m < n) {
200  if(fabs(complexEigenvalues[m]) <= eps*tst1) {
201  break;
202  }
203  m++;
204  }
205 
206  // If m == l, d[l] is an eigenvalue, otherwise, iterate.
207  if (m > l) {
208  int iter = 0;
209  do {
210  iter = iter + 1; // (Could check iteration count here.)
211 
212  // Compute implicit shift
213  Float g = realEigenvalues[l];
214  Float p = (realEigenvalues[l+1] - g) / (2.0 * complexEigenvalues[l]);
215  Float r = hypot(p,1.0);
216  if (p < 0) {
217  r = -r;
218  }
219  realEigenvalues[l] = complexEigenvalues[l] / (p + r);
220  realEigenvalues[l+1] = complexEigenvalues[l] * (p + r);
221  Float dl1 = realEigenvalues[l+1];
222  Float h = g - realEigenvalues[l];
223  for (int i = l+2; i < n; i++) {
224  realEigenvalues[i] -= h;
225  }
226  f = f + h;
227 
228  // Implicit QL transformation.
229  p = realEigenvalues[m];
230  Float c = 1.0;
231  Float c2 = c;
232  Float c3 = c;
233  Float el1 = complexEigenvalues[l+1];
234  Float s = 0.0;
235  Float s2 = 0.0;
236  for (int i = m-1; i >= l; i--) {
237  c3 = c2;
238  c2 = c;
239  s2 = s;
240  g = c * complexEigenvalues[i];
241  h = c * p;
242  r = hypot(p,complexEigenvalues[i]);
243  complexEigenvalues[i+1] = s * r;
244  s = complexEigenvalues[i] / r;
245  c = p / r;
246  p = c * realEigenvalues[i] - s * g;
247  realEigenvalues[i+1] = h + s * (c * g + s * realEigenvalues[i]);
248 
249  // Accumulate transformation.
250  for(int k = 0; k < n; k++) {
251  h = eigenvectors[k][i+1];
252  eigenvectors[k][i+1] = s * eigenvectors[k][i] + c * h;
253  eigenvectors[k][i] = c * eigenvectors[k][i] - s * h;
254  }
255  }
256  p = -s * s2 * c3 * el1 * complexEigenvalues[l] / dl1;
257  complexEigenvalues[l] = s * p;
258  realEigenvalues[l] = c * p;
259 
260  // Check for convergence.
261  } while (fabs(complexEigenvalues[l]) > eps*tst1);
262  }
263  realEigenvalues[l] = realEigenvalues[l] + f;
264  complexEigenvalues[l] = 0.0;
265  }
266 
267  // Sort eigenvalues and corresponding vectors.
268  for(int i = 0; i < n-1; i++) {
269  int k = i;
270  Float p = realEigenvalues[i];
271  for (int j = i+1; j < n; j++) {
272  if(realEigenvalues[j] < p) {
273  k = j;
274  p = realEigenvalues[j];
275  }
276  }
277  if (k != i) {
278  realEigenvalues[k] = realEigenvalues[i];
279  realEigenvalues[i] = p;
280  for (int j = 0; j < n; j++) {
281  p = eigenvectors[j][i];
282  eigenvectors[j][i] = eigenvectors[j][k];
283  eigenvectors[j][k] = p;
284  }
285  }
286  }
287  return;
288 }
289 
291 
292  int low = 0;
293  int high = n-1;
294 
295  for(int m = low+1; m <= high-1; m++) {
296 
297  // Scale column.
298  Float scale = 0.0;
299  for (int i = m; i <= high; i++) {
300  scale = scale + fabs(h[i][m-1]);
301  }
302  if (scale != 0.0) {
303 
304  // Compute Householder transformation.
305  Float ht = 0.0;
306  for(int i = high; i >= m; i--) {
307  ort[i] = h[i][m-1]/scale;
308  ht += ort[i] * ort[i];
309  }
310  Float g = sqrt( ht );
311  if (ort[m] > 0) {
312  g = -g;
313  }
314  ht = ht - ort[m] * g;
315  ort[m] = ort[m] - g;
316 
317  // Apply Householder similarity transformation
318  // H = (I-u*u'/h)*H*(I-u*u')/h)
319  for (int j = m; j < n; j++) {
320  Float f = 0.0;
321  for (int i = high; i >= m; i--) {
322  f += ort[i]*h[i][j];
323  }
324  f = f/ht;
325  for (int i = m; i <= high; i++) {
326  h[i][j] -= f*ort[i];
327  }
328  }
329 
330  for(int i = 0; i <= high; i++) {
331  Float f = 0.0;
332  for(int j = high; j >= m; j--) {
333  f += ort[j]*h[i][j];
334  }
335  f = f/ht;
336  for (int j = m; j <= high; j++) {
337  h[i][j] -= f*ort[j];
338  }
339  }
340  ort[m] = scale*ort[m];
341  h[m][m-1] = scale*g;
342  }
343  }
344 
345  // Accumulate transformations (Algol's ortran).
346  for (int i = 0; i < n; i++) {
347  for (int j = 0; j < n; j++) {
348  eigenvectors[i][j] = (i == j ? 1.0 : 0.0);
349  }
350  }
351 
352  for (int m = high-1; m >= low+1; m--) {
353  if (h[m][m-1] != 0.0) {
354  for (int i = m+1; i <= high; i++) {
355  ort[i] = h[i][m-1];
356  }
357  for (int j = m; j <= high; j++) {
358  Float g = 0.0;
359  for (int i = m; i <= high; i++) {
360  g += ort[i] * eigenvectors[i][j];
361  }
362  // Double division avoids possible underflow
363  g = (g / ort[m]) / h[m][m-1];
364  for (int i = m; i <= high; i++) {
365  eigenvectors[i][j] += g * ort[i];
366  }
367  }
368  }
369  }
370  return;
371 }
372 
374 
375  // Initialize
376  int nn = this->n;
377  int n = nn-1;
378  int low = 0;
379  int high = nn-1;
380  Float eps = pow(2.0,-52.0);
381  Float exshift = 0.0;
382  Float p=0,q=0,r=0,s=0,z=0,t,w,x,y;
383 
384  // Store roots isolated by balanc and compute matrix norm
385  Float norm = 0.0;
386  for(int i = 0; i < nn; i++) {
387  if( (i < low) | (i > high) ){
388  realEigenvalues[i] = h[i][i];
389  complexEigenvalues[i] = 0.0;
390  }
391  for (int j = findMax(i-1,0); j < nn; j++) {
392  norm = norm + fabs(h[i][j]);
393  }
394  }
395 
396  // Outer loop over eigenvalue index
397  int iter = 0;
398  while (n >= low) {
399 
400  // Look for single small sub-diagonal element
401  int l = n;
402  while (l > low) {
403  s = fabs(h[l-1][l-1]) + fabs(h[l][l]);
404  if (s == 0.0) {
405  s = norm;
406  }
407  if(fabs(h[l][l-1]) < eps * s) {
408  break;
409  }
410  l--;
411  }
412 
413  // Check for convergence
414  // One root found
415  if(l == n) {
416  h[n][n] = h[n][n] + exshift;
417  realEigenvalues[n] = h[n][n];
418  complexEigenvalues[n] = 0.0;
419  n--;
420  iter = 0;
421 
422  // Two roots found
423  } else if (l == n-1) {
424  w = h[n][n-1] * h[n-1][n];
425  p = (h[n-1][n-1] - h[n][n]) / 2.0;
426  q = p * p + w;
427  z = sqrt(fabs(q));
428  h[n][n] = h[n][n] + exshift;
429  h[n-1][n-1] = h[n-1][n-1] + exshift;
430  x = h[n][n];
431 
432  // Real pair
433  if (q >= 0) {
434  if (p >= 0) {
435  z = p + z;
436  } else {
437  z = p - z;
438  }
439  realEigenvalues[n-1] = x + z;
440  realEigenvalues[n] = realEigenvalues[n-1];
441  if (z != 0.0) {
442  realEigenvalues[n] = x - w / z;
443  }
444  complexEigenvalues[n-1] = 0.0;
445  complexEigenvalues[n] = 0.0;
446  x = h[n][n-1];
447  s = fabs(x) + fabs(z);
448  p = x / s;
449  q = z / s;
450  r = sqrt(p * p+q * q);
451  p = p / r;
452  q = q / r;
453 
454  // Row modification
455  for(int j = n-1; j < nn; j++) {
456  z = h[n-1][j];
457  h[n-1][j] = q * z + p * h[n][j];
458  h[n][j] = q * h[n][j] - p * z;
459  }
460 
461  // Column modification
462  for(int i = 0; i <= n; i++) {
463  z = h[i][n-1];
464  h[i][n-1] = q * z + p * h[i][n];
465  h[i][n] = q * h[i][n] - p * z;
466  }
467 
468  // Accumulate transformations
469  for(int i = low; i <= high; i++) {
470  z = eigenvectors[i][n-1];
471  eigenvectors[i][n-1] = q * z + p * eigenvectors[i][n];
472  eigenvectors[i][n] = q * eigenvectors[i][n] - p * z;
473  }
474 
475  // Complex pair
476  } else {
477  realEigenvalues[n-1] = x + p;
478  realEigenvalues[n] = x + p;
479  complexEigenvalues[n-1] = z;
480  complexEigenvalues[n] = -z;
481  }
482  n = n - 2;
483  iter = 0;
484 
485  // No convergence yet
486  } else {
487 
488  // Form shift
489  x = h[n][n];
490  y = 0.0;
491  w = 0.0;
492  if (l < n) {
493  y = h[n-1][n-1];
494  w = h[n][n-1] * h[n-1][n];
495  }
496 
497  // Wilkinson's original ad hoc shift
498  if (iter == 10) {
499  exshift += x;
500  for (int i = low; i <= n; i++) {
501  h[i][i] -= x;
502  }
503  s = fabs(h[n][n-1]) + fabs(h[n-1][n-2]);
504  x = y = 0.75 * s;
505  w = -0.4375 * s * s;
506  }
507 
508  // MATLAB's new ad hoc shift
509  if (iter == 30) {
510  s = (y - x) / 2.0;
511  s = s * s + w;
512  if (s > 0) {
513  s = sqrt(s);
514  if (y < x) {
515  s = -s;
516  }
517  s = x - w / ((y - x) / 2.0 + s);
518  for(int i = low; i <= n; i++) {
519  h[i][i] -= s;
520  }
521  exshift += s;
522  x = y = w = 0.964;
523  }
524  }
525 
526  iter = iter + 1; // (Could check iteration count here.)
527 
528  // Look for two consecutive small sub-diagonal elements
529  int m = n-2;
530  while (m >= l) {
531  z = h[m][m];
532  r = x - z;
533  s = y - z;
534  p = (r * s - w) / h[m+1][m] + h[m][m+1];
535  q = h[m+1][m+1] - z - r - s;
536  r = h[m+2][m+1];
537  s = fabs(p) + fabs(q) + fabs(r);
538  p = p / s;
539  q = q / s;
540  r = r / s;
541  if(m == l){
542  break;
543  }
544  if(fabs(h[m][m-1]) * (fabs(q) +fabs(r)) <
545  eps * (fabs(p) * (fabs(h[m-1][m-1]) + fabs(z) +
546  fabs(h[m+1][m+1])))) {
547  break;
548  }
549  m--;
550  }
551 
552  for(int i = m+2; i <= n; i++) {
553  h[i][i-2] = 0.0;
554  if (i > m+2) {
555  h[i][i-3] = 0.0;
556  }
557  }
558 
559  // Double QR step involving rows l:n and columns m:n
560  for(int k = m; k <= n-1; k++) {
561  bool notlast = (k != n-1);
562  if(k != m) {
563  p = h[k][k-1];
564  q = h[k+1][k-1];
565  r = (notlast ? h[k+2][k-1] : 0.0);
566  x = fabs(p) + fabs(q) + fabs(r);
567  if (x != 0.0) {
568  p = p / x;
569  q = q / x;
570  r = r / x;
571  }
572  }
573  if(x == 0.0){
574  break;
575  }
576  s = sqrt(p * p + q * q + r * r);
577  if(p < 0){
578  s = -s;
579  }
580  if(s != 0){
581  if(k != m){
582  h[k][k-1] = -s * x;
583  }else if(l != m){
584  h[k][k-1] = -h[k][k-1];
585  }
586  p = p + s;
587  x = p / s;
588  y = q / s;
589  z = r / s;
590  q = q / p;
591  r = r / p;
592 
593  // Row modification
594  for(int j = k; j < nn; j++) {
595  p = h[k][j] + q * h[k+1][j];
596  if(notlast){
597  p = p + r * h[k+2][j];
598  h[k+2][j] = h[k+2][j] - p * z;
599  }
600  h[k][j] = h[k][j] - p * x;
601  h[k+1][j] = h[k+1][j] - p * y;
602  }
603 
604  // Column modification
605  for (int i = 0; i <= findMin(n,k+3); i++) {
606  p = x * h[i][k] + y * h[i][k+1];
607  if(notlast){
608  p = p + z * h[i][k+2];
609  h[i][k+2] = h[i][k+2] - p * r;
610  }
611  h[i][k] = h[i][k] - p;
612  h[i][k+1] = h[i][k+1] - p * q;
613  }
614 
615  // Accumulate transformations
616  for(int i = low; i <= high; i++) {
617  p = x * eigenvectors[i][k] + y * eigenvectors[i][k+1];
618  if(notlast){
619  p = p + z * eigenvectors[i][k+2];
620  eigenvectors[i][k+2] = eigenvectors[i][k+2] - p * r;
621  }
622  eigenvectors[i][k] = eigenvectors[i][k] - p;
623  eigenvectors[i][k+1] = eigenvectors[i][k+1] - p * q;
624  }
625  } // (s != 0)
626  } // k loop
627  } // check convergence
628  } // while (n >= low)
629 
630  // Backsubstitute to find vectors of upper triangular form
631  if(norm == 0.0){
632  return;
633  }
634 
635  for(n = nn-1; n >= 0; n--) {
636  p = realEigenvalues[n];
637  q = complexEigenvalues[n];
638 
639  // Real vector
640  if (q == 0) {
641  int l = n;
642  h[n][n] = 1.0;
643  for(int i = n-1; i >= 0; i--) {
644  w = h[i][i] - p;
645  r = 0.0;
646  for(int j = l; j <= n; j++) {
647  r = r + h[i][j] * h[j][n];
648  }
649  if(complexEigenvalues[i] < 0.0) {
650  z = w;
651  s = r;
652  } else {
653  l = i;
654  if (complexEigenvalues[i] == 0.0) {
655  if (w != 0.0) {
656  h[i][n] = -r / w;
657  } else {
658  h[i][n] = -r / (eps * norm);
659  }
660 
661  // Solve real equations
662  } else {
663  x = h[i][i+1];
664  y = h[i+1][i];
665  q = (realEigenvalues[i] - p) * (realEigenvalues[i] - p) + complexEigenvalues[i] * complexEigenvalues[i];
666  t = (x * s - z * r) / q;
667  h[i][n] = t;
668  if(fabs(x) > fabs(z)) {
669  h[i+1][n] = (-r - w * t) / x;
670  } else {
671  h[i+1][n] = (-s - y * t) / z;
672  }
673  }
674 
675  // Overflow control
676  t = fabs(h[i][n]);
677  if ((eps * t) * t > 1) {
678  for(int j = i; j <= n; j++) {
679  h[j][n] = h[j][n] / t;
680  }
681  }
682  }
683  }
684 
685  // Complex vector
686  } else if (q < 0) {
687  int l = n-1;
688 
689  // Last vector component imaginary so matrix is triangular
690  if (fabs(h[n][n-1]) > fabs(h[n-1][n])) {
691  h[n-1][n-1] = q / h[n][n-1];
692  h[n-1][n] = -(h[n][n] - p) / h[n][n-1];
693  } else {
694  cdiv(0.0,-h[n-1][n],h[n-1][n-1]-p,q);
695  h[n-1][n-1] = cdivr;
696  h[n-1][n] = cdivi;
697  }
698  h[n][n-1] = 0.0;
699  h[n][n] = 1.0;
700  for(int i = n-2; i >= 0; i--) {
701  Float ra,sa,vr,vi;
702  ra = 0.0;
703  sa = 0.0;
704  for (int j = l; j <= n; j++) {
705  ra = ra + h[i][j] * h[j][n-1];
706  sa = sa + h[i][j] * h[j][n];
707  }
708  w = h[i][i] - p;
709 
710  if(complexEigenvalues[i] < 0.0) {
711  z = w;
712  r = ra;
713  s = sa;
714  } else {
715  l = i;
716  if(complexEigenvalues[i] == 0) {
717  cdiv(-ra,-sa,w,q);
718  h[i][n-1] = cdivr;
719  h[i][n] = cdivi;
720  } else {
721 
722  // Solve complex equations
723  x = h[i][i+1];
724  y = h[i+1][i];
725  vr = (realEigenvalues[i] - p) * (realEigenvalues[i] - p) + complexEigenvalues[i] * complexEigenvalues[i] - q * q;
726  vi = (realEigenvalues[i] - p) * 2.0 * q;
727  if((vr == 0.0) & (vi == 0.0)){
728  vr = eps * norm * (fabs(w) + fabs(q) + fabs(x) + fabs(y) + fabs(z));
729  }
730  cdiv(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi);
731  h[i][n-1] = cdivr;
732  h[i][n] = cdivi;
733  if (fabs(x) > (fabs(z) + fabs(q))) {
734  h[i+1][n-1] = (-ra - w * h[i][n-1] + q * h[i][n]) / x;
735  h[i+1][n] = (-sa - w * h[i][n] - q * h[i][n-1]) / x;
736  } else {
737  cdiv(-r-y*h[i][n-1],-s-y*h[i][n],z,q);
738  h[i+1][n-1] = cdivr;
739  h[i+1][n] = cdivi;
740  }
741  }
742 
743  // Overflow control
744  t = findMax(fabs(h[i][n-1]),fabs(h[i][n]));
745  if ((eps * t) * t > 1) {
746  for(int j = i; j <= n; j++) {
747  h[j][n-1] = h[j][n-1] / t;
748  h[j][n] = h[j][n] / t;
749  }
750  }
751  }
752  }
753  }
754  }
755 
756  // Vectors of isolated roots
757  for (int i = 0; i < nn; i++) {
758  if((i < low) | (i > high)){
759  for (int j = i; j < nn; j++) {
760  eigenvectors[i][j] = h[i][j];
761  }
762  }
763  }
764 
765  // Back transformation to get eigenvectors of original matrix
766  for (int j = nn-1; j >= low; j--) {
767  for (int i = low; i <= high; i++) {
768  z = 0.0;
769  for (int k = low; k <= findMin(j,high); k++) {
770  z = z + eigenvectors[i][k] * h[k][j];
771  }
772  eigenvectors[i][j] = z;
773  }
774  }
775 
776  return;
777 }
778 
779 void EigenvalueDecomposition::cdiv(Float xr, Float xi, Float yr, Float yi){
780  Float r,d;
781  if(fabs(yr) > fabs(yi)){
782  r = yi/yr;
783  d = yr + r*yi;
784  cdivr = (xr + r*xi)/d;
785  cdivi = (xi - r*xr)/d;
786  } else {
787  r = yr/yi;
788  d = yi + r*yr;
789  cdivr = (r*xr + xi)/d;
790  cdivi = (r*xi - xr)/d;
791  }
792  return;
793 }
794 
796 
797  MatrixFloat x(n,n);
798  for (int i = 0; i < n; i++) {
799  for (int j = 0; j < n; j++) {
800  x[i][j] = 0.0;
801  }
802  x[i][i] = realEigenvalues[i];
803  if(complexEigenvalues[i] > 0) {
804  x[i][i+1] = complexEigenvalues[i];
805  } else if(complexEigenvalues[i] < 0) {
806  x[i][i-1] = complexEigenvalues[i];
807  }
808  }
809  return x;
810 }
811 
813  return realEigenvalues;
814 }
815 
817  return complexEigenvalues;
818 }
819 
820 GRT_END_NAMESPACE
virtual bool resize(const unsigned int size)
Definition: Vector.h:133
void cdiv(Float xr, Float xi, Float yr, Float yi)
unsigned int getNumCols() const
Definition: Matrix.h:549
virtual bool resize(const unsigned int r, const unsigned int c)
Definition: Matrix.h:232