In this exercise you have to implement a subroutine which integrates a
given function f from a to b with
the absolute accuracy acc and realtive accuracy
eps. The subroutine should return the estimate of the
integral, Q, and the estimate of the error,
err, such that the following condition is satisfied:
| Q - ∫ab f(x)dx | < acc + |Q|*eps .
The subroutine might also return the estimate of the error
err ≈ | Q - ∫ab f(x)dx |
double my_integrator(double f(double), double a, double b, double acc, double eps, double *err)
{
Q = my_estimate_of_the_integral;
*err = my_estimate_of_the_error; /* should be smaller than acc+|Q|*eps */
return Q;
}
double
*err.
main function could then call the integrator as
double my_function(double x){return x*x;}
int main (void)
{
double a=0, b=1, err, acc=0.0001, eps=0.0001;
double Q = my_integrator(my_function, a, b, acc, eps, &err);
printf("integral=%lg, error=%lg\n",Q,err);
return 0;
}
my_function inside the main function (a
technique called 'nested functions') where it can inherit all variables
from the main-function scope.
In C++ language — in addition to the C-interface where
the user supplies the pointer to their function and the pointer
to their err variable—one can also use the
std::function object; and pass the err variable
by reference:
double my_CXX_integrator(
std::function<double(double)> f,
double a, double b, double acc, double eps, double& err)
public static interface integrand{ public double call(double x); }
Exercises
(6 points) Recursive adaptive integrators
f on a given interval
[a,b] with the required absolute, acc, or
relative, eps, accuracy goals.
∫01
dx 4√(1-(1-x)2) = π
with as many significant digits as you can and estimate the number of
integrand evaluations.
Compare with library routines (for example, gsl_integration_qags).
(3 points)
Generalize your integrators such that they can accept infinite limits.
An infinite limit integral can be converted by a variable transformation
(see lecture notes) into a finite limit integral, which can then be
evaluated by your ordinary integrator.
In C/C++ infinities are defined in math.h by macros
INFINITY and ‑INFINITY
and can be identified by the macro isinf. You might need to use the
-std=c99 switch.
Test your implementation on some (converging) infitine limit integrals.
(1 point)
∫-11 f(x)dx = ∫0π f(cos(θ))sinθdθ
Check whether there is any improvements on integrals with integrable divergencies at the ends of the intervals.
Compare with your ODE driver:
Q=∫abf(x)dx
can be
reformulated as an ordinary differential equation,
y'=f(x), y(a)=0, Q=y(b),
which can be solved with your adaptive ODE
solver. Pick an interesing f(x) and compare the effectiveness of
your ODE drivers with your adaptive integrators.
(0 point) Singular integrands
∫01
dx (ln(x)/√(x)) = -4
with acc=eps=0.001 and estimate the number of integrand
evaluations with you open-adaptive integrator from exercise A and the
present integrator.