pub struct Adaptive<'a, I> { /* private fields */ }Expand description
An adaptive Gauss-Kronrod integrator.
The Adaptive integrator applies a Gauss-Kronrod integration Rule to approximate the
integral of a one-dimensional function. Unlike the Basic routine, the routine implemented
by Adaptive is adaptive. After the initial integration, each iteration of the routine picks
the previous integration area which has the largest error estimate and bisects this region,
updating the estimate to the integal and the total approximated error. The adaptive routine
will return the first approximation, result, to the integral which has an absolute error
smaller than the tolerance tol encoded through the Tolerance enum, where
Tolerance::Absolutespecifies absolute tolerance and returns final estimate whenerror <= tol,Tolerance::Relativespecifies a relative error and returns final estimate whenerror <= tol * abs(result),Tolerance::Eitherto return a result as soon as either the relative or absolute error bound has been satisfied.
The routine will end when either one of the tolerance conditions have been satisfied or an
error has occurred, see Error for more details.
This routine is primarily aimed towards the evaluation of integrals of relatively smooth
functions on finite integration domains that are free from singularities. If the function the
user wishes to integrate has integrable singularities and/or is defined on an infinite or
semi-infinite integration domain then the AdaptiveSingularity integrator should be
preferred. In fact, it can often be the case that the AdaptiveSingularity integrator is
generally more efficient than the Adaptive routine though this should be benchmarked on a
case-by-case basis.
§Example
Here we present a calculation of the integral, $$ I = \int_{0}^{1} x^{\alpha} \ln \frac{1}{x} dx = \frac{1}{(1+\alpha)^{2}} $$ for different values of $\alpha$.
use rint::{Integrand, Limits, Tolerance};
use rint::quadrature::{Adaptive, Basic, Rule};
use std::f64::consts::*;
struct Function1 {
alpha: f64,
}
impl Integrand for Function1 {
type Point = f64;
type Scalar = f64;
fn evaluate(&self, x: &Self::Point) -> Self::Scalar {
let alpha = self.alpha;
x.powf(alpha) * (1.0 / x).ln()
}
}
const TOL: f64 = 1.0e-12;
let tolerance = Tolerance::Relative(TOL);
let limits = Limits::new(0.0, 1.0)?;
let rule = Rule::gk31();
let max_iterations = 1000;
let alpha_values = [2.6, PI, EULER_GAMMA, LOG10_E, 100.0, PI.powi(3)];
for alpha in alpha_values {
let function = Function1 { alpha };
let integral = Adaptive::new(&function, &rule, limits, tolerance, max_iterations)?
.integrate()?;
let target = 1.0 / (1.0 + alpha).powi(2);
let result = integral.result();
let error = integral.error();
let abs_actual_error = (result - target).abs();
let tol = TOL * result.abs();
assert!(abs_actual_error < error);
assert!(error < tol);
}Implementations§
Source§impl<'a, I> Adaptive<'a, I>
impl<'a, I> Adaptive<'a, I>
Sourcepub fn new(
function: &'a I,
rule: &'a Rule,
limits: Limits,
tolerance: Tolerance,
max_iterations: usize,
) -> Result<Self, InitialisationError>
pub fn new( function: &'a I, rule: &'a Rule, limits: Limits, tolerance: Tolerance, max_iterations: usize, ) -> Result<Self, InitialisationError>
Generate a new Adaptive integrator.
Initialise an adaptive Gauss-Kronrod integrator. Arguments:
function: A user supplied function to be integrated which is something implementing theIntegrandtrait.rule: An n-point Gauss-Kronrod integrationRulelimits: The interval over which thefunctionshould be integrated,Limits.tolerance: The tolerance requested by the user. Can be either an absolute tolerance or relative tolerance. Determines the exit condition of the integration routine, seeTolerance.max_iterations: The maximum number of iterations that the adaptive routine should use to try to satisfy the requested tolerance.
§Errors
Function can return an error if it receives bad user input. This is primarily related to
using invalid values for the tolerance. The returned error is an InitialisationError.
See Tolerance and InitialisationError for more details.
Sourcepub fn integrate(
&self,
) -> Result<IntegralEstimate<I::Scalar>, IntegrationError<I::Scalar>>
pub fn integrate( &self, ) -> Result<IntegralEstimate<I::Scalar>, IntegrationError<I::Scalar>>
Integrate the function and return a IntegralEstimate integration result.
Adaptively applies the n-point Gauss-Kronrod integration Rule to the user supplied
function implementing the Integrand trait to generate an IntegralEstimate upon
successful completion.
§Errors
The error type IntegrationError will return both the error IntegrationErrorKind and
the IntegralEstimate obtained before an error was encountered. The integration routine
has several ways of failing:
-
The user supplied
Tolerancecould not be satisfied within the maximum number of iterations, seeIntegrationErrorKind::MaximumIterationsReached. -
A roundoff error was detected. Can occur when the calculated numerical error from an internal integration is smaller than the estimated roundoff, but larger than the tolerance requested by the user, or when too many successive iterations do not reasonably improve the integral value and error estimate, see
IntegrationErrorKind::RoundoffErrorDetected. -
Bisection of the highest error region into two subregions results in subregions with integraion limits that are too small, see
IntegrationErrorKind::BadIntegrandBehaviour. -
An error is encountered when initialising the integration workspace. This is an internal error, which should not occur in user code, see
IntegrationErrorKind::UninitialisedWorkspace.