From 232f470ce1d7ed445ec4a053b79b17cda857f405 Mon Sep 17 00:00:00 2001 From: Simon Gardling Date: Wed, 9 Mar 2022 21:15:12 -0500 Subject: [PATCH] roots --- TODO.md | 4 ++-- src/function.rs | 28 ++++++++++++++++++++++++++++ src/function_output.rs | 12 ++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/TODO.md b/TODO.md index 833eb29..6b829de 100644 --- a/TODO.md +++ b/TODO.md @@ -8,10 +8,10 @@ - Non `y=` functions. 3. Smart display of graph - Display of intersections between functions - - Display of roots 4. Fix integral line 5. re-add euler's number (well it works if you use capital e like `E^x`) 6. allow constants in min/max integral input (like pi or euler's number) 7. sliding values for functions (like a user-interactable slider that adjusts a variable in the function, like desmos) 8. Keybinds -9. nth derivative support (again) \ No newline at end of file +9. nth derivative support (again) +10. add configs for toggling display of roots and extrema \ No newline at end of file diff --git a/src/function.rs b/src/function.rs index 90c1783..33ddf16 100644 --- a/src/function.rs +++ b/src/function.rs @@ -276,6 +276,33 @@ impl FunctionEntry { self } + // Finds roots + fn roots(&mut self) { + let mut root_list: Vec = Vec::new(); + let mut last_ele: Option = None; + for ele in self.output.back.as_ref().unwrap().iter() { + if last_ele.is_none() { + last_ele = Some(*ele); + continue; + } + + if last_ele.unwrap().y.signum() != ele.y.signum() { + // Do 10 iterations of newton's method, should be more than accurate + let x = { + let mut x1: f64 = last_ele.unwrap().x; + for _ in 0..10 { + x1 = last_ele.unwrap().x + - (self.function.get(x1) / self.function.derivative(x1)) + } + x1 + }; + root_list.push(Value::new(x, self.function.get(x))); + } + last_ele = Some(*ele); + } + self.output.roots = Some(root_list); + } + // Finds extrema fn extrema(&mut self) { let mut extrama_list: Vec = Vec::new(); @@ -309,6 +336,7 @@ impl FunctionEntry { self.output.integral = integral; self.output.derivative = derivative; self.extrema(); + self.roots(); self.output.display( plot_ui, diff --git a/src/function_output.rs b/src/function_output.rs index 33e34c6..3f0c2a5 100644 --- a/src/function_output.rs +++ b/src/function_output.rs @@ -14,6 +14,7 @@ pub struct FunctionOutput { pub(crate) integral: Option<(Vec, f64)>, pub(crate) derivative: Option>, pub(crate) extrema: Option>, + pub(crate) roots: Option>, } impl FunctionOutput { @@ -23,6 +24,7 @@ impl FunctionOutput { integral: None, derivative: None, extrema: None, + roots: None, } } @@ -31,6 +33,7 @@ impl FunctionOutput { self.integral = None; self.derivative = None; self.extrema = None; + self.roots = None; } pub fn invalidate_back(&mut self) { self.back = None; } @@ -68,6 +71,15 @@ impl FunctionOutput { ); } + if let Some(roots_data) = self.roots.clone() { + plot_ui.points( + Points::new(Values::from_values(roots_data)) + .color(Color32::LIGHT_BLUE) + .name("Root") + .radius(5.0), + ); + } + if let Some(integral_data) = self.integral.clone() { plot_ui.bar_chart( BarChart::new(integral_data.0)