Real GaussKronrodAdaptive::integrateRecursively( const boost::function<Real (Real)>& f, Real a, Real b, Real tolerance) const { Real halflength = (b - a) / 2; Real center = (a + b) / 2; Real g7; // will be result of G7 integral Real k15; // will be result of K15 integral Real t, fsum; // t (abscissa) and f(t) Real fc = f(center); g7 = fc * g7w[0]; k15 = fc * k15w[0]; // calculate g7 and half of k15 Integer j, j2; for (j = 1, j2 = 2; j < 4; j++, j2 += 2) { t = halflength * k15t[j2]; fsum = f(center - t) + f(center + t); g7 += fsum * g7w[j]; k15 += fsum * k15w[j2]; } // calculate other half of k15 for (j2 = 1; j2 < 8; j2 += 2) { t = halflength * k15t[j2]; fsum = f(center - t) + f(center + t); k15 += fsum * k15w[j2]; } // multiply by (a - b) / 2 g7 = halflength * g7; k15 = halflength * k15; // 15 more function evaluations have been used increaseNumberOfEvaluations(15); // error is <= k15 - g7 // if error is larger than tolerance then split the interval // in two and integrate recursively if (std::fabs(k15 - g7) < tolerance) { return k15; } else { QL_REQUIRE(numberOfEvaluations()+30 <= maxEvaluations(), "maximum number of function evaluations " "exceeded"); return integrateRecursively(f, a, center, tolerance/2) + integrateRecursively(f, center, b, tolerance/2); } }
Real GaussLobattoIntegral::adaptivGaussLobattoStep( const boost::function<Real (Real)>& f, Real a, Real b, Real fa, Real fb, Real acc) const { QL_REQUIRE(numberOfEvaluations() < maxEvaluations(), "max number of iterations reached"); const Real h=(b-a)/2; const Real m=(a+b)/2; const Real mll=m-alpha_*h; const Real ml =m-beta_*h; const Real mr =m+beta_*h; const Real mrr=m+alpha_*h; const Real fmll= f(mll); const Real fml = f(ml); const Real fm = f(m); const Real fmr = f(mr); const Real fmrr= f(mrr); increaseNumberOfEvaluations(5); const Real integral2=(h/6)*(fa+fb+5*(fml+fmr)); const Real integral1=(h/1470)*(77*(fa+fb) +432*(fmll+fmrr)+625*(fml+fmr)+672*fm); // avoid 80 bit logic on x86 cpu volatile Real dist = acc + (integral1-integral2); if(dist==acc || mll<=a || b<=mrr) { QL_REQUIRE(m>a && b>m,"Interval contains no more machine number"); return integral1; } else { return adaptivGaussLobattoStep(f,a,mll,fa,fmll,acc) + adaptivGaussLobattoStep(f,mll,ml,fmll,fml,acc) + adaptivGaussLobattoStep(f,ml,m,fml,fm,acc) + adaptivGaussLobattoStep(f,m,mr,fm,fmr,acc) + adaptivGaussLobattoStep(f,mr,mrr,fmr,fmrr,acc) + adaptivGaussLobattoStep(f,mrr,b,fmrr,fb,acc); } }