From cfd245f82c913a618ff949d72b83b48e572b930f Mon Sep 17 00:00:00 2001 From: Simon Gardling Date: Mon, 16 May 2022 10:23:08 -0400 Subject: [PATCH] refactor handling of {min,max}_x --- src/function_entry.rs | 37 +++++++++++++++---------------------- src/math_app.rs | 19 +++++++++++++++---- tests/function.rs | 7 +++++-- 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/function_entry.rs b/src/function_entry.rs index 0df4049..7253307 100644 --- a/src/function_entry.rs +++ b/src/function_entry.rs @@ -41,10 +41,6 @@ pub struct FunctionEntry { /// Stores a function string (that hasn't been processed via `process_func_str`) to display to the user raw_func_str: String, - /// Minimum and Maximum values of what do display - min_x: f64, - max_x: f64, - /// If calculating/displayingintegrals are enabled pub integral: bool, @@ -127,8 +123,6 @@ impl FunctionEntry { pub const EMPTY: FunctionEntry = FunctionEntry { function: BackingFunction::EMPTY, raw_func_str: String::new(), - min_x: -1.0, - max_x: 1.0, integral: false, derivative: false, nth_derviative: false, @@ -249,19 +243,20 @@ impl FunctionEntry { } /// Helps with processing newton's method depending on level of derivative - fn newtons_method_helper(&self, threshold: &f64, derivative_level: usize) -> Vec { - let range = self.min_x..self.max_x; + fn newtons_method_helper( + &self, threshold: &f64, derivative_level: usize, range: &std::ops::Range, + ) -> Vec { let newtons_method_output: Vec = match derivative_level { 0 => newtons_method_helper( threshold, - &range, + range, self.back_data.as_slice(), &|x: f64| self.function.get(x), &|x: f64| self.function.get_derivative_1(x), ), 1 => newtons_method_helper( threshold, - &range, + range, self.derivative_data.as_slice(), &|x: f64| self.function.get_derivative_1(x), &|x: f64| self.function.get_derivative_2(x), @@ -276,7 +271,8 @@ impl FunctionEntry { /// Does the calculations and stores results in `self` pub fn calculate( - &mut self, min_x: &f64, max_x: &f64, width_changed: bool, settings: &AppSettings, + &mut self, min_x: &f64, max_x: &f64, width_changed: bool, min_max_changed: bool, + settings: &AppSettings, ) { if self.test_result.is_some() { return; @@ -293,12 +289,8 @@ impl FunctionEntry { } let mut partial_regen = false; - let min_max_changed = (min_x != &self.min_x) | (max_x != &self.max_x); - let derivative_required = settings.do_extrema | self.derivative; - self.min_x = *min_x; - self.max_x = *max_x; if width_changed { self.invalidate_back(); self.invalidate_derivative(); @@ -425,15 +417,16 @@ impl FunctionEntry { } let threshold: f64 = resolution / 2.0; + let x_range = settings.min_x..settings.max_x; // Calculates extrema if settings.do_extrema && (min_max_changed | self.extrema_data.is_empty()) { - self.extrema_data = self.newtons_method_helper(&threshold, 1); + self.extrema_data = self.newtons_method_helper(&threshold, 1, &x_range); } // Calculates roots if settings.do_roots && (min_max_changed | self.root_data.is_empty()) { - self.root_data = self.newtons_method_helper(&threshold, 0); + self.root_data = self.newtons_method_helper(&threshold, 0, &x_range); } } @@ -450,7 +443,7 @@ impl FunctionEntry { let step = (settings.integral_min_x - settings.integral_max_x).abs() / (settings.integral_num as f64); - let resolution = (self.min_x - self.max_x).abs() / (settings.plot_width as f64); + let resolution = (settings.min_x - settings.max_x).abs() / (settings.plot_width as f64); // Plot back data if !self.back_data.is_empty() { @@ -566,7 +559,7 @@ impl FunctionEntry { derivative_target: Vec<(f64, f64)>, area_target: f64, min_x: f64, max_x: f64, ) { { - self.calculate(&min_x, &max_x, true, &settings); + self.calculate(&min_x, &max_x, true, true, &settings); assert!(!self.back_data.is_empty()); assert_eq!(self.back_data.len(), settings.plot_width + 1); let back_vec_tuple = self.back_data.to_tuple(); @@ -586,7 +579,7 @@ impl FunctionEntry { } { - self.calculate(&(min_x + 1.0), &(max_x + 1.0), true, &settings); + self.calculate(&(min_x + 1.0), &(max_x + 1.0), true, true, &settings); assert_eq!( self.derivative_data @@ -626,7 +619,7 @@ impl FunctionEntry { } { - self.calculate(&(min_x - 1.0), &(max_x - 1.0), true, &settings); + self.calculate(&(min_x - 1.0), &(max_x - 1.0), true, true, &settings); assert_eq!( self.derivative_data @@ -682,7 +675,7 @@ impl FunctionEntry { assert!(self.extrema_data.is_empty()); assert!(self.derivative_data.is_empty()); - self.calculate(&min_x, &max_x, true, &settings); + self.calculate(&min_x, &max_x, true, true, &settings); assert!(!self.back_data.is_empty()); assert!(self.integral_data.is_none()); diff --git a/src/math_app.rs b/src/math_app.rs index f820b69..fc024f7 100644 --- a/src/math_app.rs +++ b/src/math_app.rs @@ -29,6 +29,10 @@ pub struct AppSettings { /// Max value for calculating an pub integral_max_x: f64, + pub min_x: f64, + + pub max_x: f64, + /// Stores whether or not integral settings have changed pub integral_changed: bool, @@ -52,6 +56,8 @@ impl const Default for AppSettings { riemann_sum: DEFAULT_RIEMANN, integral_min_x: DEFAULT_MIN_X, integral_max_x: DEFAULT_MAX_X, + min_x: 0.0, + max_x: 0.0, integral_changed: true, integral_num: DEFAULT_INTEGRAL_NUM, do_extrema: true, @@ -577,14 +583,19 @@ impl App for MathApp { .legend(egui::plot::Legend::default()) .show(ui, |plot_ui| { let bounds = plot_ui.plot_bounds(); - let minx_bounds: f64 = bounds.min()[0]; - let maxx_bounds: f64 = bounds.max()[0]; + let min_x: f64 = bounds.min()[0]; + let max_x: f64 = bounds.max()[0]; + let min_max_changed = + (min_x != self.settings.min_x) | (max_x != self.settings.max_x); + self.settings.min_x = min_x; + self.settings.max_x = max_x; dyn_mut_iter(self.functions.get_entries_mut()).for_each(|(_, function)| { function.calculate( - &minx_bounds, - &maxx_bounds, + &min_x, + &max_x, width_changed, + min_max_changed, &self.settings, ) }); diff --git a/tests/function.rs b/tests/function.rs index bd03b63..1ac4fca 100644 --- a/tests/function.rs +++ b/tests/function.rs @@ -1,12 +1,15 @@ use ytbn_graphing_software::{AppSettings, FunctionEntry, Riemann}; fn app_settings_constructor( - sum: Riemann, integral_min_x: f64, integral_max_x: f64, pixel_width: usize, integral_num: usize, + sum: Riemann, integral_min_x: f64, integral_max_x: f64, pixel_width: usize, + integral_num: usize, min_x: f64, max_x: f64, ) -> AppSettings { AppSettings { riemann_sum: sum, integral_min_x, integral_max_x, + min_x, + max_x, integral_changed: true, integral_num, do_extrema: false, @@ -44,7 +47,7 @@ static DERIVATIVE_TARGET: [(f64, f64); 11] = [ ]; fn do_test(sum: Riemann, area_target: f64) { - let settings = app_settings_constructor(sum, -1.0, 1.0, 10, 10); + let settings = app_settings_constructor(sum, -1.0, 1.0, 10, 10, -1.0, 1.0); let mut function = FunctionEntry::EMPTY; function.update_string("x^2");