/* (C) Copr. 1986-92 Numerical Recipes Software ##'. */ #include #include #include #include "filter.h" #include "dates.h" static double swap; #define SWAP(a,b) {swap=(a);(a)=(b);(b)=swap;} static void covsrt( double **covar, int ma); static float sqrarg; #define SQR(a) ((sqrarg=(a)) == 0.0 ? 0.0 : sqrarg*sqrarg) void nrerror(char error_text[]); void gaussj(double **a,int n,double **b,int m); /***************************************************************/ /* * Apply a linear fit to data contained in x and y arrays. * Return the intercept, slope, sigmas of both, and chi-squared. */ /***************************************************************/ void fit( double x[], double y[], int ndata, float *a, float *b, float *siga, float *sigb, float *chi2 ) { int i; float t,sxoss,sx=0.0,sy=0.0,st2=0.0,ss,sigdat; *siga = 0.0; *sigb = 0.0; *a = 0.0; *b = 0.0; if (ndata <= 1) { return; } if (ndata == 2) { *b = (y[1]-y[0])/(x[1]-x[0]); *a = y[0] - (x[0] * (*b)); return; } for (i=0;i i) { SWAP(data[j],data[i]); SWAP(data[j+1],data[i+1]); } m=n >> 1; while (m >= 2 && j > m) { j -= m; m >>= 1; } j += m; } mmax=2; while (n > mmax) { istep=mmax << 1; theta=isign*(6.28318530717959/mmax); wtemp=sin(0.5*theta); wpr = -2.0*wtemp*wtemp; wpi=sin(theta); wr=1.0; wi=0.0; for (m=1;m= big) { big = fabs(a[j][k]); irow = j; icol = k; } } else if (ipiv[k] > 1) { nrerror ("gaussj: Singular Matrix-1"); } } } } ++(ipiv[icol]); if (irow != icol) { for (l=0; l=0; l--) { if (indxr[l] != indxc[l]) { for (k=0; k x[n-1]) return (0); splint (x, y, s2, n, xp, &s1, &sd); return (s1); } /**********************************************************************/ /* General linear least squares fit to a function. * * Modified from the numerical recipes routine, to * use double precision instead of float, and to * explicitly use 0 offset arrays. Also uses all * parameters in the fit, rather than a selected number * like in the numerical recipes version. */ /**********************************************************************/ void lfit( double x[], /* Input - the x axis values */ double y[], /* Input - the y axis values */ double sig[], /* Input - the uncertainty for each x,y pair */ int ndat, /* Input - the number of points in x,y,sig */ float a[], /* Output - the coefficients of the fit */ double **covar, /* Output - the covariances of the coefficients */ int ma, /* Input - Number of coefficients to fit */ float *chisq, /* Output - the chi square value of the fit */ void (*funcs)() /* Input - The function that returns the partial derivative of the function at a given time x */ ) { int i,j,k,l,m; double ym,wt,sum, sig2i; double **beta, *afunc; beta = dmatrix (0,ma,0, 0); afunc = (double *) calloc (ma, sizeof(double)); /* Initialize arrays to 0 */ for (j=0; j=0;j--) { for (i=0; i>1); if (isign == 1) { c2 = -0.5; four1(data,n>>1,1); } else { c2=0.5; theta = -theta; } wtemp=sin(0.5*theta); wpr = -2.0*wtemp*wtemp; wpi=sin(theta); wr=1.0+wpr; wi=wpi; np3=n+3; for (i=2;i<=(n>>2);i++) { i4=1+(i3=np3-(i2=1+(i1=i+i-1))); h1r=c1*(data[i1]+data[i3]); h1i=c1*(data[i2]-data[i4]); h2r = -c2*(data[i2]+data[i4]); h2i=c2*(data[i1]-data[i3]); data[i1]=h1r+wr*h2r-wi*h2i; data[i2]=h1i+wr*h2i+wi*h2r; data[i3]=h1r-wr*h2r+wi*h2i; data[i4] = -h1i+wr*h2i+wi*h2r; wr=(wtemp=wr)*wpr-wi*wpi+wr; wi=wi*wpr+wtemp*wpi+wi; } if (isign == 1) { data[1] = (h1r=data[1])+data[2]; data[2] = h1r-data[2]; } else { data[1]=c1*((h1r=data[1])+data[2]); data[2]=c1*(h1r-data[2]); four1(data,n>>1,-1); for (i=1; i<=n; i++) data[i] = data[i]*2.0/(float) n; } } /*************************************************************************/ /* Given arrays x[0..n-1] and y[0..n-1] containing a function, * return the array y2[0..n-1] that contains the second derivatives of * the interpolating function at the tabulated points x. * This routine sets the boundary condition for a natural spline * with 0 second derivative on the boundaries. */ void spline( double x[], double y[], int n, double y2[] ) { int i,k; double p,qn,sig,un,*u; u=(double *) calloc (n, sizeof(double)); y2[0]=u[0]=0.0; for (i=1;i<=n-2;i++) { sig=(x[i]-x[i-1])/(x[i+1]-x[i-1]); p=sig*y2[i-1]+2.0; y2[i]=(sig-1.0)/p; u[i]=(y[i+1]-y[i])/(x[i+1]-x[i]) - (y[i]-y[i-1])/(x[i]-x[i-1]); u[i]=(6.0*u[i]/(x[i+1]-x[i-1])-sig*u[i-1])/p; } qn=un=0.0; y2[n-1]=(un-qn*u[n-2])/(qn*y2[n-2]+1.0); for (k=n-2;k>=0;k--) y2[k]=y2[k]*y2[k+1]+u[k]; free (u); } /*******************************************************/ void splint ( double xa[], double ya[], double y2a[], int n, double x, double *y, double *yd ) { int klo, khi, k; double h, b, a, g; /* * Find correct position by bisection * khi and klo should bracket the value of x */ klo = 0; khi = n-1; while (khi - klo > 1) { k = (khi+klo) >> 1; if (xa[k] > x) khi = k; else klo=k; } h = xa[khi] - xa[klo]; g = ya[khi] - ya[klo]; if (h == 0.0) { fprintf (stderr, "Bad xa input to routine splint\n"); exit(1); } a = (xa[khi] - x) / h; b = (x - xa[klo]) / h; /* calculate the function */ *y = a*ya[klo] + b*ya[khi] + ((a*a*a-a)*y2a[klo] + (b*b*b-b)*y2a[khi]) * (h*h) / 6.0; /* calculate the derivative */ *yd = g/h - (((3.0*a*a - 1.0) * y2a[klo] + (3*b*b - 1) * y2a[khi]) * h) / 6.0; return; } #define NR_END 1 #define FREE_ARG char* /***********************************************************************/ /* Numerical Recipes standard error handler */ /***********************************************************************/ void nrerror(error_text) char error_text[]; { void exit(); fprintf(stderr,"Numerical Recipes run-time error...\n"); fprintf(stderr,"%s\n",error_text); fprintf(stderr,"...now exiting to system...\n"); exit(1); } /***********************************************************************/ /* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch] */ /***********************************************************************/ double **dmatrix(nrl,nrh,ncl,nch) long nch,ncl,nrh,nrl; { long i, nrow=nrh-nrl+1,ncol=nch-ncl+1; double **m; /* allocate pointers to rows */ m=(double **) malloc((unsigned int)((nrow+NR_END)*sizeof(double*))); if (!m) nrerror("allocation failure 1 in matrix()"); m += NR_END; m -= nrl; /* allocate rows and set pointers to them */ m[nrl]=(double *) malloc((unsigned int)((nrow*ncol+NR_END)*sizeof(double))); if (!m[nrl]) nrerror("allocation failure 2 in matrix()"); m[nrl] += NR_END; m[nrl] -= ncl; for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol; /* return pointer to array of pointers to rows */ return m; } /***********************************************************************/ /* free a double matrix allocated by dmatrix() */ /***********************************************************************/ void free_dmatrix(m,nrl,nrh,ncl,nch) double **m; long nch,ncl,nrh,nrl; { free((FREE_ARG) (m[nrl]+ncl-NR_END)); free((FREE_ARG) (m+nrl-NR_END)); }