// deriv.go includes deriv, rderiv, nuderiv // 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) // point is the term where derivative is computed // f'(x0) = (1/bh^order)*( a(0)*f(x0) + a(1)*f(x1) // + ... + a(points-1)*f(x points-1) // uniformly spaced points x1=x0+h, x2=x1+h=x1+2*h, ... // // rderiv returns c[0]=(1/bh^order)*a[0] ... // // nuderiv works for non-uniformly spaced points // // 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 package main import "fmt" import "math" func Abs(x int) int { if x < 0 { return -x } return x } // end Abs func Gcd(a int, b int) int { var a1 int var b1 int var q int var r int 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 for r != 0 { q = a1 / b1 r = a1 - q * b1 a1 = b1 b1 = r } return a1 } // end Gcd funct 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, order+1); 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 // nuderiv.c non uniformly spaced derivative coefficients static void inverse(int n, double A[], double AA[]); void nuderiv(int order, int npoint, int point, double x[], double c[]) { double *A; double *AI; double *fct; double pwr; int i, j, k, n; n = npoint; A = (double *)calloc(n*n, sizeof(double)); AI = (double *)calloc(n*n, sizeof(double)); fct = (double *)calloc(n, sizeof(double)); for(i=0; i ABS_PIVOT ){ I_PIVOT = i ; J_PIVOT = j ; PIVOT = AA[ROW[i]*n+COL[j]] ; } } } if(abs(PIVOT) < 1.0E-12){ free(ROW); free(COL); free(TEMP); printf("nuderiv MATRIX is SINGULAR !!! \n"); return; } HOLD = ROW[k]; ROW[k]= ROW[I_PIVOT]; ROW[I_PIVOT] = HOLD ; HOLD = COL[k]; COL[k]= COL[J_PIVOT]; COL[J_PIVOT] = HOLD ; // reduce about pivot AA[ROW[k]*n+COL[k]] = 1.0 / PIVOT ; for (j=0; j=1, npoints>=order+1, 0 <= point < npoints, // 'c' array returned with the coefficients, int i, bb[1], a[100]; double hpower, aa[100]; if(order+npoints<=15) { deriv(order, npoints, point, a, bb); hpower = h; for(i=1; i