Real GaussLobattoIntegral::calculateAbsTolerance( const boost::function<Real (Real)>& f, Real a, Real b) const { Real relTol = std::max(relAccuracy_, QL_EPSILON); const Real m = (a+b)/2; const Real h = (b-a)/2; const Real y1 = f(a); const Real y3 = f(m-alpha_*h); const Real y5 = f(m-beta_*h); const Real y7 = f(m); const Real y9 = f(m+beta_*h); const Real y11= f(m+alpha_*h); const Real y13= f(b); const Real f1 = f(m-x1_*h); const Real f2 = f(m+x1_*h); const Real f3 = f(m-x2_*h); const Real f4 = f(m+x2_*h); const Real f5 = f(m-x3_*h); const Real f6 = f(m+x3_*h); Real acc=h*(0.0158271919734801831*(y1+y13) +0.0942738402188500455*(f1+f2) +0.1550719873365853963*(y3+y11) +0.1888215739601824544*(f3+f4) +0.1997734052268585268*(y5+y9) +0.2249264653333395270*(f5+f6) +0.2426110719014077338*y7); increaseNumberOfEvaluations(13); if (acc == 0.0 && ( f1 != 0.0 || f2 != 0.0 || f3 != 0.0 || f4 != 0.0 || f5 != 0.0 || f6 != 0.0)) { QL_FAIL("can not calculate absolute accuracy " "from relative accuracy"); } Real r = 1.0; if (useConvergenceEstimate_) { const Real integral2 = (h/6)*(y1+y13+5*(y5+y9)); const Real integral1 = (h/1470)*(77*(y1+y13)+432*(y3+y11)+ 625*(y5+y9)+672*y7); if (std::fabs(integral2-acc) != 0.0) r = std::fabs(integral1-acc)/std::fabs(integral2-acc); if (r == 0.0 || r > 1.0) r = 1.0; } if (relAccuracy_ != Null<Real>()) return std::min(absoluteAccuracy(), acc*relTol)/(r*QL_EPSILON); else { return absoluteAccuracy()/(r*QL_EPSILON); } }
Real GaussKronrodAdaptive::integrate(const boost::function<Real (Real)>& f, Real a, Real b) const { return integrateRecursively(f, a, b, absoluteAccuracy()); }
Real GaussKronrodNonAdaptive::integrate(const boost::function<Real (Real)>& f, Real a, Real b) const { Real result; //Size neval; Real fv1[5], fv2[5], fv3[5], fv4[5]; Real savfun[21]; /* array of function values which have been computed */ Real res10, res21, res43, res87; /* 10, 21, 43 and 87 point results */ Real err; Real resAbs; /* approximation to the integral of abs(f) */ Real resasc; /* approximation to the integral of abs(f-i/(b-a)) */ int k ; QL_REQUIRE(a<b, "b must be greater than a)"); const Real halfLength = 0.5 * (b - a); const Real center = 0.5 * (b + a); const Real fCenter = f(center); // Compute the integral using the 10- and 21-point formula. res10 = 0; res21 = w21b[5] * fCenter; resAbs = w21b[5] * std::fabs(fCenter); for (k = 0; k < 5; k++) { Real abscissa = halfLength * x1[k]; Real fval1 = f(center + abscissa); Real fval2 = f(center - abscissa); Real fval = fval1 + fval2; res10 += w10[k] * fval; res21 += w21a[k] * fval; resAbs += w21a[k] * (std::fabs(fval1) + std::fabs(fval2)); savfun[k] = fval; fv1[k] = fval1; fv2[k] = fval2; } for (k = 0; k < 5; k++) { Real abscissa = halfLength * x2[k]; Real fval1 = f(center + abscissa); Real fval2 = f(center - abscissa); Real fval = fval1 + fval2; res21 += w21b[k] * fval; resAbs += w21b[k] * (std::fabs(fval1) + std::fabs(fval2)); savfun[k + 5] = fval; fv3[k] = fval1; fv4[k] = fval2; } result = res21 * halfLength; resAbs *= halfLength ; Real mean = 0.5 * res21; resasc = w21b[5] * std::fabs(fCenter - mean); for (k = 0; k < 5; k++) resasc += (w21a[k] * (std::fabs(fv1[k] - mean) + std::fabs(fv2[k] - mean)) + w21b[k] * (std::fabs(fv3[k] - mean) + std::fabs(fv4[k] - mean))); err = rescaleError ((res21 - res10) * halfLength, resAbs, resasc) ; resasc *= halfLength ; // test for convergence. if (err < absoluteAccuracy() || err < relativeAccuracy() * std::fabs(result)) { setAbsoluteError(err); setNumberOfEvaluations(21); return result; } /* compute the integral using the 43-point formula. */ res43 = w43b[11] * fCenter; for (k = 0; k < 10; k++) res43 += savfun[k] * w43a[k]; for (k = 0; k < 11; k++) { Real abscissa = halfLength * x3[k]; Real fval = (f(center + abscissa) + f(center - abscissa)); res43 += fval * w43b[k]; savfun[k + 10] = fval; } // test for convergence. result = res43 * halfLength; err = rescaleError ((res43 - res21) * halfLength, resAbs, resasc); if (err < absoluteAccuracy() || err < relativeAccuracy() * std::fabs(result)) { setAbsoluteError(err); setNumberOfEvaluations(43); return result; } /* compute the integral using the 87-point formula. */ res87 = w87b[22] * fCenter; for (k = 0; k < 21; k++) res87 += savfun[k] * w87a[k]; for (k = 0; k < 22; k++) { Real abscissa = halfLength * x4[k]; res87 += w87b[k] * (f(center + abscissa) + f(center - abscissa)); } // test for convergence. result = res87 * halfLength ; err = rescaleError ((res87 - res43) * halfLength, resAbs, resasc); setAbsoluteError(err); setNumberOfEvaluations(87); return result; }