scivex_optim/roots/mod.rs
1//! Root-finding algorithms for scalar functions.
2//!
3//! Find `x` such that `f(x) = 0`.
4
5mod bisection;
6mod brent;
7mod newton;
8
9pub use bisection::bisection;
10pub use brent::brent_root;
11pub use newton::newton;
12
13use scivex_core::Float;
14
15/// Result of a root-finding algorithm.
16///
17/// # Examples
18///
19/// ```
20/// # use scivex_optim::prelude::*;
21/// let result = bisection(|x: f64| x * x - 2.0, 1.0, 2.0, &RootOptions::default()).unwrap();
22/// assert!(result.converged);
23/// assert!((result.root - std::f64::consts::SQRT_2).abs() < 1e-10);
24/// ```
25#[cfg_attr(
26 feature = "serde-support",
27 derive(serde::Serialize, serde::Deserialize)
28)]
29#[derive(Debug, Clone)]
30pub struct RootResult<T: Float> {
31 /// The estimated root.
32 pub root: T,
33 /// The function value at the root: `f(root)`.
34 pub f_root: T,
35 /// Number of iterations performed.
36 pub iterations: usize,
37 /// Whether the algorithm converged within tolerances.
38 pub converged: bool,
39}
40
41/// Options controlling root-finding algorithms.
42///
43/// # Examples
44///
45/// ```
46/// # use scivex_optim::prelude::*;
47/// let opts = RootOptions {
48/// xtol: 1e-8,
49/// ftol: 1e-8,
50/// max_iter: 50,
51/// };
52/// let result = bisection(|x: f64| x * x - 2.0, 1.0, 2.0, &opts).unwrap();
53/// assert!(result.converged);
54/// ```
55#[cfg_attr(
56 feature = "serde-support",
57 derive(serde::Serialize, serde::Deserialize)
58)]
59#[derive(Debug, Clone)]
60pub struct RootOptions<T: Float> {
61 /// Tolerance on the root position.
62 pub xtol: T,
63 /// Tolerance on the function value.
64 pub ftol: T,
65 /// Maximum number of iterations.
66 pub max_iter: usize,
67}
68
69impl<T: Float> Default for RootOptions<T> {
70 fn default() -> Self {
71 Self {
72 xtol: T::from_f64(1e-12),
73 ftol: T::from_f64(1e-12),
74 max_iter: 100,
75 }
76 }
77}