/* Statistical methods library */ /* linear fits, qudratic fits, basic statistics */ /* in a program with x[N], y[N], a,b,sa,sb call with */ /* linear_fit(&a, &b, &sa, &sb, x,y,N); */ /* chebyshev fit and definite integration */ /* solution to linear equations, determinants */ /* chebyshev derivatives */ /* J. R. Schmidt, 2001/2002/2003 */ /*declarations */ #define MAX 100 #include /* prototypes */ void standard (double *mean, double *sd, double *x, int N); void linear_fit (double *a, double *b, double *sa, double *sb, double *x, double *y, int N); double quad_fit (double *x0, double *v0, double *a, double *x, double *y, int N); double sigma (double x0, double v0, double a, double *x, double *y, int N); double determinant (double (*A)[MAX], int N); void sums (double *sx, double *sy, double *sx2, double *sxy, double *x, double *y, int N); /* compute derivative from chbyshev fit */ void derivative (double *xp, double *yp, double *derptr, int M, int NN); /* chebyshev polynomials */ double T (double x, int n); /* fit to chebyshev function expansion */ /* NN is order of fit, M is length of data arrays */ /* \int_{xmin}^{xmax} f(x) dx from \{(x_0, y_0),...,(x_{M-1},y_{M-1})\} */ void chebyshev_int (double *integ, double *x_min, double *x_max, double *xp, double *yp, int M, int NN); /* solve a\cdot x=b */ void solve (double (*A)[MAX], double *B, double *X, int N); /* chi-squared statistic and probability */ double chi_2_prob(double val, int N); double chisquared(double *exper, double *theor, int N); /* error function for normal distributions */ double erf(double z); double poisson(double mean, int M); double normal_dist(double xmin, double xmax, double mean, double sig); /* The routines */ void linear_fit (double *a, double *b, double *sa, double *sb, double *x, double *y, int N) { double Sx, Sy, Sx2, Sxy, sig, A, B, SA, SB, Den, term; int i, j; Sx = 0.0; Sy = 0.0; Sx2 = 0.0; Sxy = 0.0; sig = 0.0; for (i = 0; i < N; i++) { Sx = Sx + *(x + i); Sy = Sy + *(y + i); Sx2 = Sx2 + (*(x + i)) * (*(x + i)); Sxy = Sxy + (*(x + i)) * (*(y + i)); } Den = (double) N *Sx2 - Sx * Sx; if (Den != 0.0) { A = ((double) N * Sxy - Sx * Sy) / Den; B = -(Sx * Sxy - Sx2 * Sy) / Den; } else { A = 1.0E10; B = 1.0E10; } for (i = 0; i < N; i++) { term = *(y + i) - (A * (*(x + i)) + B); term = term * term; sig = sig + term; } sig = sig / (double) (N - 1); if (Den != 0.0) { SB = sig * Sx2 / Den; SA = sig * (double) N / Den; } else { SA = 1.0E10; SB = 1.0E10; } *a = A; *b = B; *sa = sqrt (SA); *sb = sqrt (SB); } double chisquared(double *exper, double *theor, int N){ int i; double sum, term; sum=0.0; for(i=0;i xmax) xmax = X[k]; } scale = 2.0 / (xmax - xmin); offset = -(xmax + xmin) / (xmax - xmin); for (k = 0; k < M; k++) { X[k] = scale * X[k] + offset; /* now -1 <= X[k] <= 1 */ } for (i = 0; i <= NN; i++) { for (j = 0; j <= NN; j++) { a[i][j] = 0.0; } } /* set up a and b for polynomial fit of order N */ for (j = 0; j <= NN; j++) { b[j] = 0.0; /* x[j] = 0.0; */ for (k = 0; k < M; k++) { b[j] = b[j] + Y[k] * T (X[k], j); } } for (i = 0; i <= NN; i++) { for (j = 0; j <= NN; j++) { for (k = 0; k < M; k++) a[i][j] = a[i][j] + T (X[k], j) * T (X[k], i); } } b_ptr = &b[0]; /* initialize the first addresses */ c_ptr = &c[0]; a_ptr = &a[0]; solve (a_ptr, b_ptr, c_ptr, NN); /* solve the equations */ integral = 2.0 * (*(c_ptr + 0)); for (k = 1; k <= NN; k++) { if (2 * (k / 2) == k) { integral = integral - 2.0 * (*(c_ptr + k)) / ((double) k * (double) k - 1.0); } } integral = integral / scale; /* fill pointers for output */ *x_min = xmin; *x_max = xmax; *integ = integral; } double determinant (double (*A)[MAX], int N) { /* the routine for solving the simultaneous equations */ double temp, factor, product; int m, n, u, p; int i, j, k, l; for (k = 0; k <= N; k++) { m = k; u = 0; do { u + 1; } while (*(*(A + k) + u + k) == 0.0); m = k + u; for (l = m + 1; l <= N; l++) { if (*(*(A + k) + m) != 0.0) { factor = *(*(A + k) + l) / *(*(A + k) + m); /* perform row operation on [a] */ for (j = 0; j <= N; j++) { *(*(A + j) + l) = *(*(A + j) + l) - factor * (*(*(A + j) + m)); } } } for (j = 0; j <= N; j++) { temp = *(*(A + j) + k); *(*(A + j) + k) = *(*(A + j) + m); *(*(A + j) + m) = temp; } } /* compute the determinant */ product = 1.0; for (i = 0; i <= N; i++) product = product * (*(*(A + i) + i)); return (product); } void solve (double (*A)[MAX], double *B, double *X, int N) { /* the routine for solving the simultaneous equations */ double temp, factor, sum; int m, n, p, i, j, k, l, u; for (k = 0; k <= N; k++) { m = k; u = 0; do { u + 1; } while (*(*(A + k) + u + k) == 0.0); m = k + u; for (l = m + 1; l <= N; l++) { if (*(*(A + k) + m) != 0.0) { factor = *(*(A + k) + l) / *(*(A + k) + m); /* perform row operation on [a] */ for (j = 0; j <= N; j++) { *(*(A + j) + l) = *(*(A + j) + l) - factor * (*(*(A + j) + m)); } /* perform row operation on [b] */ *(B + l) = *(B + l) - factor * (*(B + m)); } } for (j = 0; j <= N; j++) { temp = *(*(A + j) + k); *(*(A + j) + k) = *(*(A + j) + m); *(*(A + j) + m) = temp; } /* do the switch for [b] */ temp = *(B + k); *(B + k) = *(B + m); *(B + m) = temp; } /* compute the solutions x[i] */ *(X + N) = *(B + N) / (*(*(A + N) + N)); for (p = 0; p <= N; p++) { sum = 0.0; for (u = N - p + 1; u <= N; u++) sum = sum + (*(*(A + u) + N - p)) * (*(X + u)); *(X + N - p) = (*(B + N - p) - sum) / (*(*(A + N - p) + N - p)); } } void derivative (double *xp, double *yp, double *derptr, int M, int NN) { double left,right,change,xmin,xmax,X[MAX],Y[MAX],offset,scale; double a[MAX][MAX], b[MAX], c[MAX], (*a_ptr)[MAX], *b_ptr,*c_ptr; int i,j,k,l; change=0.001; /* NN is order of polynomial fit */ /* M data points */ /* we will fit a chebyshev sum, and differentiate it */ k = 0; for (k = 0; k < M; k++) { X[k] = *(xp + k); Y[k] = *(yp + k); } xmin = X[0]; xmax = X[0]; for (k = 1; k < M; k++) { if (X[k] < xmin) xmin = X[k]; if (X[k] > xmax) xmax = X[k]; } scale = 2.0 / (xmax - xmin); offset = -(xmax + xmin) / (xmax - xmin); for (k = 0; k < M; k++) { X[k] = scale * X[k] + offset; /* now -1 <= X[k] <= 1 */ } for (i = 0; i <= NN; i++) { for (j = 0; j <= NN; j++) { a[i][j] = 0.0; } } /* set up a and b for Hermite polynomial fit of order N */ for (j = 0; j <= NN; j++) { b[j] = 0.0; c[j] = 0.0; for (k = 0; k < M; k++) { b[j] = b[j] + Y[k] * T (X[k], j); } } for (i = 0; i <= NN; i++) { for (j = 0; j <= NN; j++) { for (k = 0; k < M; k++) a[i][j] = a[i][j] + T (X[k], j) * T (X[k], i); } } b_ptr = &b[0]; /* initialise the first addresses */ c_ptr = &c[0]; a_ptr = &a[0]; solve (a_ptr, b_ptr, c_ptr, NN); /* solve the equations */ /* create the return derivative column */ /* insufficient data to get slope at first, last points */ /* so don,t try */ for(i=1; i= %f)=%.*Ff

\r\n", val, 5, sum); */ retval=mpf_get_d(sum); return(retval); for(m=0;m<21;m++){ mpf_clear(y[m]); mpf_clear(w[m]); mpf_clear(D[m]); mpf_clear(powers[m]); mpf_clear(factors[m]); mpf_clear(two); mpf_clear(sum); mpf_clear(tmp); mpf_clear(term); mpf_clear(chi); } } double erf(double z){ double a[7], power[7], sum; int n; power[0]=1.0; for(n=1;n<7;n++){ power[n]=z*power[n-1]; } a[0]=1.0; a[1]=0.0705230784; a[2]=0.0422820123; a[3]=0.0092705272; a[4]=0.0001520143; a[5]=0.0002765672; a[6]=0.0000430638; sum=0.0; for(n=0;n<7;n++){ sum=sum+power[n]*a[n]; } sum=sum*sum; sum=sum*sum; sum=sum*sum; sum=sum*sum; return(1.0-1.0/sum); } double poisson(double mean, int M){ /* poisson distribution */ int fact[M+1]; double powers[M+1]; int n; fact[0]=1; powers[0]=1; for(n=1;n<=M;n++){ fact[n]=n*fact[n-1]; powers[n]=mean*powers[n-1]; } return(exp(-mean)*(powers[M]/(double)fact[M])); } double normal_dist(double xmin, double xmax, double mean, double sig){ double z, val1, val2; z=(xmax-mean)/sig; if(z >= 0.0) val1=0.5*(1.0+erf(z)); else val1=0.5*(1.0-erf(fabs(z))); z=(xmin-mean)/sig; if(z >= 0.0) val2=0.5*(1.0+erf(z)); else val2=0.5*(1.0-erf(fabs(z))); return(val1-val2); }