As far as I know there are no functions of the type you are searching for in the standard library. Here is one implementation of the:
The extended trapezoidal rule.
For a fixed function f(x)
to be integrated between fixed
limits a
and b
, one can double the number of intervals in the extended trapezoidal rule without losing the benefit of previous work. The coarsest implementation of the trapezoidal rule is to average the function at its endpoints a
and b
. The first stage of refinement is to add to this average the value of the function at the halfway point. The second stage of refinement is to add the values at the 1/4
and 3/4
points.

A number of elementary quadrature algorithms involve adding
successive stages of refinement. It is convenient to encapsulate this feature in a Quadrature
structure:
struct Quadrature
{
//Abstract base class for elementary quadrature algorithms.
Int n; // Current level of refinement.
virtual Doub next() = 0;
//Returns the value of the integral at the nth stage of refinement.
//The function next() must be defined in the derived class.
};
Then the Trapzd
structure is derived from this as follows:
template<class T>
struct Trapzd: Quadrature
{
Doub a, b, s; // Limits of integration and current value of integral.
T &func;
Trapzd() { };
// func is function or functor to be integrated between limits: a and b
Trapzd(T &funcc, const Doub aa, const Doub bb)
: func(funcc), a(aa), b(bb)
{
n = 0;
}
// Returns the nth stage of refinement of the extended trapezoidal rule.
// On the first call (n = 1), the routine returns the crudest estimate
// of integral of f x / dx in [a,b]. Subsequent calls set n=2,3,... and
// improve the accuracy by adding 2n - 2 additional interior points.
Doub next()
{
Doub x, tnm, sum, del;
Int it, j;
n++;
if (n == 1)
{
return (s = 0.5 * (b-a) * (func(a) + func(b)));
}
else
{
for (it = 1, j = 1; j < n - 1; j++)
{
it <<= 1;
}
tnm = it;
// This is the spacing of the points to be added.
del = (b - a) / tnm;
x = a + 0.5 * del;
for (sum = 0.0,j = 0; j < it; j++, x += del)
{
sum += func(x);
}
// This replaces s by its refined value.
s = 0.5 * (s + (b - a) * sum / tnm);
return s;
}
}
};
Usage:
The Trapzd
structure could be used in several ways. The
simplest and crudest is to integrate a function by the extended trapezoidal rule where you know in advance the number of steps you want. If you
want 2^M + 1
, you can accomplish this by the fragment:
Ftor func; // Functor func here has no parameters.
Trapzd<Ftor> s(func, a, b);
for(j = 1 ;j <= m + 1; j++) val = s.next();
with the answer returned as val
. Here Ftor
is a functor containing the function to be integrated.
Bonus:
Much better, of course, is to refine the trapezoidal rule until some specified
degree of accuracy has been achieved. A function for this is:
template<class T>
Doub qtrap(T &func, const Doub a, const Doub b, const Doub eps = 1.0e-10)
{
// Returns the integral of the function or functor func from a to b.
// The constants EPS can be set to the desired fractional accuracy and
// JMAX so that 2 to the power JMAX-1 is the maximum allowed number of
// steps. Integration is performed by the trapezoidal rule.
const Int JMAX = 20;
Doub s, olds = 0.0; // Initial value of olds is arbitrary.
Trapzd<T> t(func, a, b);
for (Int j = 0; j < JMAX; j++)
{
s = t.next();
if (j > 5) // Avoid spurious early convergence.
{
if (abs(s - olds) < eps * abs(olds) || (s == 0.0 && olds == 0.0))
{
return s;
}
}
olds = s;
}
throw("Too many steps in routine qtrap");
}
Typedefs.
typedef double Doub; // 64 - bit floating point
typedef int Int; // 32 - bit signed integer