diff --git a/src/function.rs b/src/function.rs index 7d7a238..59c82a5 100644 --- a/src/function.rs +++ b/src/function.rs @@ -1,7 +1,7 @@ #![allow(clippy::too_many_arguments)] // Clippy, shut #[allow(unused_imports)] -use crate::misc::debug_log; +use crate::misc::{debug_log, SteppedVector}; use eframe::egui::{ plot::{BarChart, Line, Value, Values}, @@ -104,20 +104,17 @@ impl Function { let resolution: f64 = self.pixel_width as f64 / (max_x.abs() + min_x.abs()); let back_cache = self.back_cache.as_ref().unwrap(); - let x_data: Vec = back_cache.iter().map(|ele| ele.x).collect(); + let x_data: SteppedVector = back_cache + .iter() + .map(|ele| ele.x) + .collect::>() + .into(); self.back_cache = Some( (0..=self.pixel_width) .map(|x| (x as f64 / resolution as f64) + min_x) .map(|x| { - // If x is outside of previous bounds, just go ahead and just skip searching for the index - if (x < self.min_x) | (self.max_x < x) { - return Value::new(x, self.run_func(x)); - } - - let i_option = x_data.iter().position(|&r| r == x); // Optimize this later, this could be done much much better, but tbh it doesn't matter that much as the program is already super fast - - if let Some(i) = i_option { + if let Some(i) = x_data.get_index(x) { back_cache[i] } else { Value::new(x, self.run_func(x)) @@ -149,22 +146,19 @@ impl Function { self.back_cache.as_ref().unwrap().clone() })); - match self.integral { + let front_bars = match self.integral { true => { - let front_bars: (BarChart, f64) = { - if self.front_cache.is_none() { - let (data, area) = self.integral_rectangles(); - self.front_cache = - Some((data.iter().map(|(x, y)| Bar::new(*x, *y)).collect(), area)); - } - let cache = self.front_cache.as_ref().unwrap(); - (BarChart::new(cache.0.clone()), cache.1) - }; - - (back_values, Some(front_bars)) + if self.front_cache.is_none() { + let (data, area) = self.integral_rectangles(); + self.front_cache = + Some((data.iter().map(|(x, y)| Bar::new(*x, *y)).collect(), area)); + } + let cache = self.front_cache.as_ref().unwrap(); + Some((BarChart::new(cache.0.clone()), cache.1)) } - false => (back_values, None), - } + false => None, + }; + (back_values, front_bars) } // Creates and does the math for creating all the rectangles under the graph diff --git a/src/lib.rs b/src/lib.rs index dfa435c..ab5a12a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #![allow(clippy::unused_unit)] // Fixes clippy keep complaining about wasm_bindgen #![feature(const_mut_refs)] +#![feature(total_cmp)] mod egui_app; mod function; diff --git a/src/main.rs b/src/main.rs index a30b0f5..99b1fae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,6 @@ #![feature(const_mut_refs)] +#![feature(total_cmp)] + mod egui_app; mod function; mod misc; diff --git a/src/misc.rs b/src/misc.rs index af6bb8b..21db1c2 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -135,6 +135,57 @@ pub fn test_func(function_string: String) -> Option { None } +pub struct SteppedVector { + data: Vec, // Assumes data is sorted from min to maximum + min: f64, + max: f64, + step: f64, +} + +impl SteppedVector { + pub fn get_index(&self, x: f64) -> Option { + if (x > self.max) | (self.min > x) { + return None; + } + + // Should work.... + let possible_i = ((x + self.min) / self.step) as usize; + if self.data[possible_i] == x { + return Some(possible_i); + } else if (x >= self.min) && (self.max >= x) { + panic!("possible_i did not result in a possible value, but x is in range"); + // Panic in case (no clue how this would happen). I may remove this check later. + } + + // Not really needed as the above code should handle everything + /* + for (i, ele) in self.data.iter().enumerate() { + if ele > &x { + return None; + } else if &x == ele { + return Some(i); + } + } + */ + None + } +} + +impl From> for SteppedVector { + // Note: input `data` is assumed to be sorted from min to max + fn from(data: Vec) -> SteppedVector { + let max = data[0]; + let min = data[data.len() - 1]; + let step = (max - min).abs() / ((data.len() - 1) as f64); + SteppedVector { + data, + min, + max, + step, + } + } +} + // Rounds f64 to specific number of digits pub fn digits_precision(x: f64, digits: usize) -> f64 { let large_number: f64 = 10.0_f64.powf(digits as f64);