diff --git a/TODO.md b/TODO.md index a38f48e..8bb1a99 100644 --- a/TODO.md +++ b/TODO.md @@ -17,4 +17,6 @@ 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) -10. Update function tests \ No newline at end of file +10. Update function tests +11. rewrite FunctionEntry to move more information and handling to egui_app (such as config changes) +12. dynamically adjust newton iterations and resolution of graph based on performance and if the machine is lagging \ No newline at end of file diff --git a/src/egui_app.rs b/src/egui_app.rs index a818b6f..0f7f765 100644 --- a/src/egui_app.rs +++ b/src/egui_app.rs @@ -263,6 +263,10 @@ struct AppSettings { // Stores whether or not dark mode is enabled pub dark_mode: bool, + + pub extrema: bool, + + pub roots: bool, } impl Default for AppSettings { @@ -276,6 +280,8 @@ impl Default for AppSettings { integral_max_x: DEFAULT_MAX_X, integral_num: DEFAULT_INTEGRAL_NUM, dark_mode: true, + extrema: true, + roots: true, } } } @@ -323,6 +329,29 @@ impl MathApp { ui.selectable_value(&mut self.settings.sum, RiemannSum::Right, "Right"); }); + let mut extrema_toggled: bool = false; + let mut roots_toggled: bool = false; + ui.horizontal(|ui| { + extrema_toggled = ui + .add(Button::new("Extrema")) + .on_hover_text(match self.settings.extrema { + true => "Disable Displaying Extrema", + false => "Display Extrema", + }) + .clicked(); + + roots_toggled = ui + .add(Button::new("Roots")) + .on_hover_text(match self.settings.roots { + true => "Disable Displaying Roots", + false => "Display Roots", + }) + .clicked(); + }); + + self.settings.extrema.bitxor_assign(extrema_toggled); + self.settings.roots.bitxor_assign(roots_toggled); + let min_x_old = self.settings.integral_min_x; let min_x_changed = ui .add( @@ -359,6 +388,12 @@ impl MathApp { ) .changed(); + let configs_changed = max_x_changed + | min_x_changed + | integral_num_changed + | roots_toggled + | extrema_toggled; + let functions_len = self.functions.len(); let mut remove_i: Option = None; for (i, function) in self.functions.iter_mut().enumerate() { @@ -405,11 +440,9 @@ impl MathApp { }); let proc_func_str = process_func_str(self.func_strs[i].clone()); - if integral_toggle + if configs_changed + | integral_toggle | derivative_toggle - | max_x_changed - | min_x_changed - | integral_num_changed | (proc_func_str != function.get_func_str()) | self.last_error.iter().any(|ele| ele.0 == i) { @@ -434,6 +467,8 @@ impl MathApp { Some(self.settings.integral_max_x), Some(self.settings.integral_num), Some(self.settings.sum), + self.settings.extrema, + self.settings.roots, ); self.last_error = self .last_error diff --git a/src/function.rs b/src/function.rs index 9edf800..3ce972c 100644 --- a/src/function.rs +++ b/src/function.rs @@ -42,6 +42,8 @@ pub struct FunctionEntry { integral_max_x: f64, integral_num: usize, sum: RiemannSum, + roots: bool, + extrema: bool, } // How many times should newton's method iterate? @@ -63,12 +65,15 @@ impl FunctionEntry { integral_max_x: f64::NAN, integral_num: 0, sum: DEFAULT_RIEMANN, + roots: true, + extrema: true, } } pub fn update( &mut self, func_str: String, integral: bool, derivative: bool, integral_min_x: Option, integral_max_x: Option, integral_num: Option, sum: Option, + extrema: bool, roots: bool, ) { // If the function string changes, just wipe and restart from scratch if func_str != self.func_str { @@ -79,6 +84,8 @@ impl FunctionEntry { self.derivative = derivative; self.integral = integral; + self.extrema = extrema; + self.roots = roots; // Makes sure proper arguments are passed when integral is enabled if integral @@ -289,7 +296,14 @@ impl FunctionEntry { continue; } - if last_ele.unwrap().y.signum() != ele.y.signum() { + let last_ele_signum = last_ele.unwrap().y.signum(); + let ele_signum = ele.y.signum(); + + if last_ele_signum.is_nan() | ele_signum.is_nan() { + continue; + } + + if last_ele_signum != ele_signum { // Do 50 iterations of newton's method, should be more than accurate let x = { let mut x1: f64 = last_ele.unwrap().x; @@ -317,7 +331,14 @@ impl FunctionEntry { continue; } - if last_ele.unwrap().y.signum() != ele.y.signum() { + let last_ele_signum = last_ele.unwrap().y.signum(); + let ele_signum = ele.y.signum(); + + if last_ele_signum.is_nan() | ele_signum.is_nan() { + continue; + } + + if last_ele_signum != ele_signum { // Do 50 iterations of newton's method, should be more than accurate let x = { let mut x1: f64 = last_ele.unwrap().x; @@ -341,8 +362,18 @@ impl FunctionEntry { self.output.back = Some(back_values); self.output.integral = integral; self.output.derivative = derivative; - self.extrema(); - self.roots(); + + if self.extrema { + self.extrema(); + } else { + self.output.extrema = None; + } + + if self.roots { + self.roots(); + } else { + self.output.roots = None; + } self.output.display( plot_ui, diff --git a/src/parsing.rs b/src/parsing.rs index 2e1edb9..eef40eb 100644 --- a/src/parsing.rs +++ b/src/parsing.rs @@ -1,7 +1,7 @@ use exmex::prelude::*; lazy_static::lazy_static! { - static ref EMPTY_FUNCTION: FlatEx = exmex::parse::("0").unwrap(); + static ref EMPTY_FUNCTION: FlatEx = exmex::parse::("0/0").unwrap(); } #[derive(Clone)]