source: proiecte/PPPP/eigenface/new/jacobi_vector.c @ 93

Last change on this file since 93 was 93, checked in by (none), 14 years ago

added jacobi_vector + eigen_sort

File size: 3.5 KB
Line 
1#include <math.h>
2#include <stdio.h>
3#include <stdlib.h>
4#define ROTATE(a,i,j,k,l) g=a[i*n + j];h=a[k*n + l];a[i*n + j]=g-s*(h+g*tau);\
5a[k*n + l]=h+s*(g-h*tau);
6
7/*
8Computes all eigenvalues and eigenvectors of a real symmetric matrix a[1..n][1..n]. On
9output, elements of a above the diagonal are destroyed. d[1..n] returns the eigenvalues of a.
10v[1..n][1..n] is a matrix whose columns contain, on output, the normalized eigenvectors of
11a. nrot returns the number of Jacobi rotations that were required.
12*/
13void jacobi(float *a, int n, float d[], float *v, int *nrot)
14{
15        int j,iq,ip,i;
16        float tresh,theta,tau,t,sm,s,h,g,c,*b,*z;
17       
18        b = (float *) malloc(n * sizeof(float));
19        z = (float *) malloc(n * sizeof(float));
20       
21        for (ip=0;ip<n;ip++) {                                                                                                                  // Initialize to the identity matrix.
22                for (iq=0;iq<n;iq++) v[ip*n + iq]=0.0;
23                        v[ip*n + ip]=1.0;
24        }
25        for (ip=0;ip<n;ip++) {                                                                                                                  // Initialize b and d to the diagonal of a.
26                b[ip]=d[ip]=a[ip*n + ip];                                                                                                               
27                z[ip]=0.0;                                                                                                                              // This vector will accumulate terms of the form t*a[pq] as in equation (11.1.14).
28        }
29       
30        *nrot=0;
31        for (i=1;i<=50;i++) {
32                sm=0.0;
33                for (ip=0;ip<n-1;ip++) {                                                                                                                // Sum off-diagonal elements.
34                        for (iq=ip+1;iq<n;iq++)
35                        sm += fabs(a[ip*n + iq]);
36                }
37                if (sm == 0.0) {                                                                                                                        // The normal return, which relies on quadratic convergence to machine underflow.
38                        free(z);
39                        free(b);
40                        return;
41                }
42                if (i < 4)
43                        tresh=0.2*sm/(n*n);                                                                                                             // ...on the first three sweeps.
44                else
45                        tresh=0.0;                                                                                                                      // ...thereafter.
46                for (ip=0;ip<n-1;ip++) {
47                        for (iq=ip+1;iq<n;iq++) {
48                                g=100.0*fabs(a[ip*n + iq]);
49                                if (i > 4 && (float)(fabs(d[ip])+g) == (float)fabs(d[ip])                                               // After four sweeps, skip the rotation if the off-diagonal element is small.
50                                        && (float)(fabs(d[iq])+g) == (float)fabs(d[iq]))
51                                        a[ip*n + iq]=0.0;
52                                else if (fabs(a[ip*n + iq]) > tresh) {
53                                        h=d[iq]-d[ip];
54                                        if ((float)(fabs(h)+g) == (float)fabs(h))
55                                                t=(a[ip*n + iq])/h;                                                                                     // t = 1/(2*theta)
56                                        else {
57                                                theta=0.5*h/(a[ip*n + iq]);                                                                     // Equation (11.1.10).
58                                                t=1.0/(fabs(theta)+sqrt(1.0+theta*theta));
59                                                if (theta < 0.0) t = -t;
60                                        }
61                                       
62                                        c=1.0/sqrt(1+t*t);
63                                        s=t*c;
64                                        tau=s/(1.0+c);
65                                        h=t*a[ip*n + iq];
66                                        z[ip] -= h;
67                                        z[iq] += h;
68                                        d[ip] -= h;
69                                        d[iq] += h;
70                                        a[ip*n + iq]=0.0;
71                                       
72                                        for (j=0;j<=ip-1;j++) {                                                                                         // Case of rotations 1 <= j < p.
73                                                ROTATE(a,j,ip,j,iq)
74                                        }
75                                        for (j=ip+1;j<=iq-1;j++) {                                                                              // Case of rotations p < j < q.
76                                                ROTATE(a,ip,j,j,iq)
77                                        }
78                                        for (j=iq+1;j<n;j++) {                                                                                  // Case of rotations q < j <= n.
79                                                ROTATE(a,ip,j,iq,j)
80                                        }
81                                        for (j=0;j<n;j++) {
82                                                ROTATE(v,j,ip,j,iq)
83                                        }
84                                       
85                                        ++(*nrot);
86                                }
87                        }
88                }
89               
90                for (ip=0;ip<n;ip++) {
91                        b[ip] += z[ip];
92                        d[ip]=b[ip];                                                                                                                    // Updte d with the sum of t*a[pq],
93                        z[ip]=0.0;                                                                                                                      // and reinitialize z.
94                }
95        }
96       
97        printf("Too many iterations in routine jacobi\n");
98}
99
100/*
101Given the eigenvalues d[1..n] and eigenvectors v[1..n][1..n] as output from jacobi
102(x11.1) or tqli (x11.3), this routine sorts the eigenvalues into descending order, and rearranges
103the columns of v correspondingly. The method is straight insertion.
104*/
105void eigsrt(float d[], float **v, int n)       
106{
107        int k,j,i;
108        float p;
109        for (i=0;i<n-1;i++) {
110                p=d[k=i];
111                for (j=i+1;j<n;j++)
112                        if (d[j] >= p) p=d[k=j];
113                if (k != i) {
114                        d[k]=d[i];
115                        d[i]=p;
116                        for (j=0;j<n;j++) {
117                                p=v[j*n + i];
118                                v[j*n + i]=v[j*n + k];
119                                v[j*n + k]=p;
120                        }
121                }
122        }
123}
Note: See TracBrowser for help on using the repository browser.