// ----------------------------------------------------------------------- // Adaptive Simpson's Rule // double adaptiveSimpsonsAux(double (*f)(double), double a, double b, double epsilon, double S, double fa, double fb, double fc, int bottom) { double c = (a + b)/2, h = b - a; double d = (a + c)/2, e = (c + b)/2; double fd = f(d), fe = f(e); double Sleft = (h/12)*(fa + 4*fd + fc); double Sright = (h/12)*(fc + 4*fe + fb); double S2 = Sleft + Sright; if (bottom <= 0 || fabs(S2 - S) <= 15*epsilon) return S2 + (S2 - S)/15; return adaptiveSimpsonsAux(f, a, c, epsilon/2, Sleft, fa, fc, fd, bottom-1) + adaptiveSimpsonsAux(f, c, b, epsilon/2, Sright, fc, fb, fe, bottom-1); }
double adaptiveSimpsons(double (*f)(double), // ptr to function double a, double b, // interval [a,b] double epsilon, // error tolerance int maxRecursionDepth) { // recursion cap double c = (a + b)/2, h = b - a; double fa = f(a), fb = f(b), fc = f(c); double S = (h/6)*(fa + 4*fc + fb); return adaptiveSimpsonsAux(f, a, b, epsilon, S, fa, fb, fc, maxRecursionDepth); }
// an integration function for functions like: X(r) over r // TODO: make more rebust. no infinte loops posible and such. double NIntegration( double (*funcPtr)(double), double Start, double End) { double epsilon = 1.0 / PRECISION; double Mid = (Start + End)/2, h = End - Start; double funcStart = funcPtr(Start), funcEnd= funcPtr(End), funcMid = funcPtr(Mid); double S = (h/6)*(funcStart + 4*funcMid + funcEnd); return adaptiveSimpsonsAux(funcPtr, Start, End, epsilon, S, funcStart, funcEnd, funcMid, MAX_RECURSION_DEPTH); }
/** This section of code uses the Adaptive Simpsons rule to calculate the integral. It uses a recursive way to minimize to error. */ double adaptiveSimpsonsAux(double (*f)(double), double a, double b, double epsilon, double S, double fa, double fb, double fc, int bottom) { double c = (a + b)/2, h = b - a; double d = (a + c)/2, e = (c + b)/2; double fd = f(d), fe = f(e); double Sleft = (h/12)*(fa + 4*fd + fc); double Sright = (h/12)*(fc + 4*fe + fb); double S2 = Sleft + Sright; if (S2 == NAN) { fprintf(stderr,"NAN detected while integrating, stopping integration"); fprintf(stderr,"Sleft = %E\n Sright = %E\n", Sleft, Sright); return NAN; } if (bottom <= 0 || fabs(S2 - S) <= 15*epsilon) return S2 + (S2 - S)/15; return adaptiveSimpsonsAux(f, a, c, epsilon/2, Sleft, fa, fc, fd, bottom-1) + adaptiveSimpsonsAux(f, c, b, epsilon/2, Sright, fc, fb, fe, bottom-1); }