DAS  3.1.6 - 18/09/2017
SVD.C
Go to the documentation of this file.
1 #include <windows.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <malloc.h>
6 #include <math.h>
7 #include <io.h>
8 #include "mgui.h"
9 #include "DAS_Spatram.h"
10 #include "dcl.h"
11 #include "dil.h"
12 #include "bil.h"
13 #include "DOAS.h"
14 #include "nrutil.h"
15 #include "Marq.h"
16 
17 
18 
19 #define SWAP(a,b) {swap=(a);(a)=(b);(b)=swap;}
20 
21 #define TOL 1.0e-5 //Default value for single precision and variables scaled to order unity.
22 
23 void covsrt(float **covar, int ma, int ia[], int mfit)
24 //Expand in storage the covariance matrix covar so as to take into account parameters that are
25 //being held .xed.(For the latter,return zero covariances.)
26 {
27  int i,j,k;
28  float swap;
29  for (i=mfit+1;i<=ma;i++)
30  for (j=1;j<=i;j++) covar[i][j]=covar[j][i]=0.0;
31  k=mfit;
32  for (j=ma;j>=1;j--)
33  {
34  if (ia[j])
35  {
36  for (i=1;i<=ma;i++) SWAP(covar[i][k],covar[i][j])
37  for (i=1;i<=ma;i++) SWAP(covar[k][i],covar[j][i])
38  k--;
39  }
40  }
41 }
42 
43 
44 
45 
46 
47 void svdfit(float x[], float y[], float sig[], int ndata, float a[], int ma,
48 float **u, float **v, float w[], float *chisq,
49 void (*funcs)(float, float [], int))
50 /*
51 Given a set of data points x[1..ndata] y[1..ndata] with individual standard deviations
52 sig[1..ndata],use 2 minimization to determine the coe .cients a[1..ma] of the .t-
53 ting function y = i ai ~ afunci(x )Here we solve the .tting equations using singular
54 value decomposition of the ndata by ma matrix as in 2.6.Arrays u[1..ndata][1..ma]
55 v[1..ma][1..ma],and w[1..ma] provide workspace on input;on output they de .ne the
56 singular value decomposition and can be used to obtain the covariance matrix.The pro-
57 gram returns values for the ma .t parameters and 2 chisq The user supplies a routine
58 funcs(x,afunc,ma) that returns the ma basis functions evaluated at x = x in the array
59 afunc[1..ma].
60 */
61 {
62  void svbksb(long double **u, long double w[], long double **v, int m, int n, long double b[],
63  double x[]);
64  void svdcmp(long double **a, int m, int n, long double w[], long double **v);
65  int j,i;
66  long double wmax,tmp,thresh,sum,*b,*afunc;
67 
68  b=dvector(1,ndata);
69  afunc=dvector(1,ma);
70  for (i=1;i<=ndata;i++)
71  { //Accumulate coefficients of the fitting matrix.
72  (*funcs)(x[i],(float *)afunc,ma);
73  tmp=1.0/sig[i];
74  for (j=1;j<=ma;j++) u[i][j]=afunc[j]*tmp;
75  b[i]=y[i]*tmp;
76  }
77  svdcmp(u,ndata,ma,w,v); //Singular value decomposition.
78  wmax=0.0; //Edit the singular values,given TOL from the
79  //#define statement,between here ...
80  for (j=1;j<=ma;j++)
81  if (w[j] > wmax) wmax=w[j];
82  thresh=TOL*wmax;
83  for (j=1;j<=ma;j++)
84  if (w[j] < thresh) w[j]=0.0; //...and here.
85  svbksb(u,w,v,ndata,ma,b,a);
86  *chisq=0.0; //Evaluate chi-square.
87  for (i=1;i<=ndata;i++)
88  {
89  (*funcs)(x[i],afunc,ma);
90  for (sum=0.0,j=1;j<=ma;j++) sum += a[j]*afunc[j];
91  *chisq += (float)(tmp=(y[i]-sum)/sig[i],tmp*tmp);
92  }
93  free_vector(afunc,1,ma);
94  free_vector(b,1,ndata);
95 }
96 
97 
98 
99 void svbksb(long double **u, long double w[], long double **v,
100  int m, int n, long double b[], long double x[])
101 /*
102 Solves A X = B for a vector X where A is specified by the arrays u[1..m][1..n],w[1..n],
103 v[1..n][1..n] as returned by svdcmp m and n are the dimensions of a and will be equal for
104 square matrices.b[1..m] is the input right-hand side.x[1..n] is the output solution vector.
105 No input quantities are destroyed,so the routine may be called sequentially with different bs.
106 */
107 {
108  int jj,j,i;
109  long double s,*tmp;
110  tmp=dvector(1,n);
111  for (j=1;j<=n;j++)
112  { //Calculate U T B
113  s=0.0;
114  if (w[j])
115  { //Nonzero result only if wj is nonzero.
116  for (i=1;i<=m;i++) s += u[i][j]*b[i];
117  s /= w[j]; //This is the divide by wj .
118  }
119  tmp[j]=s;
120  }
121  for (j=1;j<=n;j++)
122  { //Matrix multiply by V to get answer.
123  s=0.0;
124  for (jj=1;jj<=n;jj++) s += v[j][jj]*tmp[jj];
125  x[j]=s;
126  }
127  free_dvector(tmp,1,n);
128 }
129 
130 
131 
132 void svdcmp(long double **a, int m, int n, long double w[], long double **v)
133 /*
134 Given a matrix a[1..m][1..n],this routine computes its singular value decomposition,
135 A =U W V(Transposed).
136 The matrix U replaces a on output.The diagonal matrix of singular values W
137  is output as a vector w[1..n].The matrix V (not the transpose V T )is output as v[1..n][1..n].
138 */
139 {
140  FILE *fpp;
141  long double pythag(long double a, long double b);
142  int flag,i,its,j,jj,k,l,nm;
143  long double anorm,c,f,g,h,s,scale,x,y,z,*rv1;
144  rv1=dvector(1,n);
145  g=scale=anorm=0.0; //Householder reduction to bidiagonal form.
146  for (i=1;i<=n;i++)
147  {
148  l=i+1;
149  rv1[i]=scale*g;
150  g=s=scale=0.0;
151  if (i <= m)
152  {
153  for (k=i;k<=m;k++)
154  scale += fabs(a[k][i]);
155  if (scale)
156  {
157  for (k=i;k<=m;k++)
158  {
159  a[k][i] /= scale;
160  s += a[k][i]*a[k][i];
161  }
162  f=a[i][i];
163  g = -SIGN(sqrt(s),f);
164  h=f*g-s;
165  a[i][i]=f-g;
166  for (j=l;j<=n;j++)
167  {
168  for (s=0.0,k=i;k<=m;k++) s += a[k][i]*a[k][j];
169  f=s/h;
170  for (k=i;k<=m;k++) a[k][j] += f*a[k][i];
171  }
172  for (k=i;k<=m;k++) a[k][i] *= scale;
173  }
174  }
175  w[i]=scale *g;
176  g=s=scale=0.0;
177  if (i <= m && i != n)
178  {
179  for (k=l;k<=n;k++) scale += fabs(a[i][k]);
180  if (scale)
181  {
182  for (k=l;k<=n;k++)
183  {
184  a[i][k] /= scale;
185  s += a[i][k]*a[i][k];
186  }
187  f=a[i][l];
188  g = -SIGN(sqrt(s),f);
189  h=f*g-s;
190  a[i][l]=f-g;
191  for (k=l;k<=n;k++) rv1[k]=a[i][k]/h;
192  for (j=l;j<=m;j++)
193  {
194  for (s=0.0,k=l;k<=n;k++) s += a[j][k]*a[i][k];
195  for (k=l;k<=n;k++) a[j][k] += s*rv1[k];
196  }
197  for (k=l;k<=n;k++) a[i][k] *= scale;
198  }
199  }
200  anorm=DMAX(anorm,(fabs(w[i])+fabs(rv1[i])));
201  }
202  for (i=n;i>=1;i--)
203  { //Accumulation of right-hand transformations.
204  if (i < n)
205  {
206  if (g)
207  {
208  for (j=l;j<=n;j++) //Double division to avoid possible under .o .
209  v[j][i]=(a[i][j]/a[i][l])/g;
210  for (j=l;j<=n;j++)
211  {
212  for (s=0.0,k=l;k<=n;k++) s += a[i][k]*v[k][j];
213  for (k=l;k<=n;k++) v[k][j] += s*v[k][i];
214  }
215  }
216  for (j=l;j<=n;j++) v[i][j]=v[j][i]=0.0;
217  }
218  v[i][i]=1.0;
219  g=rv1[i];
220  l=i;
221  }
222  for (i=IMIN(m,n);i>=1;i--)
223  { //Accumulation of left-hand transformations.
224  l=i+1;
225  g=w[i];
226  for (j=l;j<=n;j++) a[i][j]=0.0;
227  if (g)
228  {
229  g=1.0/g;
230  for (j=l;j<=n;j++)
231  {
232  for (s=0.0,k=l;k<=m;k++) s += a[k][i]*a[k][j];
233  f=(s/a[i][i])*g;
234  for (k=i;k<=m;k++) a[k][j] += f*a[k][i];
235  }
236  for (j=i;j<=m;j++) a[j][i] *= g;
237  }
238  else
239  for (j=i;j<=m;j++) a[j][i]=0.0;
240  ++a[i][i];
241  }
242 
243  for (k=n;k>=1;k--)
244  { //Diagonalization of the bidiagonal form:Loop over singular values,and over allo ed iterations.
245  for (its=1;its<=30;its++)
246  {
247  flag=1;
248  for (l=k;l>=1;l--)
249  { //Test for splitting.
250  nm=l-1; //Note that rv1[1] is always zero.
251  if ((float)(fabs(rv1[l])+anorm) == anorm)
252  {
253  flag=0;
254  break;
255  }
256  if ((float)(fabs(w[nm])+anorm) == anorm) break;
257  }
258  if (flag)
259  {
260  c=0.0; //Cancellation of rv1[l],if l > 1
261  s=1.0;
262  for (i=l;i<=k;i++)
263  {
264  f=s*rv1[i];
265  rv1[i]=c*rv1[i];
266  if ((float)(fabs(f)+anorm) == anorm) break;
267  g=w[i];
268  h=pythag(f,g);
269  w[i]=h;
270  h=1.0/h;
271  c=g*h;
272  s = -f*h;
273  for (j=1;j<=m;j++)
274  {
275  y=a[j][nm];
276  z=a[j][i];
277  a[j][nm]=y*c+z*s;
278  a[j][i]=z*c-y*s;
279  }
280  }
281  }
282  z=w[k];
283  if (l == k)
284  { //Convergence.
285  if (z < 0.0)
286  { //Singular value is made nonnegative.
287  w[k] = -z;
288  for (j=1;j<=n;j++) v[j][k] = -v[j][k];
289  }
290  break;
291  }
292  if (its == 30) nrerror("no convergence in 30 svdcmp iterations");
293  x=w[l]; //Shift from bottom 2-by-2 minor.
294  nm=k-1;
295  y=w[nm];
296  g=rv1[nm];
297  h=rv1[k];
298  f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
299  g=pythag(f,1.0);
300  f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x;
301  c=s=1.0; //Next QR transformation:
302  for (j=l;j<=nm;j++)
303  {
304  i=j+1;
305  g=rv1[i];
306  y=w[i];
307  h=s*g;
308  g=c*g;
309  z=pythag(f,h);
310  rv1[j]=z;
311  c=f/z;
312  s=h/z;
313  f=x*c+g*s;
314  g = g*c-x*s;
315  h=y*s;
316  y *=c;
317  for (jj=1;jj<=n;jj++)
318  {
319  x=v[jj][j];
320  z=v[jj][i];
321  v[jj][j]=x*c+z*s;
322  v[jj][i]=z*c-x*s;
323  }
324  z=pythag(f,h);
325  w[j]=z; //Rotation can be arbitrary if z =0
326  if (z)
327  {
328  z=1.0/z;
329  c=f*z;
330  s=h*z;
331  }
332  f=c*g+s*y;
333  x=c*y-s*g;
334  for (jj=1;jj<=m;jj++)
335  {
336  y=a[jj][j];
337  z=a[jj][i];
338  a[jj][j]=y*c+z*s;
339  a[jj][i]=z*c-y*s;
340  }
341  }
342  rv1[l]=0.0;
343  rv1[k]=f;
344  w[k]=x;
345  }
346  }
347 
348  fpp = fopen("matUInSVD.dat", "w");
349  for(k=1;k<=m;k++)
350  {
351  for(l=1;l<=m;l++)
352  {
353  fprintf(fpp,"%7.6e ",a[k][l]) ;
354  }
355  fprintf(fpp,"\n");
356  }
357 
358  fclose(fpp);
359 
360 
361  free_vector(rv1,1,n);
362 }
363 
364 
365 
366 long double pythag(long double a, long double b)
367 //Computes (a 2 + b 2 ) 1/2 without destructive underflow or overflow.
368 {
369  long double absa,absb;
370  absa=fabs(a);
371  absb=fabs(b);
372  if (absa > absb) return absa*sqrt(1.0+DSQR(absb/absa));
373  else return (absb == 0.0 ? 0.0 : absb*sqrt(1.0+DSQR(absa/absb)));
374 }
#define SIGN(a, b)
Definition: NRUTIL.H:42
void svdfit(float x[], float y[], float sig[], int ndata, float a[], int ma, float **u, float **v, float w[], float *chisq, void(*funcs)(float, float [], int))
Definition: SVD.C:47
#define DSQR(a)
Definition: NRUTIL.H:8
long double pythag(long double a, long double b)
Definition: SVD.C:366
void free_dvector()
void svbksb(long double **u, long double w[], long double **v, int m, int n, long double b[], long double x[])
Definition: SVD.C:99
#define TOL
Definition: SVD.C:21
#define SWAP(a, b)
Definition: SVD.C:19
double * dvector()
void svdcmp(long double **a, int m, int n, long double w[], long double **v)
Definition: SVD.C:132
Function prototypes.
void covsrt(float **covar, int ma, int ia[], int mfit)
Definition: SVD.C:23
#define DMAX(a, b)
Definition: NRUTIL.H:11
Function prototypes.
#define IMIN(a, b)
Definition: NRUTIL.H:39
void free_vector()
struct flag flag
Control Flags.
void nrerror()
______________________________________________________________________________________
Generated on Mon Sep 18 2017 11:44:10 for DAS - Rel. 3.1.6 - 18/09/2017.