~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
cvs/emstar/libnl/nr/svdcmp.c


  1 
  2 /*
  3  *  svdcmp.c
  4  *
  5  *  svdcmp and such from Numerical Recipes
  6  *
  7  */
  8 
  9 #include "nr.h"
 10 #include "math.h"
 11 #include <signal.h>
 12 #include <stdio.h>
 13 
 14 #define SIG_MATH
 15 
 16 void nr_sig(int reason)
 17 {
 18   nrerror("Caught FPE");
 19 }
 20 
 21 #define C(x) do { x; \
 22   if (nrerror_set) { char str[256]; sprintf(str, "SIGFPE at %s:%d", __FILE__, __LINE__); nrerror(str); goto done; } \
 23 } while(0)
 24 
 25 #define sgn(x) ((x<0) ? -1 : 1)
 26 
 27 #define SMALL_F (10e-38)
 28 
 29 #if 0
 30 #define RMULT(x,y) \
 31  (((x==0)||(y==0)) ? 0 : \
 32   (((ilogbf(x)+ilogbf(y)) < -125) ? (printf("***\n"),(sgn(x)*sgn(y)*SMALL_F)) : ((x)*(y))))
 33 #endif
 34 #define RMULT(x,y) ((x)*(y))
 35 
 36 
 37 /* compute h hat matrix */
 38 void compute_h(float **a, float **u, float w[], float **v, int m, int n,
 39                float **h, float **tmp_nm)
 40 {
 41   int j, i, k;
 42   float s;
 43 
 44   nrerror_set = 0;
 45 
 46 #ifdef SIG_MATH
 47   void (* last_sig)(int);
 48   last_sig = signal(SIGFPE, nr_sig);
 49 #endif
 50 
 51   for (j=1; j<=n; j++) {                // Calculate V W U T.
 52     for (i=1; i<=m; i++) {
 53       s=0.0;
 54       for (k=1;k<=n;k++) {
 55         C(s += u[i][k]*v[j][k]/w[k]);
 56       }
 57       tmp_nm[j][i]=s;
 58     }
 59   }
 60 
 61   for (i=1;i<=m;i++) {          // Matrix multiply A * tmp
 62     for (j=1;j<=m;j++) { 
 63       s=0.0;    
 64       for (k=1;k<=n;k++) {
 65         C(s += a[j][k]*tmp_nm[k][j]);
 66       }
 67       h[i][j] = s;
 68     }
 69   }
 70 
 71  done:
 72 #ifdef SIG_MATH
 73   signal(SIGFPE, last_sig);
 74 #endif
 75 }
 76 
 77 
 78 /**
 79   * Computes (a^2 + b^2)^1/2 without destructive underflow or overflow
 80   *
 81   */
 82 float pythag(float a, float b)
 83 {
 84   float absa, absb;
 85   
 86   absa = fabs(a);
 87   absb = fabs(b);
 88   
 89   if (absa > absb)
 90     return absa*sqrtf(1.0 + SQR(absb/absa));
 91   else
 92     return (absb==0?0.0:absb*sqrtf(1.0+SQR(absa/absb)));
 93 }  
 94 
 95 /*
 96  * Given a matrix a[1..m][1..n], this routine computes its singular 
 97  * value decomposition, * A =
 U  W  V T . The matrix U replaces 
 98  * a on output. The diagonal matrix of singular values W is output as 
 99  * a Vector w[1..n]. The matrix V (not the transpose VT) is output 
100  * as v[1..n][1..n].
101  *
102  * rv1 is a 1-n temp vector 
103  */
104 
105 void svdcmp(float **a, int m, int n, float w[], float **v, float *rv1)
106 {
107   int   flag,i,its,j,jj,k,l=0,nm=0;
108   float anorm,c,f,g,h,s,scale,x,y,z;
109 
110   nrerror_set = 0;
111 
112 #ifdef SIG_MATH
113   void (* last_sig)(int);
114   last_sig = signal(SIGFPE, nr_sig);
115 #endif
116 
117   g=scale=anorm=0.0;    //Householder reduction to bidiagonal form.
118   for (i=1;i<=n;i++) {
119     l=i+1;
120     rv1[i]=scale*g;
121     g=s=scale=0.0;
122     if (i <= m) {
123       for (k=i;k<=m;k++) C(scale += fabs(a[k][i]));
124       if (scale) {
125         for (k=i;k<=m;k++) {
126           a[k][i] /= scale;
127           C(s += RMULT(a[k][i],a[k][i]));
128         }
129         
130         f=a[i][i];
131         g = -SIGN(sqrtf(s),f);
132         h=f*g-s;
133         C(a[i][i]=f-g);
134         for (j=l;j<=n;j++) {
135           for (s=0.0,k=i;k<=m;k++) C(s += RMULT(a[k][i],a[k][j]));
136           f=s/h;
137           for (k=i;k<=m;k++) C(a[k][j] += RMULT(f,a[k][i]));
138         }
139         
140         for (k=i;k<=m;k++) C(a[k][i] *= scale);
141       }
142     }
143     
144     w[i]=scale *g;
145     C(g=s=scale=0.0);
146     if(i<= m && i != n) {
147       for (k=l;k<=n;k++) C(scale += fabs(a[i][k]));
148       if (scale) {
149         for (k=l;k<=n;k++) {
150           a[i][k] /= scale;
151           C(s += a[i][k]*a[i][k]);
152         }
153         
154         f=a[i][l];
155         g = -SIGN(sqrtf(s),f);
156         h=f*g-s;
157         C(a[i][l]=f-g);
158         
159         for (k=l;k<=n;k++) C(rv1[k]=a[i][k]/h);
160         for (j=l;j<=m;j++) {
161           for (s=0.0,k=l;k<=n;k++) C(s += a[j][k]*a[i][k]);
162           for (k=l;k<=n;k++) C(a[j][k] += s*rv1[k]);
163         }
164         
165         for (k=l;k<=n;k++) C(a[i][k] *= scale);
166       }
167     }
168     
169     C(anorm=FMAX(anorm,(fabs(w[i])+fabs(rv1[i]))));
170   }
171         
172   for (i=n;i>=1;i--) {  //Accumulation of right-hand transformations.
173     if(i < n) {
174       if (g) {
175         for (j=l;j<=n;j++) // Double division to avoid possible under ow.
176           C(v[j][i]=(a[i][j]/a[i][l])/g);
177         for (j=l;j<=n;j++) {
178           for (s=0.0,k=l;k<=n;k++) C(s += a[i][k]*v[k][j]);
179           for (k=l;k<=n;k++) C(v[k][j] += s*v[k][i]);
180         }
181       }
182       
183       for (j=l;j<=n;j++) v[i][j]=v[j][i]=0.0;
184     }
185     
186     v[i][i]=1.0;
187     g=rv1[i];
188     l=i;
189   }
190   
191   for (i=IMIN(m,n);i>=1;i--) { //Accumulation of left-hand transformations.
192     l=i+1;
193     g=w[i];
194     for (j=l;j<=n;j++) a[i][j]=0.0;
195     if (g) {
196       g=1.0/g;
197       for (j=l;j<=n;j++) {
198         for (s=0.0,k=l;k<=m;k++) C(s += RMULT(a[k][i],a[k][j]));
199         ;
200         f=(s/a[i][i])*g;
201         ;
202         for (k=i;k<=m;k++) C(a[k][j] += RMULT(f,a[k][i]));
203         ;
204       }
205       
206       for (j=i;j<=m;j++) C(a[j][i] *= g);
207     } else for (j=i;j<=m;j++) a[j][i]=0.0;
208     
209     ++a[i][i];
210   }
211   
212   for (k=n;k>=1;k--) {  
213     //Diagonalization of the bidiagonal form: Loop over
214     //singular values, and over allowed iterations. 
215     for (its=1;its<=30;its++) {
216       flag=1;
217       for (l=k;l>=1;l--) { //Test for splitting.
218         nm=l-1;                         //Note that rv1[1] is always zero.
219         if ((float)(fabs(rv1[l])+anorm) == anorm) {
220           flag=0;
221           break;
222         }
223         
224         if ((float)(fabs(w[nm])+anorm) == anorm) break;
225       }
226       if (flag) {
227         c=0.0;                  //Cancellation of rv1[l], ifl>1.
228         s=1.0;
229         for (i=l;i<=k;i++) {
230           f=s*rv1[i];
231           C(rv1[i]=c*rv1[i]);
232           if ((float)(fabs(f)+anorm) == anorm) break;
233           g=w[i];
234           h=pythag(f,g);
235           w[i]=h;
236           h=1.0/h;
237           c=g*h;
238           C(s = -f*h);
239           for (j=1;j<=m;j++) {
240             y=a[j][nm];
241             z=a[j][i];
242             a[j][nm]=y*c+z*s;
243             C(a[j][i]=z*c-y*s);
244           }
245         }
246       }
247       z=w[k];
248       
249       if (l == k) {             //Convergence.
250         if (z < 0.0) {  //Singular value is made nonnegative.
251           w[k] = -z;
252           for (j=1;j<=n;j++) C(v[j][k] = -v[j][k]);
253         }
254         break;
255       }
256       
257       if (its == 30) {
258         nrerror("no convergence in 30 svdcmp iterations");
259         goto done;
260       }
261       x=w[l];                           //Shiftfrom bottom 2-by-2minor.
262       nm=k-1;
263       y=w[nm];
264       g=rv1[nm];
265       h=rv1[k];
266       f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
267       g=pythag(f,1.0);
268       C(f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x);
269       c=s=1.0;                  //Next QR transformation:
270       for (j=l;j<=nm;j++) {
271         i=j+1;
272         g=rv1[i];
273         y=w[i];
274         h=s*g;
275         g=c*g;
276         z=pythag(f,h);
277         rv1[j]=z;
278         c=f/z;
279         s=h/z;
280         f=x*c+g*s;
281         g = g*c-x*s;
282         h=y*s;
283         C(y *= c);
284         
285         for (jj=1;jj<=n;jj++) {
286           x=v[jj][j];
287           z=v[jj][i];
288           v[jj][j]=x*c+z*s;
289           C(v[jj][i]=z*c-x*s);
290         }
291         
292         z=pythag(f,h);
293         w[j]=z;                         //Rotation can be arbitrary if z = 0.
294         
295         if (z) {
296           z=1.0/z;
297           c=f*z;
298           s=h*z;
299         }
300         
301         f=c*g+s*y;
302         C(x=c*y-s*g);
303         for (jj=1;jj<=m;jj++) {
304           y=a[jj][j];
305           z=a[jj][i];
306           a[jj][j]=y*c+z*s;
307           C(a[jj][i]=z*c-y*s);
308         }
309       }
310       
311       rv1[l]=0.0;
312       rv1[k]=f;
313       w[k]=x;
314     }
315   }
316   
317  done:
318 #ifdef SIG_MATH
319   signal(SIGFPE, last_sig);
320 #endif
321 }
322 
323 /*
324  * Solves A.X = B for a Vector X, where A is specied by the arrays u[1..m][1..n], 
325  * w[1..n],
 v[1..n][1..n] as returned by svdcmp. m and n are the dimensions of a, 
326  * and will be equal for
 square matrices. b[1..m] is the input right-hand side. 
327  * x[1..n] is the output solution Vector.
328  * No input quantities are destroyed, so the routine may be called sequentially 
329  * with different b's.
330  *
331  * tmp is a 1-n tmp vector
332  */
333 void svbksb(float **u, float w[], float **v, int m, int n, float b[], float x[],
334             float *tmp)
335 {
336   int jj, j, i;
337   float s;
338         
339   for (j=1; j<=n; j++) {                // Calculate U T B.
340     s=0.0;
341     if (w[j]) {                                 // Nonzero result only if wj is nonzero.
342       for (i=1;i<=m;i++) 
343         s += u[i][j]*b[i];
344       s /= w[j];                        // This is the divide by wj .
345     }
346     
347     tmp[j]=s;
348   }
349 
350   for (j=1;j<=n;j++) {          // Matrix multiply by V to get answer.
351     s=0.0;      
352     for (jj=1;jj<=n;jj++) s += v[j][jj]*tmp[jj];
353     x[j]=s;
354   }
355 
356 }
357 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.