home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 8
/
CDASC08.ISO
/
NEWS
/
2299
/
GNUFIT
/
LINEAR2.C
< prev
next >
Wrap
Text File
|
1993-10-07
|
7KB
|
211 lines
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "fit.h"
/* declarations for data declared externally */
extern int grflag;
extern int wiflag;
extern int veflag;
extern int debug;
int window(double *x, int num_indep);
/* linear_fit() does a linear least squares fit to a specified function. */
/* because the functions are defined for non-linear fitting, we have */
/* to jump through some hoops to do the calculation. */
int linear_fit(double **data,struct data_order order,
int num_indep, int ndata, int itmax, double *a,
int ma, int *lista, int mfit, double **covar,
double *chisq, int (*func)(),
char *filename, char *comment){
int i, j, k, l, m; /* indices for loops */
int failed=0;
double **alpha; /* See Chapter 14 of Numerical Recipes */
double *beta;
double *X;
double *x;
double *dyda; /* Not really needed, but function might return */
/* values for dyda[i], so we have to allocate space */
double *aj; /* The function needs to return the value of each basis */
/* function at a given x, X[j](x[i]). However, function */
/* is set up to return value of f(x,a). */
/* To get X[j](x[i]), we send a parameter list where */
/* a[i] = 0 if a != j, and a[i] = 1 if a ==j. */
/* I call this parameter list aj to distinguish it from a. */
int *fita; /* fita tells the user function func() which dyda[i]'s to */
/* compute. We don't need any of them for linear fitting */
/* so we set all the fita[i]'s to zero */
int *dydx_flag; /* dydx_flag tells the user function which dydx[i]'s to compute. */
/* We can't use them for linear fitting, because we are not */
/* iterating and don't have a guess for the parameters until */
/* the fit is finished. As a result, our linear fitting does */
/* not consider errors in the independent variables. We set */
/* all of the dydx_flag[i]'s to zero, so the function does not */
/* have to waste time computing them. */
double *dydx; /* However, since user functions might compute the dydx[i]'s */
/* anyway, we need to allocate storage. */
double sig2i; /* sigmayi * sigmay1 */
double *atry; /* These are the parameter values multiplying the basis functions */
/* used in the fit. If a basis function is not used in the fit, */
/* it is multiplied by zero. atry has dimension mfit and holds */
/* only the parameters multiplying basis functions which are fit */
double chisqr;
alpha=dmatrix(mfit,mfit);
X = dvector(ma); /* value of basis function at each data point */
beta = dvector(mfit);
dyda=dvector(ma);
fita = ivector(ma);
x = dvector(num_indep);
dydx = dvector(num_indep);
dydx_flag = ivector(num_indep);
aj = dvector(ma);
atry = dvector(mfit);
for(j = 0; j < num_indep; j++) dydx_flag[j] = 0; /* don't calculate dydx[i]'s */
for(j = 0; j < ma; j++) fita[j] = 0; /* don't calculate dyda[i]'s */
/* set all alpha[i][j]'s equal to zero */
for(i = 0; i < mfit; i++){
for(j = 0; j < mfit; j++){
alpha[i][j] = 0;
}
beta[i] = 0;
}
/* loop summing over data points */
for(i = 0; i < ndata; i++){
/* set up array of independent variable values at i'th data point */
for(j = 0; j < num_indep; j++){
x[j] = data[order.x[j]][i];
if(debug > 1)
printf("i: %d order.x[%d]: %d x[%d]: %g\n", i, j, order.x[j], j, x[j]);
}
/* If windowing is on, only consider data points within window */
if(wiflag == 0 || window(x, num_indep)){
/* calculate value of relevant basis functions at current data point */
for(j = 0; j < mfit; j++){
/* set up aj[i]'s so function value = basis function value */
for(l=0; l < ma; l++){
if(l != lista[j]) aj[l] = 0;
else aj[l] = 1;
}
failed = (*func)(x,aj,&X[lista[j]],dyda,ma,0, fita, dydx_flag, dydx, data[order.y][i]);
if(debug > 1) printf("X[%d]: %g ",lista[j], X[lista[j]]);
if(failed) break;
}
if(debug > 1) printf("\n");
if(failed) break;
sig2i = data[order.sig][i]*data[order.sig][i];
if(debug > 1) printf("order.sig: %d data[order.sig][i]: %g sig2i: %g\n",
order.sig, data[order.sig][i], sig2i);
/* add this data point to alpha and beta */
for(k = 0; k < mfit; k++){
for(j = 0; j <= k; j++){
/* if(debug > 1) printf("alpha[%d][%d] += X[%d]*X[%d]/sig2i;\n",
j, k, lista[j], lista[k]); */
alpha[j][k] += X[lista[j]]*X[lista[k]]/sig2i;
}
beta[k] += data[order.y][i]*X[lista[k]]/sig2i;
}
}
}
if(debug) printf("done looping over data points\n");
if(!failed){
if(debug){
printf("\nalpha: ");
for(j=0;j<mfit;j++){
printf("\n %d ",j);
for(k=0;k<mfit;k++) printf(" %g ",alpha[j][k]);
}
}
/* fill in rest of alpha, alpha is symmetric, and we only */
/*calculated upper triangular, we need the whole thing */
for(k = mfit-1; k >= 0; k--){
for(j = mfit-1; j > k; j--){
alpha[j][k] = alpha[k][j];
}
}
if(veflag==2){
printf("\nalpha: ");
for(j=0;j<mfit;j++){
printf("\n %d ",j);
for(k=0;k<mfit;k++) printf(" %g ",alpha[j][k]);
}
printf("\n");
}
/* solve the matrix equation alpha*atry = beta, where alpha is */
/* a matrix, and atry and beta are vectors */
/* covar is the inverse of alpha */
if(debug) printf("calling solve_for_da()\n");
solve_for_da(alpha, covar, beta, atry, mfit);
if(debug) printf("returned from solve_for_da()\n");
if(veflag==2){
printf("\ncovar: ");
for(j=0;j<mfit;j++){
printf("\n %d ",j);
for(k=0;k<mfit;k++) printf("\n covar[%d][%d]= %g ",j, k, covar[j][k]);
}
printf("\n");
}
if(debug){
for(j=0; j < mfit; j++)printf("\n atry%d = %g", j, atry[j]);
printf("\n");
}
for(j = 0; j < ma; j++) a[j] = 0;
for(j = 0; j < mfit; j++) a[lista[j]] = atry[j];
if(grflag){
if(debug)printf("in linear_fit(), calling plot()\n");
failed=plot(func,data, order, num_indep, ndata, filename, comment, a, ma);
if(debug)printf("in linear_fit(), plot() returned %d\n", failed);
}
/* call calc_yfit to compute chisqr */
failed = calc_yfit(func, data, order, num_indep, a, ndata, ma, &chisqr);
for(j=0; j < ma; j++)printf("\n a%d = %g", j, a[j]);
*chisq = chisqr;
printf("\n chisqr = %g", *chisq);
printf("\n");
}
free_dmatrix(alpha,mfit,mfit);
free(X);
free(beta);
free(dyda);
free(fita);
free(x);
free(dydx);
free(dydx_flag);
free(aj);
free(atry);
return failed;
}