numerics_rs/root_finding/
builder.rs1use super::*;
2pub struct RootFinderBuilder<'a> {
4 method: RootFindingMethod,
5 initial_guess: Option<f64>,
6 boundaries: Option<(f64, f64)>,
7 tolerance: Option<f64>,
8 max_iterations: Option<usize>,
9 log_convergence: Option<bool>,
10 function: Option<&'a F>, derivative: Option<&'a F>, }
13
14impl<'a> RootFinderBuilder<'a> {
15 pub fn new(method: RootFindingMethod) -> Self {
17 Self {
18 method,
19 initial_guess: None,
20 boundaries: None,
21 tolerance: None,
22 max_iterations: None,
23 log_convergence: None,
24 function: None,
25 derivative: None,
26 }
27 }
28
29 pub fn initial_guess(mut self, guess: f64) -> Self {
31 self.initial_guess = Some(guess);
32 self
33 }
34
35 pub fn boundaries(mut self, x0: f64, x1: f64) -> Self {
37 self.boundaries = Some((x0, x1));
38 self
39 }
40
41 pub fn tolerance(mut self, tol: f64) -> Self {
43 self.tolerance = Some(tol);
44 self
45 }
46
47 pub fn max_iterations(mut self, max: usize) -> Self {
49 self.max_iterations = Some(max);
50 self
51 }
52
53 pub fn log_convergence(mut self, log: bool) -> Self {
55 self.log_convergence = Some(log);
56 self
57 }
58
59 pub fn function(mut self, function: &'a F) -> Self {
61 self.function = Some(function);
62 self
63 }
64
65 pub fn derivative(mut self, derivative: &'a F) -> Self {
67 self.derivative = Some(derivative);
68 self
69 }
70
71 pub fn build(self) -> Result<RootFindingIterationDecorator<'a>, String> {
73 let function = self.function.ok_or("Function must be specified")?;
74 let tolerance = self.tolerance.ok_or("Tolerance must be specified.")?;
75 let max_iterations = self
76 .max_iterations
77 .ok_or("Max iterations must be specified.")?;
78 let log_convergence = self.log_convergence.unwrap_or(false);
79 let rf: Result<Box<dyn RootFinder + 'a>, String> = match self.method {
81 RootFindingMethod::NewtonRaphson => {
82 let initial_guess = self
84 .initial_guess
85 .ok_or("Initial guess must be specified")?;
86
87 Ok(Box::new(newton_raphson::NewtonRaphsonRootFinder {
88 x0: initial_guess,
89 tolerance,
90 }))
91 }
92 RootFindingMethod::Secant => {
93 let boundaries = self
94 .boundaries
95 .ok_or("Derivative must be specified for Secant method.")?;
96
97 Ok(Box::new(secant::SecantRootFinder {
98 x0: boundaries.0,
99 x1: boundaries.1,
100 x2: f64::NAN,
101 tolerance,
102 }))
103 }
104 RootFindingMethod::Bisection => {
105 let boundaries = self
106 .boundaries
107 .ok_or("Derivative must be specified for Bisection method.")?;
108
109 Ok(Box::new(bisection::BisectionRootFinder {
110 x0: boundaries.0,
111 x1: boundaries.1,
112 tolerance,
113 search_left: true,
114 }))
115 }
116 _ => Err("Unsupported method in this example.".to_string()),
118 };
119 Ok(RootFindingIterationDecorator::new(
120 function,
121 self.derivative,
122 rf?,
123 max_iterations,
124 log_convergence,
125 ))
126 }
127}