Skip to content
Permalink
master
Go to file
 
 
Cannot retrieve contributors at this time
714 lines (615 sloc) 29.3 KB
/**
* \file Integrator.h
* This file contains routines for numerical integration using Gauss-Kronrod quadrature.
* \sa R Piessens, E de Doncker-Kapenger, C Ueberhuber, D Kahaner, QUADPACK, A Subroutine Package
* for Automatic Integration, Springer Verlag, 1983.
*/
#ifndef EIGEN_INTEGRATOR_H
#define EIGEN_INTEGRATOR_H
namespace Numer
{
/**
* \ingroup Quadrature_Module
*
* \brief This class provides numerical integration functionality.
*
* Memory management and additional information (e.g. number of function calls, estimated error),
* are provided by the class in a way that can support the future porting of additional quadrature
* functions from the QUADPACK library.
*
* \todo Ensure only appropriates types are used for Scalar_, e.g. prohibit integers.
*/
template <typename Scalar_>
class Integrator
{
public:
typedef Scalar_ Scalar;
typedef Eigen::DenseIndex DenseIndex;
/**
* \brief The local Gauss-Kronrod quadrature rule to use.
*/
enum QuadratureRule
{
GaussKronrod15 = 1, /**< Use 7, 15 points. */
GaussKronrod21 = 2, /**< Use 10, 21 points. */
GaussKronrod31 = 3, /**< Use 15, 31 points. */
GaussKronrod41 = 4, /**< Use 20, 41 points. */
GaussKronrod51 = 5, /**< Use 25, 51 points. */
GaussKronrod61 = 6, /**< Use 30, 61 points. */
GaussKronrod71 = 7, /**< Use 35, 71 points. */
GaussKronrod81 = 8, /**< Use 40, 81 points. */
GaussKronrod91 = 9, /**< Use 45, 91 points. */
GaussKronrod101 = 10, /**< Use 50, 101 points. */
GaussKronrod121 = 11, /**< Use 60, 121 points. */
GaussKronrod201 = 12 /**< Use 100, 201 points. */
};
/**
* \brief Prepares an Integrator for a call to a quadrature function.
*
* \param[in] maxSubintervals The maximum number of subintervals allowed in the subdivision process
* of quadrature functions. This corresponds to the amount of memory allocated for said
* functions.
*/
Integrator(const int maxSubintervals)
: m_maxSubintervals(maxSubintervals)
{
assert(maxSubintervals >= 1); // \todo use Eigen assert.
m_errorListIndices.resize(maxSubintervals, 1);
m_lowerList.resize(maxSubintervals, 1);
m_upperList.resize(maxSubintervals, 1);
m_integralList.resize(maxSubintervals, 1);
m_errorList.resize(maxSubintervals, 1);
}
/**
* \brief This function calculates an approximation I' to a given definite integral I, the
* integral of f from lowerLimit to upperLimit, hopefully satisfying
* abs(I - I') <= max(desiredAbsoluteError, desiredRelativeError * abs(I)).
*
* This function is best suited for integrands without singularities or discontinuities, which
* are too difficult for non-adaptive quadrature, and, in particular, for integrands with
* oscillating behavior of a non-specific type.
*
* \param[in,out] f The function defining the integrand function.
* \param[in] lowerLimit The lower limit of integration.
* \param[in] upperLimit The upper limit of integration.
* \param[in] desiredAbsoluteError The absolute accuracy requested.
* \param[in] desiredRelativeError The relative accuracy requested.
* If desiredAbsoluteError <= 0 and desiredRelativeError < 50 * machinePrecision,
* the routine will end with errorCode = 6.
* \param[in] quadratureRule The local Gauss-Kronrod quadrature rule to use.
*
* \returns The approximation to the integral.
*/
template <typename FunctionType>
Scalar quadratureAdaptive(
const FunctionType& f, const Scalar lowerLimit, const Scalar upperLimit,
const Scalar desiredAbsoluteError = Scalar(0.), const Scalar desiredRelativeError = Scalar(0.),
const QuadratureRule quadratureRule = Integrator<Scalar>::QuadratureRule(1))
{
if ((desiredAbsoluteError <= Scalar(0.) && desiredRelativeError < Eigen::NumTraits<Scalar>::epsilon())
|| m_maxSubintervals < 1)
{
m_errorCode = 6;
return Scalar(0.);
}
m_errorCode = 0;
m_numEvaluations = 0;
m_lowerList[0] = lowerLimit;
m_upperList[0] = upperLimit;
m_integralList[0] = Scalar(0.);
m_errorList[0] = Scalar(0.);
m_errorListIndices[0] = 0;
m_errorListIndices[1] = 1;
Scalar absDiff;
Scalar absResult;
// First approximation to the integral
Scalar integral = quadratureKronrod(
f, lowerLimit, upperLimit, m_estimatedError, absDiff, absResult, quadratureRule);
m_numSubintervals = 1;
m_integralList[0] = integral;
m_errorList[0] = m_estimatedError;
// Test on accuracy.
using std::abs;
Scalar errorBound = (std::max)(desiredAbsoluteError, desiredRelativeError * abs(integral));
if (m_maxSubintervals == 1)
{
m_errorCode = 1;
}
else if (m_estimatedError <= Eigen::NumTraits<Scalar>::epsilon() * Scalar(50.) * absDiff
&& m_estimatedError > errorBound)
{
m_errorCode = 2;
}
if (m_errorCode != 0
|| (m_estimatedError <= errorBound && m_estimatedError != absResult)
|| m_estimatedError == Scalar(0.))
{
if (quadratureRule == GaussKronrod15)
{
m_numEvaluations = m_numEvaluations * 30 + 15;
}
else
{
m_numEvaluations = (quadratureRule * 10 + 1) * (m_numEvaluations * 2 + 1);
}
return integral;
}
// The sum of the integrals over the subintervals.
Scalar area = integral;
Scalar errorSum = m_estimatedError;
// The maximum interval error.
Scalar errorMax = m_estimatedError;
// An index into m_errorList at the interval with largest error estimate.
DenseIndex maxErrorIndex = 0;
DenseIndex nrMax = 0;
int roundOff1 = 0;
int roundOff2 = 0;
// Main loop for the integration
for (m_numSubintervals = 2; m_numSubintervals <= m_maxSubintervals; ++m_numSubintervals)
{
const DenseIndex numSubintervalsIndex = m_numSubintervals - 1;
// Bisect the subinterval with the largest error estimate.
Scalar lower1 = m_lowerList[maxErrorIndex];
Scalar upper2 = m_upperList[maxErrorIndex];
Scalar upper1 = (lower1 + upper2) * Scalar(.5);
Scalar lower2 = upper1;
Scalar error1;
Scalar error2;
Scalar absDiff1;
Scalar absDiff2;
const Scalar area1 = quadratureKronrod(
f, lower1, upper1, error1, absResult, absDiff1, quadratureRule);
const Scalar area2 = quadratureKronrod(
f, lower2, upper2, error2, absResult, absDiff2, quadratureRule);
// Improve previous approximations to integral and error and test for accuracy.
++(m_numEvaluations);
const Scalar area12 = area1 + area2;
const Scalar error12 = error1 + error2;
errorSum += error12 - errorMax;
area += area12 - m_integralList[maxErrorIndex];
if (absDiff1 != error1 && absDiff2 != error2)
{
if (abs(m_integralList[maxErrorIndex] - area12) <= abs(area12) * Scalar(1.e-5)
&& error12 >= errorMax * Scalar(.99))
{
++roundOff1;
}
if (m_numSubintervals > 10 && error12 > errorMax)
{
++roundOff2;
}
}
m_integralList[maxErrorIndex] = area1;
m_integralList[numSubintervalsIndex] = area2;
errorBound = (std::max)(desiredAbsoluteError, desiredRelativeError * abs(area));
if (errorSum > errorBound)
{
// Set error flag in the case that the number of subintervals has reached the max allowable.
if (m_numSubintervals == m_maxSubintervals)
{
m_errorCode = 1;
}
// Test for roundoff error and set error flag.
else if (roundOff1 >= 6 || roundOff2 >= 20)
{
m_errorCode = 2;
}
// Set m_error_code in the case of poor integrand behaviour within
// the integration range.
else if ((std::max)(abs(lower1), abs(upper2))
<= (Eigen::NumTraits<Scalar>::epsilon() * Scalar(100.) + Scalar(1.))
* (abs(lower2) + (std::numeric_limits<Scalar>::min)() * Scalar(1.e3) ))
{
m_errorCode = 3;
}
}
// Append the newly-created intervals to the list.
if (error2 > error1)
{
m_lowerList[numSubintervalsIndex] = lower1;
m_lowerList[maxErrorIndex] = lower2;
m_upperList[numSubintervalsIndex] = upper1;
m_integralList[maxErrorIndex] = area2;
m_integralList[numSubintervalsIndex] = area1;
m_errorList[maxErrorIndex] = error2;
m_errorList[numSubintervalsIndex] = error1;
}
else
{
m_lowerList[numSubintervalsIndex] = lower2;
m_upperList[maxErrorIndex] = upper1;
m_upperList[numSubintervalsIndex] = upper2;
m_errorList[maxErrorIndex] = error1;
m_errorList[numSubintervalsIndex] = error2;
}
// Maintain the descending ordering in the list of error estimates and select the subinterval
// with the largest error estimate, (the next subinterval to be bisected).
quadratureSort(maxErrorIndex, errorMax,nrMax);
if (m_errorCode != 0 || errorSum <= errorBound || m_numSubintervals == m_maxSubintervals)
{
break;
}
}
integral = Scalar(0.);
for (int k = 0; k < m_numSubintervals; ++k)
{
integral += m_integralList[k];
}
m_estimatedError = errorSum;
if (quadratureRule == GaussKronrod15)
{
m_numEvaluations = m_numEvaluations * 30 + 15;
}
else
{
m_numEvaluations = (quadratureRule * 10 + 1) * (m_numEvaluations * 2 + 1);
}
return integral;
}
/**
* \brief Returns the estimated absolute error from the last integration.
*
* \returns The value returned will only be valid after calling quadratureAdaptive at least once.
*/
inline Scalar estimatedError() const {return m_estimatedError;}
/**
* \brief Returns the error code.
*
* \returns The value returned will only be valid after calling quadratureAdaptive at least once.
*/
inline DenseIndex errorCode() const {return m_errorCode;}
private:
/**
* \brief This routine maintains the descending ordering in the list of the local error
* estimates resulting from the interval subdivision process.
*
* At each call two error estimates are inserted using the sequential search method, top-down
* for the largest error estimate and bottom-up for the smallest error estimate.
*
* \param[in,out] maxErrorIndex The index to the nrMax-th largest error estimate currently in the list.
* \param[in,out] errorMax The nrMax-th largest error estimate. errorMaxIndex = errorList(maxError).
* \param[in,out] nrMax The integer value such that maxError = errorListIndices(nrMax).
*/
void quadratureSort(DenseIndex& maxErrorIndex, Scalar& errorMax, DenseIndex& nrMax)
{
if (m_numSubintervals <= 2)
{
m_errorListIndices[0] = 0;
m_errorListIndices[1] = 1;
maxErrorIndex = m_errorListIndices[nrMax];
errorMax = m_errorList[maxErrorIndex];
return;
}
// This part of the routine is only executed if, due to a difficult integrand, subdivision has
// increased the error estimate. In the normal case the insert procedure should start after the
// nrMax-th largest error estimate.
DenseIndex i = 0;
DenseIndex succeed = 0;
const Scalar errorMaximum = m_errorList[maxErrorIndex];
if (nrMax != 1)
{
for (i = 1; i < nrMax; ++i)
{
succeed = m_errorListIndices[nrMax - 1];
if (errorMaximum <= m_errorList[succeed])
{
break;
}
m_errorListIndices[nrMax] = succeed;
--nrMax;
}
}
// Compute the number of elements in the list to be maintained in descending order. This number
// depends on the number of subdivisions remaining allowed.
DenseIndex topBegin = m_numSubintervals - 1;
DenseIndex bottomEnd = topBegin - 1;
DenseIndex start = nrMax + 1;
if (m_numSubintervals > m_maxSubintervals / 2 + 2)
{
topBegin = m_maxSubintervals + 3 - m_numSubintervals + 1;
}
// Insert errorMax by traversing the list top-down, starting comparison from the element
// errorlist(m_errorListIndices(nrMax+1)).
if (start <= bottomEnd)
{
for (i = start; i <= bottomEnd; ++i)
{
succeed = m_errorListIndices[i];
if (errorMaximum >= m_errorList[succeed])
{
break;
}
m_errorListIndices[i - 1] = succeed;
}
}
if (start > bottomEnd)
{
m_errorListIndices[bottomEnd] = maxErrorIndex;
m_errorListIndices[topBegin] = m_numSubintervals - 1;
maxErrorIndex = m_errorListIndices[nrMax];
errorMax = m_errorList[maxErrorIndex];
return;
}
// Insert errorMin by traversing the list bottom-up.
m_errorListIndices[i - 1] = maxErrorIndex;
DenseIndex tempIndex = bottomEnd;
for (DenseIndex j = i; j <= bottomEnd; ++j)
{
succeed = m_errorListIndices[tempIndex];
if (m_errorList[m_numSubintervals - 1] < m_errorList[succeed])
{
m_errorListIndices[tempIndex + 1] = m_numSubintervals - 1;
maxErrorIndex = m_errorListIndices[nrMax];
errorMax = m_errorList[maxErrorIndex];
return;
}
m_errorListIndices[tempIndex + 1] = succeed;
--tempIndex;
}
m_errorListIndices[i] = m_numSubintervals - 1;
maxErrorIndex = m_errorListIndices[nrMax];
errorMax = m_errorList[maxErrorIndex];
return;
}
/**
* \brief This function calculates an approximation I' to a given definite integral I, the
* integral of f from lowerLimit to upperLimit and provides an error estimate.
*
* \param[in] f The variable representing the function f(x) be integrated.
* \param[in] lowerLimit The lower limit of integration.
* \param[in] upperLimit The upper limit of integration.
* \param[in,out] errorEstimate Estimate of the modulus of the absolute error, not to exceed
* abs(I - I').
* \param[in,out] absIntegral The approximation to the integral of abs(f) from lowerLimit to
* upperLimit.
* \param[in,out] absDiffIntegral The approximation to the integral of
* abs(f - I/(upperLimit - lowerLimit)).
*
* \returns The approximation I' to the integral I. It is computed by applying the 15, 21, 31,
* 41, 51, 61, 71, 81, 91, 101, 121, 201-point kronrod rule obtained by optimal addition
* of abscissae to the 7, 10, 15, 20, 25, 30, 35, 40, 45, 50, 60, 100-point Gauss rule.
*
* \detail This series of functions represents a priority queue data structure:
* - Apply Gauss-Kronrod on the whole initial interval and estimate the error.
* - Split the interval symmetrically in two and again apply Gauss-Kronrod on the intervals,
* estimate the errors and add a pair (or tuple) "interval, error" to the priority queue.
* - If the total error is smaller than the requested tolerance, or if the maximum number
* of subdivisions is reached, discontinue the process.
* - Otherwise, pop the top element from the queue (highest error), split the interval in two,
* and apply Gauss-Kronrod to the new intervals, add those two new elements to the priority
* queue and repeat from the previous step.
*/
template <typename FunctionType>
Scalar quadratureKronrod(
const FunctionType& f, const Scalar lowerLimit, const Scalar upperLimit,
Scalar& estimatedError, Scalar& absIntegral, Scalar& absDiffIntegral,
const QuadratureRule quadratureRule)
{
switch (quadratureRule)
{
case GaussKronrod15:
return quadratureKronrodHelper(
QuadratureKronrod<Scalar>::abscissaeGaussKronrod15,
QuadratureKronrod<Scalar>::weightsGaussKronrod15, QuadratureKronrod<Scalar>::weightsGauss15,
f, lowerLimit, upperLimit, estimatedError, absIntegral, absDiffIntegral, quadratureRule);
case GaussKronrod21:
return quadratureKronrodHelper(
QuadratureKronrod<Scalar>::abscissaeGaussKronrod21,
QuadratureKronrod<Scalar>::weightsGaussKronrod21, QuadratureKronrod<Scalar>::weightsGauss21,
f, lowerLimit, upperLimit, estimatedError, absIntegral, absDiffIntegral, quadratureRule);
case GaussKronrod31:
return quadratureKronrodHelper(
QuadratureKronrod<Scalar>::abscissaeGaussKronrod31,
QuadratureKronrod<Scalar>::weightsGaussKronrod31, QuadratureKronrod<Scalar>::weightsGauss31,
f, lowerLimit, upperLimit, estimatedError, absIntegral, absDiffIntegral, quadratureRule);
case GaussKronrod41:
return quadratureKronrodHelper(
QuadratureKronrod<Scalar>::abscissaeGaussKronrod41,
QuadratureKronrod<Scalar>::weightsGaussKronrod41, QuadratureKronrod<Scalar>::weightsGauss41,
f, lowerLimit, upperLimit, estimatedError, absIntegral, absDiffIntegral, quadratureRule);
case GaussKronrod51:
return quadratureKronrodHelper(
QuadratureKronrod<Scalar>::abscissaeGaussKronrod51,
QuadratureKronrod<Scalar>::weightsGaussKronrod51, QuadratureKronrod<Scalar>::weightsGauss51,
f, lowerLimit, upperLimit, estimatedError, absIntegral, absDiffIntegral, quadratureRule);
case GaussKronrod61:
return quadratureKronrodHelper(
QuadratureKronrod<Scalar>::abscissaeGaussKronrod61,
QuadratureKronrod<Scalar>::weightsGaussKronrod61, QuadratureKronrod<Scalar>::weightsGauss61,
f, lowerLimit, upperLimit, estimatedError, absIntegral, absDiffIntegral, quadratureRule);
case GaussKronrod71:
return quadratureKronrodHelper(
QuadratureKronrod<Scalar>::abscissaeGaussKronrod71,
QuadratureKronrod<Scalar>::weightsGaussKronrod71, QuadratureKronrod<Scalar>::weightsGauss71,
f, lowerLimit, upperLimit, estimatedError, absIntegral, absDiffIntegral, quadratureRule);
case GaussKronrod81:
return quadratureKronrodHelper(
QuadratureKronrod<Scalar>::abscissaeGaussKronrod81,
QuadratureKronrod<Scalar>::weightsGaussKronrod81, QuadratureKronrod<Scalar>::weightsGauss81,
f, lowerLimit, upperLimit, estimatedError, absIntegral, absDiffIntegral, quadratureRule);
case GaussKronrod91:
return quadratureKronrodHelper(
QuadratureKronrod<Scalar>::abscissaeGaussKronrod91,
QuadratureKronrod<Scalar>::weightsGaussKronrod91, QuadratureKronrod<Scalar>::weightsGauss91,
f, lowerLimit, upperLimit, estimatedError, absIntegral, absDiffIntegral, quadratureRule);
case GaussKronrod101:
return quadratureKronrodHelper(
QuadratureKronrod<Scalar>::abscissaeGaussKronrod101,
QuadratureKronrod<Scalar>::weightsGaussKronrod101, QuadratureKronrod<Scalar>::weightsGauss101,
f, lowerLimit, upperLimit, estimatedError, absIntegral, absDiffIntegral, quadratureRule);
case GaussKronrod121:
return quadratureKronrodHelper(
QuadratureKronrod<Scalar>::abscissaeGaussKronrod121,
QuadratureKronrod<Scalar>::weightsGaussKronrod121, QuadratureKronrod<Scalar>::weightsGauss121,
f, lowerLimit, upperLimit, estimatedError, absIntegral, absDiffIntegral, quadratureRule);
case GaussKronrod201:
return quadratureKronrodHelper(
QuadratureKronrod<Scalar>::abscissaeGaussKronrod201,
QuadratureKronrod<Scalar>::weightsGaussKronrod201, QuadratureKronrod<Scalar>::weightsGauss201,
f, lowerLimit, upperLimit, estimatedError, absIntegral, absDiffIntegral, quadratureRule);
default:
return Scalar(0.);
}
}
template <typename FunctionType, int numKronrodRows, int numGaussRows, int alignment>
Scalar quadratureKronrodHelper(
Eigen::Array<Scalar, numKronrodRows, 1, alignment, numKronrodRows, 1> abscissaeGaussKronrod,
Eigen::Array<Scalar, numKronrodRows, 1, alignment, numKronrodRows, 1> weightsGaussKronrod,
Eigen::Array<Scalar, numGaussRows, 1, alignment, numGaussRows, 1> weightsGauss, const FunctionType& f, const Scalar lowerLimit,
const Scalar upperLimit, Scalar& estimatedError, Scalar& absIntegral, Scalar& absDiffIntegral,
const QuadratureRule quadratureRule)
{
// Half-length of the interval.
const Scalar halfLength = (upperLimit - lowerLimit) * Scalar(.5);
// Midpoint of the interval.
const Scalar center = (lowerLimit + upperLimit) * Scalar(.5);
DenseIndex size1 = numKronrodRows - 1;
DenseIndex size2 = numGaussRows - 1;
// Points to be evaluated.
Eigen::Array<Scalar, 2 * numKronrodRows - 1, 1> points;
// points[0] = center
// points[1], points[2], ..., points[size1]: center - abscissa
// points[size1 + 1], ..., points[2 * size1]: center + abscissa
points[0] = center;
for (DenseIndex j = 1; j <= size1; ++j)
{
const Scalar abscissa = halfLength * abscissaeGaussKronrod[j - 1];
points[j] = center - abscissa;
points[size1 + j] = center + abscissa;
}
// Evaluate points.
f.eval(points.data(), 2 * numKronrodRows - 1);
Eigen::Array<Scalar, 2 * numKronrodRows - 1, 1>& fPoints = points; // Alias of points
const Scalar fCenter = fPoints[0];
Eigen::Map< Eigen::Array<Scalar, numKronrodRows - 1, 1> > f1Array(&fPoints[1], size1, 1);
Eigen::Map< Eigen::Array<Scalar, numKronrodRows - 1, 1> > f2Array(&fPoints[size1 + 1], size1, 1);
// The result of the Gauss formula.
Scalar resultGauss;
if (quadratureRule % 2 == 0)
{
resultGauss = Scalar(0.);
}
else
{
resultGauss = weightsGauss[size2] * fCenter;
}
// The result of the Kronrod formula.
Scalar resultKronrod = weightsGaussKronrod[size1] * fCenter;
using std::abs;
absIntegral = abs(resultKronrod);
resultKronrod += ((f1Array + f2Array) * weightsGaussKronrod.head(size1)).sum();
// Approximation to the mean value of f over the interval (lowerLimit, upperLimit),
// i.e. I / (upperLimit - lowerLimit)
Scalar resultMeanKronrod = resultKronrod * Scalar(.5);
absDiffIntegral = weightsGaussKronrod[size1] * (abs(fCenter - resultMeanKronrod));
for (DenseIndex j = 0; j < size1; ++j)
{
if (j % 2)
resultGauss += weightsGauss[j / 2] * (f1Array[j] + f2Array[j]);
absIntegral += weightsGaussKronrod[j] * (abs(f1Array[j]) + abs(f2Array[j]));
absDiffIntegral += weightsGaussKronrod[j] * (abs(f1Array[j] - resultMeanKronrod) + abs(f2Array[j] - resultMeanKronrod));
}
Scalar result = resultKronrod * halfLength;
absIntegral *= abs(halfLength);
absDiffIntegral *= abs(halfLength);
estimatedError = abs((resultKronrod - resultGauss) * halfLength);
if (absDiffIntegral != Scalar(0.) && estimatedError != Scalar(0.))
{
const Scalar tmp = estimatedError * Scalar(200.) / absDiffIntegral;
estimatedError = absDiffIntegral
* (std::min)(Scalar(1.), tmp * std::sqrt(tmp));
}
if (absIntegral
> (std::numeric_limits<Scalar>::min)() / (Eigen::NumTraits<Scalar>::epsilon() * Scalar(50.) ))
{
estimatedError = (std::max)(
Eigen::NumTraits<Scalar>::epsilon() * static_cast<Scalar>(50.) * absIntegral,
estimatedError);
}
return result;
}
/**
* \brief An Array of dimension m_maxSubintervals for error estimates.
*
* The first k elements are indices to the error estimates over the subintervals, such that
* errorList(errorListIndices(0)), ..., errorList(errorListIndices(k - 1)) forms a decreasing
* sequence, with k = m_numSubintervals if m_numSubintervals <= (m_maxSubintervals/2 + 2),
* otherwise k = m_maxSubintervals + 1 - m_numSubintervals.
*/
Eigen::Array<DenseIndex, Eigen::Dynamic, 1> m_errorListIndices;
/**
* \brief An Array of dimension m_maxSubintervals for subinterval left endpoints.
*
* The first m_numSubintervals elements are the lower end points of the subintervals in the
* partition of the given integration range (lowerLimit, upperLimit).
*/
Eigen::Array<Scalar, Eigen::Dynamic, 1> m_lowerList;
/**
* \brief An Array of dimension m_maxSubintervals for subinterval upper endpoints.
*
* The first m_numSubintervals elements are the upper end points of the subintervals in the
* partition of the given integration range (lowerLimit, upperLimit).
*/
Eigen::Array<Scalar, Eigen::Dynamic, 1> m_upperList;
/**
* \brief An Array of dimension m_maxSubintervals for integral approximations.
*
* The first m_numSubintervals elements are the integral approximations on the subintervals.
*/
Eigen::Array<Scalar, Eigen::Dynamic, 1> m_integralList;
/**
* \brief An Array of dimension m_maxSubintervals for error estimates.
*
* The first m_numSubintervals elements of which are the moduli of the absolute error estimates
* on the subintervals.
*/
Eigen::Array<Scalar, Eigen::Dynamic, 1> m_errorList;
/**
* \brief Gives an upper bound on the number of subintervals. Must be at least 1.
*/
DenseIndex m_maxSubintervals;
/**
* \brief Estimate of the modulus of the absolute error, which should equal or exceed abs(I - I').
*/
Scalar m_estimatedError;
/**
* \brief The number of integrand evaluations.
*/
DenseIndex m_numEvaluations;
/**
* \brief Error messages generated by the routine.
*
* errorCode = 0 Indicates normal and reliable termination of the routine. (It is assumed that
* the requested accuracy has been achieved.)
* errorCode > 0 Any errorCode greater than zero indicates abnormal termination of the routine.
* (The estimates for integral and m_estimatedError are less reliable and the
* requested accuracy has not been achieved.)
* errorCode = 1 The maximum number of subdivisions allowed has been achieved. One can allow more
* subdivisions by increasing the value of m_maxSubintervals. However, if this
* yields no improvement it is advised to analyze the integrand in order to
* determine the integration difficulaties. If the position of a local difficulty
* can be determined, (i.e. singularity or discontinuity within the interval), one
* will probably gain from splitting up the interval at this point and calling the
* integrator on the subranges. If possible, an appropriate special-purpose
* integrator should be used which is designed for handling the type of difficulty
* involved.
* errorCode = 2 The occurrence of roundoff error is detected, preventing the requested tolerance
* from being achieved.
* errorCode = 3 Extremely bad integrand behaviour occurs at points in the integration interval.
* errorCode = 4 Roundoff error on extrapolation
* errorCode = 5 Divergent integral (or very slowly convergent integral)
* errorCode = 6 The input is invalid, because (desiredAbsoluteError <= 0 and
* desiredRealtiveError < 50 * relativeMachineAccuracy, or
* m_maxSubintervals < 1.
* errorCode = 7 Applies to (D)QAWF only - limiting number of cycles has been attained
*
* \todo make relativeMachineAccuracy a member variable.
*/
DenseIndex m_errorCode;
/**
* \brief The number of subintervals actually produced in the subdivision process.
*/
DenseIndex m_numSubintervals;
};
}
#endif // EIGEN_INTEGRATOR_H
You can’t perform that action at this time.