/*
Copyright (C) 2009 Ueli Hofstetter
This source code is release under the BSD License.
This file is part of JQuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://jquantlib.org/
JQuantLib is free software: you can redistribute it and/or modify it
under the terms of the JQuantLib license. You should have received a
copy of the license along with this program; if not, please email
. The license is also available online at
.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
JQuantLib is based on QuantLib. http://quantlib.org/
When applicable, the original copyright notice follows this notice.
*/
/*
Copyright (C) 2004, 2005, 2008 Klaus Spanderen
Copyright (C) 2007 StatPro Italia srl
This file is part of QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/
QuantLib is free software: you can redistribute it and/or modify it
under the terms of the QuantLib license. You should have received a
copy of the license along with this program; if not, please email
. The license is also available online at
.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
*/
package org.jquantlib.math.integrals;
import org.jquantlib.QL;
import org.jquantlib.math.Ops;
/**
* Integral of a 1-dimensional function using the Gauss-Kronrod methods
*
* This class provide a non-adaptive integration procedure which uses fixed Gauss-Kronrod abscissae to sample the integrand at a
* maximum of 87 points. It is provided for fast integration of smooth functions.
*
* This function applies the Gauss-Kronrod 10-point, 21-point, 43-point and 87-point integration rules in succession until an
* estimate of the integral of f over (a, b) is achieved within the desired absolute and relative error limits, epsabs and epsrel.
* The function returns the final approximation, result, an estimate of the absolute error, abserr and the number of function
* evaluations used, neval. The Gauss-Kronrod rules are designed in such a way that each rule uses all the results of its
* predecessors, in order to minimize the total number of function evaluations.
*
* @author Ueli Hofstetter
*/
public class GaussKronrodAdaptive extends KronrodIntegral {
// weights for 7-point Gauss-Legendre integration
// (only 4 values out of 7 are given as they are symmetric)
private static final double g7w[] = {
0.417959183673469,
0.381830050505119,
0.279705391489277,
0.129484966168870 };
// weights for 15-point Gauss-Kronrod integration
private static final double k15w[] = {
0.209482141084728,
0.204432940075298,
0.190350578064785,
0.169004726639267,
0.140653259715525,
0.104790010322250,
0.063092092629979,
0.022935322010529 };
// abscissae (evaluation points)
// for 15-point Gauss-Kronrod integration
private static final double k15t[] = {
0.000000000000000,
0.207784955007898,
0.405845151377397,
0.586087235467691,
0.741531185599394,
0.864864423359769,
0.949107912342758,
0.991455371120813 };
public GaussKronrodAdaptive(final double absoluteAccuracy, final int maxEvaluations) {
super(absoluteAccuracy, maxEvaluations);
QL.require(maxEvaluations >= 15 , "required maxEvaluations must be >= 15"); // TODO: message
}
@Override
protected double integrate(final Ops.DoubleOp f, final double a, final double b) {
return integrateRecursively(f, a, b, absoluteAccuracy());
}
private double integrateRecursively(final Ops.DoubleOp f, final double a, final double b, final double tolerance) {
final double halflength = (b - a) / 2;
final double center = (a + b) / 2;
double g7; // will be result of G7 integral
double k15; // will be result of K15 integral
double t, fsum; // t (abscissa) and f(t)
final double fc = f.op(center);
g7 = fc * g7w[0];
k15 = fc * k15w[0];
// calculate g7 and half of k15
int j, j2;
for (j = 1, j2 = 2; j < 4; j++, j2 += 2) {
t = halflength * k15t[j2];
fsum = f.op(center - t) + f.op(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.op(center - t) + f.op(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 (Math.abs(k15 - g7) < tolerance)
return k15;
else {
QL.require(numberOfEvaluations() + 30 <= maxEvaluations() , "maximum number of function evaluations exceeded"); // TODO: message
return integrateRecursively(f, a, center, tolerance / 2) + integrateRecursively(f, center, b, tolerance / 2);
}
}
}
Ads help maintain this website.