Exemplo n.º 1
0
    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);
        }
    }
Exemplo n.º 2
0
Real
GaussKronrodAdaptive::integrate(const boost::function<Real (Real)>& f,
                                Real a,
                                Real b) const {
    return integrateRecursively(f, a, b, absoluteAccuracy());
}
Exemplo n.º 3
0
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;
}