source: proiecte/PPPP/eigenface/new/jacobi.c @ 91

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

PPPP - jacobi updated

File size: 4.1 KB
Line 
1#include <stdio.h>
2#include <math.h>
3#include <malloc.h>
4#include <omp.h>
5
6#define ROTATE(a,i,j,k,l) g=a[i][j];h=a[k][l];a[i][j]=g-s*(h+g*tau);\
7a[k][l]=h+s*(g-h*tau);
8
9/*
10Computes all eigenvalues and eigenvectors of a real symmetric matrix a[1..n][1..n]. On
11output, elements of a above the diagonal are destroyed. d[1..n] returns the eigenvalues of a.
12v[1..n][1..n] is a matrix whose columns contain, on output, the normalized eigenvectors of
13a. nrot returns the number of Jacobi rotations that were required.
14*/
15void jacobi(float **a, int n, float d[], float **v, int *nrot)
16{
17        int j,iq,ip,i;
18        float tresh,theta,tau,sm,s,h,g,c,*b,*z;
19        float t;       
20        b = (float *) malloc(n * sizeof(float));
21        z = (float *) malloc(n * sizeof(float));
22       
23        int nthreads, tid;
24
25        /* Fork a team of threads giving them their own copies of variables */
26        #pragma omp parallel private(nthreads, tid)
27        {
28
29        /* Obtain thread number */
30        tid = omp_get_thread_num();
31        printf("Hello World from thread = %d\n", tid);
32
33        /* Only master thread does this */
34        if (tid == 0) 
35    {
36        nthreads = omp_get_num_threads();
37        printf("Number of threads = %d\n", nthreads);
38    }
39
40        }  /* All threads join master thread and disband */
41               
42        for (ip=0;ip<n;ip++) {          // Initialize to the identity matrix.
43                for (iq=0;iq<n;iq++) 
44                        v[ip][iq]=0.0;
45                v[ip][ip]=1.0;
46        }
47        for (ip=0;ip<n;ip++) {     // Initialize b and d to the diagonal of a.
48                b[ip]=d[ip]=a[ip][ip];                                 
49                z[ip]=0.0;                         // This vector will accumulate terms of the form t*a[pq] as in equation (11.1.14).
50        }
51       
52        *nrot=0;
53        for (i=1;i<=50;i++) {
54                sm=0.0;
55                for (ip=0;ip<n-1;ip++) {                        // Sum off-diagonal elements.
56                        for (iq=ip+1;iq<n;iq++)
57                        sm += fabs(a[ip][iq]);
58                }
59                if (sm == 0.0) {                                // The normal return, which relies on quadratic convergence to machine underflow.
60                        free(z);
61                        free(b);
62                        return;
63                }
64                if (i < 4)
65                        tresh=0.2*sm/(n*n);                             // ...on the first three sweeps.
66                else
67                        tresh=0.0;                                      // ...thereafter.
68                for (ip=0;ip<n-1;ip++) {
69                        for (iq=ip+1;iq<n;iq++) {
70                                g=100.0*fabs(a[ip][iq]);
71                                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.
72                                        && (float)(fabs(d[iq])+g) == (float)fabs(d[iq]))
73                                        a[ip][iq]=0.0;
74                                else if (fabs(a[ip][iq]) > tresh) {
75                                        h=d[iq]-d[ip];
76                                        if ((float)(fabs(h)+g) == (float)fabs(h))
77                                                t=(a[ip][iq])/h;        // t = 1/(2*theta)
78                                        else {
79                                                theta=0.5*h/(a[ip][iq]); 
80                                                t=1.0/(fabs(theta)+sqrt(1.0+theta*theta));
81                                                if (theta < 0.0) t = -t;
82                                        }
83                                       
84                                        c=1.0/sqrt(1+t*t);
85                                        s=t*c;
86                                        tau=s/(1.0+c);
87                                        h=t*a[ip][iq];
88                                        z[ip] -= h;
89                                        z[iq] += h;
90                                        d[ip] -= h;
91                                        d[iq] += h;
92                                        a[ip][iq]=0.0;
93                                       
94                                        for (j=0;j<ip-1;j++) { // Case of rotations 1 <= j < p.
95                                                ROTATE(a,j,ip,j,iq)
96                                        } 
97                                        for (j=ip+1;j<iq-1;j++) { // Case of rotations p < j < q.
98                                                ROTATE(a,ip,j,j,iq)
99                                        }
100                                        for (j=iq+1;j<n;j++) {  // Case of rotations q < j <= n.
101                                                ROTATE(a,ip,j,iq,j)
102                                        }
103                                        for (j=0;j<n;j++) {
104                                                ROTATE(v,j,ip,j,iq)
105                                        }
106                                       
107                                        ++(*nrot);
108                                }
109                        }
110                }
111               
112                for (ip=0;ip<n;ip++) {
113                        b[ip] += z[ip];
114                        d[ip]=b[ip];            // Update d with the sum of t*a[pq],
115                        z[ip]=0.0;                      // and reinitialize z.
116                }
117        }
118       
119        printf("Too many iterations in routine jacobi\n");
120}
121
122int main(int argc, char * argv[])
123{
124        int n, i, j;
125        float *d;
126        float **a;
127        float **v;
128        int nrot = 0;
129
130        char * filename = argv[1];     
131        FILE * f = fopen(filename, "r");
132        fscanf(f,"%d", &n);
133       
134        a = (float **)malloc(n * sizeof(float*));
135        for(i = 0; i < n; i++)
136                a[i] = (float *)malloc(n * sizeof(float));
137       
138        v  = (float **)malloc(n * sizeof(float*));
139        for(i = 0; i < n; i++)
140                v[i] = (float *)malloc(n * sizeof(float));
141       
142        d = (float *)malloc(n * sizeof(float));
143       
144        for(i = 0; i < n; i++)
145                for(j = 0; j < n; j++)
146                        fscanf(f,"%f", &a[i][j]);
147        for(i = 0; i < n; i++)
148        {
149                for(j = 0; j < n; j++)
150                        printf("%f ", a[i][j]);
151                printf("\n");
152        }
153       
154        jacobi(a, n, d, v, &nrot); 
155       
156        printf("v:\n");
157        for(i = 0; i < n; i++)
158        {
159                for(j = 0; j < n; j++)
160                        printf("%f ", v[i][j]);
161                printf("\n");
162        }
163
164        printf("d:\n");
165        for(i = 0; i < n; i++)
166        {
167                printf("%f ", d[i]);
168        }
169        printf("\n");
170
171        return 0;
172}
173
Note: See TracBrowser for help on using the repository browser.