/* nderiv.c compute formulas for numerical derivatives */ /* order is order of derivative, 1 = first derivative, 2 = second */ /* points is number of points where value of function is known */ /* f(x0), f(x1), f(x2) ... f(x points-1) */ /* term is the point where derivative is computer */ /* f'(x0) = (1/bh)*( a(0)*f(x0) + a(1)*f(x1) */ /* + ... + a(points-1)*f(x points-1) */ /* algorithm: use divided differences to get polynomial p(x) that */ /* approximates f(x). f(x)=p(x)+error term */ /* f'(x) = p'(x) + error term' */ /* substitute xj = x0 + j*h */ /* substitute x = x0 to get p'(x0) etc */ #include #undef abs #define abs(x) ((x)<0)?(-(x)):(x) static int gcd(int a, int b) /* needed by deriv */ { int a1, b1, q, r; if(a==0 || b==0) return 1; if(abs(a)>abs(b)) { a1 = abs(a); b1 = abs(b); } else { a1 = abs(b); b1 = abs(a); } r=1; while(r!=0) { q = a1 / b1; r = a1 - q * b1; a1 = b1; b1 = r; } return a1; } /* end gcd */ void deriv(int order, int npoints, int point, int *a, int *bb) { /* compute the exact coefficients to numerically compute a derivative */ /* of order 'order' using 'npoints' at ordinate point, */ /* where order>=1, npoints>=order+1, 0 <= point < npoints, */ /* 'a' array returned with numerator of coefficients, */ /* 'bb' returned with denominator of h^order */ int h[100]; /* coefficients of h */ int x[100]; /* coefficients of x, variable for differentiating */ int numer[100][100]; /* numerator of a term numer[term][pos] */ int denom[100]; /* denominator of coefficient */ int i, j, k, term, b; int jorder, ipower, isum, iat, jterm, r; int debug = 0; if(npoints<=order) { printf("ERROR in call to deriv, npoints=%d < order=%d+1=%d \n\n", npoints, order); return; } for(term=0; term0) for(i=0; i0)printf("p(x)= %d x^%d at term=%d \n", numer[term][j], j, term); } /* have p(x) for this 'term' */ /* differentiate 'order' number of times */ for(jorder=0; jorder0) for(i=0; i0) printf("f^(%d)(x[%d]) = (1/h^%d) (%d/%d f(x[%d]) + \n", order, iat, order, a[jterm], denom[jterm], jterm); } if(debug>0) printf("\n"); b = 0; for(jterm=0; jtermb) b=denom[jterm]; /* largest denominator */ } for(jterm=0; jterm0) printf("f^(%d)(x[%d])=(1/%dh^%d)(%d f(x[%d]) + \n", order, iat, b, order, a[jterm], jterm); } /* end computing terms of coefficients */ *bb = b; } /* end deriv */ static double pown(double x, int pwr) { int i; double val = 1.0; for(i=0; i3 && degree==npoints+1) m=3; /* extra check on error */ for(k=0; k0 && degree3) h=h/2.0; /* cumulative, for reasonable error */ if(order>4) h=h/2.0; if(order>5) h=h/2.0; pwr = degree; sum = 0.0; x = 1.0; /* let x = 1.0, compute derivative using this x */ for(i=0; i