Skip to main content

toms748

Function toms748 

Source
pub fn toms748<T, F, R>(
    f: F,
    a: T,
    b: T,
) -> Toms748<T, F, T::DefaultTerminate, R::Error>
where T: OrdField, F: FnMut(T) -> R, R: FloatOrError<T>,
Expand description

Find a root of the function f on the interval [a, b], with finite bounds assuming f(a) and f(b) have opposite signs and f is continuous using Algorithm 748 by Alefeld, Potro and Shi.

Trying to compute the root when f(a) and f(b) do not have opposite signs will return the error Error::NoSignChange. If the function is not continuous, root-finding methods will still compute a small interval at the boundary of which f changes sign and return a point in it; Toms748::bracket and Toms748::root_mut return the small interval. This algorithm works best when the function is 4 times continuously differentiable on [ab] and the root is simple.

The default stopping criterion for f64 (resp. f32) is given by Tol with rtol: 4. * f64::EPSILON, and atol: 2e-12 (resp. rtol:4. * f32::EPSILON and atol: 2e-6). The Terminate stopping criterion is |a - b| ≤ rtol · max{|a|, |b|} + atol.

The default maximum number of iterations is 100 and reaching that many iteration simply returns the root (you can report that as an error with the option maxiter_err(true)). The maximum number of iterations can be changed using the maxiter method. See the methods of Toms748 for more options.

§Examples

use root1d::toms748;
let f = |x| x * x - 2.;
assert!((toms748(f, 0., 2.).atol(0.).rtol(1e-10).root()?
         - 2f64.sqrt()).abs() < 1e-15);

The function we apply the Toms748 algorithm to may also return an error in which case the bisection stops and returns the error Error::Fun.

use root1d::toms748;
let f = |a: f64| toms748(|x| x*x - a, 0., a.max(1.)).root();
assert!((toms748(|a| f(a).and_then(|fa| Ok(fa - 2.)), 1., 5.).root()?
        - 4f64).abs() < 1e-15);

If you want to use ? to return errors in the second closure, its error type must be known and you must help Rust with a type annotation.

use root1d::{toms748, Error};
let f = |a: f64| toms748(|x| x*x - a, 0., a.max(1.)).root();
let g = |a| -> Result<_, Error<_>> { Ok(f(a)? - 2.) };
assert!((toms748(g, 1., 5.).root()? - 4f64).abs() < 1e-15);

§Reference

G. E. Alefeld, F. A. Potra, and Y. Shi, “Algorithm 748: enclosing zeros of continuous functions,” ACM Trans. Math. Softw., vol. 21, no. 3, pp. 327–344, Sep. 1995, doi: 10.1145/210089.210111.