// lsfit.c for 1, 2, 3, 4, 5, 6, 7 dimensions // 6, 6, 6, 6, 6, 6, 4 th power // Compute a multiple dimensional polynomial // that is a least square fit of some data. // Evaluate the polynomial at desired points. // use: fit_init(n,m); n is dimension, number of independent variables // m is max power of polynomial // // fit2_bpoly(nx, ny, xg, yg, u) build coefficients // nx number of x coordinates i=0,nx-1 // ny number of y coordinates j=0,ny-1 // xg array of x coordinate values // yg array of y coordinate values // u[i*ny+j] value at point i,j // 3D example // fit_init(3,6); // 3D to 6th power u = poly(x,y,z) // last = false; // for(i=0; i #include #include #include #include "lsfit.h" #undef abs #define abs(x) (((x)<0.0)?(-(x)):(x)) #undef max #define max(x,y) (((x)>(y))?((x)):(y)) #undef min #define min(x,y) (((x)<(y))?((x)):(y)) #include "lsfit.h" static int debug = 0; static int nnn; /* number of coefficients */ static int n, m; /* max power, number of variables */ static double *A; /* matrix of simultaneous equations*/ static double *C; /* polynomial coefficients */ static double *Y; // RHS of equations static int *Apwr; // powers of each variable in a term static int *Bpwr; static int *Cpwr; static int *Dpwr; static int *Epwr; static int *Fpwr; static int *Gpwr; static double *Av; // values of powers static double *Bv; static double *Cv; static double *Dv; static double *Ev; static double *Fv; static double *Gv; static void simeq(int nn, double X[]); /* A and Y global */ static void gen_1d_powers(); static void gen_2d_powers(); static void gen_3d_powers(); static void gen_4d_powers(); static void gen_5d_powers(); static void gen_6d_powers(); static void gen_7d_powers(); static void check_2d(int nx, int ny, double x[], double y[], double u[], double *rms_err, double *avg_err, double *max_err); void fit_init(int an, int am) /* dimension, power, only one fit at a time */ { int i, j, k; n = an; m = am; nnn = 0; /* number of terms to be computed*/ if(n>7) { printf("this lsfit.c can handle only handle to dimension 7 , not %d\n",n); exit(1); } if(m>6 || (n==7 && m>4)) { printf("this lsfit.c can handle only handle 6 power, 4 at 7D , not %d\n", m); exit(1); } if(n==1) { gen_1d_powers(); } else if(n==2) { gen_2d_powers(); } else if(n==3) { gen_3d_powers(); } else if(n==4) { gen_4d_powers(); } else if(n==5) { gen_5d_powers(); } else if(n==6) { gen_6d_powers(); } else if(n==7) { gen_7d_powers(); } else { printf("this lsfit.c can handle only 1,2,3,4,5,6,7 dimensions, not %d\n",n); exit(1); } if(debug) printf("nnn= %d polynomial terms \n", nnn); if(debug) fflush(stdin); A = (double *)malloc(nnn*nnn*sizeof(double)); C = (double *)malloc(nnn*sizeof(double)); Y = (double *)malloc(nnn*sizeof(double)); for(i=0; i1) free(Bpwr); if(n>2) free(Cpwr); if(n>3) free(Dpwr); if(n>4) free(Epwr); if(n>5) free(Fpwr); if(n>6) free(Gpwr); } /* end fit_free */ static void gen_1d_powers() { int i; int pwrsix[9]={0,1,2,3,4,5,6,7,8}; // start of each order int pwrs[8]={0, 1, 2, 3, 4, 5, 6, 7}; nnn = pwrsix[m+1]; Apwr = (int *)malloc(nnn*sizeof(int)); if(debug) printf("terms used to find fit \n"); for(i=0; i<=m; i++) // power requested { Apwr[i]=pwrs[i]; if(debug) printf("%d a^%d \n", i, Apwr[i]); } if(debug) printf(" \n"); } /* end gen_1d_powers */ static void gen_2d_powers() { int i, ii; int pwrsix[8]={0,1,3,6,10,15,21,28}; // start of each order int pwrs[28][2]={{0,0}, {1,0},{0,1}, {2,0},{1,1},{0,2}, {3,0},{2,1},{1,2},{0,3}, {4,0},{3,1},{2,2},{1,3},{0,4}, {5,0},{4,1},{3,2},{2,3},{1,4},{0,5}, {6,0},{5,1},{4,2},{3,3},{2,4},{1,5},{0,6}}; nnn = pwrsix[m+1]; Apwr = (int *)malloc(nnn*sizeof(int)); Bpwr = (int *)malloc(nnn*sizeof(int)); if(debug) printf("terms used to find fit \n"); for(i=0; i<=m; i++) // power requested { for(ii=pwrsix[i]; iiamax) amax=x[i]; if(a1bmax) bmax=y[j]; if(b1umax) umax=u1; if(u1maxe) maxe=diff; sum = sum + diff; sumsq = sumsq + diff*diff; } /* end j */ } /* end i */ printf("check_2d k=%d, amin=%g, amax=%g, bmin=%g, bmax=%g \n", k, amin, amax, bmin, bmax); printf(" umin=%g, umax=%g \n", umin, umax); *max_err = maxe; *avg_err = sum/(double)(nnn); *rms_err = sqrt(sumsq/(double)(nnn)); } /* end check_2d */ static void simeq(int nn, double X[]) /* A and Y global */ { /* PURPOSE : SOLVE THE LINEAR SYSTEM OF EQUATIONS WITH REAL */ /* COEFFICIENTS [A] * |X| = |Y| */ /* */ /* INPUT : THE NUMBER OF EQUATIONS n */ /* THE REAL MATRIX A should be A[i][j] but A[i*n+j] */ /* THE REAL VECTOR Y */ /* OUTPUT : THE REAL VECTOR X */ /* */ /* METHOD : GAUSS-JORDAN ELIMINATION USING MAXIMUM ELEMENT */ /* FOR PIVOT. */ /* */ /* USAGE : simeq(n,X); A and Y global here */ /* */ /* */ /* WRITTEN BY : JON SQUIRE , 28 MAY 1983 */ /* ORIGONAL DEC 1959 for IBM 650, TRANSLATED TO OTHER LANGUAGES */ /* e.g. FORTRAN converted to Ada converted to C */ double *B; /* [nn][nn+1] WORKING MATRIX */ int *ROW; /* ROW INTERCHANGE INDICIES */ int HOLD , I_PIVOT; /* PIVOT INDICIES */ double PIVOT; /* PIVOT ELEMENT VALUE */ double ABS_PIVOT; int i,j,k,m; B = (double *)calloc(nn*(nn+1), sizeof(double)); ROW = (int *)calloc(nn, sizeof(int)); m = nn+1; /* BUILD WORKING DATA STRUCTURE */ for(i=0; i ABS_PIVOT){ I_PIVOT = i; PIVOT = B[ROW[i]*m+k]; ABS_PIVOT = abs ( PIVOT ); } } /* HAVE PIVOT, INTERCHANGE ROW POINTERS */ HOLD = ROW[k]; ROW[k] = ROW[I_PIVOT]; ROW[I_PIVOT] = HOLD; /* CHECK FOR NEAR SINGULAR */ if( ABS_PIVOT < 1.0E-12 ){ for(j=k+1; j1) pwr[i*n+1] = Bpwr[i]; // power of second variable if(n>2) pwr[i*n+2] = Cpwr[i]; if(n>3) pwr[i*n+3] = Dpwr[i]; if(n>4) pwr[i*n+4] = Epwr[i]; if(n>5) pwr[i*n+5] = Fpwr[i]; if(n>6) pwr[i*n+6] = Gpwr[i]; } } /* end get_fit */ void write_fit7(char* fname) // .c will ne added { FILE * outp; int i, j, nn; // non zero coefficients char dest[100]; strcpy(dest, fname); outp = fopen(strcat(dest,".c"), "w"); if(outp==NULL) { printf("file %s could not be opened for write\n", fname); return; } fprintf(outp, "double %s(double a, double b, double c,\n", fname); fprintf(outp, " double d, double e, double f, double g) \n"); fprintf(outp, "{ \n"); fprintf(outp, " int i, j; \n"); fprintf(outp, " int m = %d; \n", m); fprintf(outp, " double t, val=0.0; \n"); fprintf(outp, " double vpwr[%d]; \n", nnn*n); // variable powers computed fprintf(outp, " double C[%d] = { \n", nnn); // coefficients fprintf(outp, " "); for(i=0; i