diff --git a/Cargo.toml b/Cargo.toml index a157ec9..b448b24 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,10 @@ repository = "https://github.com/Titaniumtown/YTBN-Graphing-Software" [lib] crate-type = ["cdylib"] +[features] +threading = ["async-lock", "rayon"] + + [profile.release] debug = false codegen-units = 1 @@ -48,7 +52,9 @@ phf_codegen = "0.10.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] instant = { version = "0.1.12" } tracing-subscriber = "0.3.9" -rayon = { git = "https://github.com/rayon-rs/rayon.git" } +rayon = { git = "https://github.com/rayon-rs/rayon.git", optional = true } +async-lock = { git = "https://github.com/smol-rs/async-lock.git", optional = true } + [target.'cfg(target_arch = "wasm32")'.dependencies] instant = { version = "0.1.12", features = ["wasm-bindgen"] } diff --git a/src/egui_app.rs b/src/egui_app.rs index 0c61b2e..83cff40 100644 --- a/src/egui_app.rs +++ b/src/egui_app.rs @@ -13,7 +13,7 @@ use epi::Frame; use instant::Duration; use std::{collections::BTreeMap, io::Read, ops::BitXorAssign, str}; -#[cfg(not(target_arch = "wasm32"))] +#[cfg(threading)] use rayon::iter::{IndexedParallelIterator, ParallelIterator}; // Stores data loaded from files diff --git a/src/function.rs b/src/function.rs index 38984ea..8e29d5e 100644 --- a/src/function.rs +++ b/src/function.rs @@ -11,7 +11,7 @@ use egui::{ use epaint::Color32; use std::fmt::{self, Debug}; -#[cfg(not(target_arch = "wasm32"))] +#[cfg(threading)] use rayon::iter::ParallelIterator; /// Represents the possible variations of Riemann Sums @@ -94,6 +94,20 @@ impl FunctionEntry { self.integral = integral; } + fn get_sum_func(&self, sum: Riemann) -> FunctionHelper { + match sum { + Riemann::Left => { + FunctionHelper::new(|left_x: f64, _: f64| -> f64 { self.function.get(left_x) }) + } + Riemann::Right => { + FunctionHelper::new(|_: f64, right_x: f64| -> f64 { self.function.get(right_x) }) + } + Riemann::Middle => FunctionHelper::new(|left_x: f64, right_x: f64| -> f64 { + (self.function.get(left_x) + self.function.get(right_x)) / 2.0 + }), + } + } + /// Creates and does the math for creating all the rectangles under the /// graph fn integral_rectangles( @@ -107,6 +121,8 @@ impl FunctionEntry { let step = (integral_min_x - integral_max_x).abs() / (*integral_num as f64); + let sum_func = self.get_sum_func(*sum); + let data2: Vec<(f64, f64)> = dyn_iter(&step_helper(*integral_num, &integral_min_x, &step)) .map(|x| { let step_offset = step * x.signum(); // store the offset here so it doesn't have to be calculated multiple times @@ -117,18 +133,13 @@ impl FunctionEntry { false => (x2, *x), }; - let y = match sum { - Riemann::Left => self.function.get(left_x), - Riemann::Right => self.function.get(right_x), - Riemann::Middle => { - (self.function.get(left_x) + self.function.get(right_x)) / 2.0 - } - }; + let y = sum_func.get(left_x, right_x); (x + (step_offset / 2.0), y) }) .filter(|(_, y)| !y.is_nan()) .collect(); + let area = data2.iter().map(|(_, y)| y * step).sum(); (data2, area) diff --git a/src/misc.rs b/src/misc.rs index 3e58490..ab81b76 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -2,10 +2,10 @@ use eframe::egui::plot::{Line, Points, Value as EguiValue, Values}; use itertools::Itertools; use serde_json::Value as JsonValue; -#[cfg(not(target_arch = "wasm32"))] +#[cfg(threading)] use rayon::prelude::*; -#[cfg(target_arch = "wasm32")] +#[cfg(not(threading))] pub fn dyn_iter<'a, T>(input: &'a Vec) -> impl Iterator where &'a [T]: IntoIterator, @@ -13,7 +13,7 @@ where input.iter() } -#[cfg(not(target_arch = "wasm32"))] +#[cfg(threading)] pub fn dyn_iter<'a, I>(input: &'a I) -> <&'a I as IntoParallelIterator>::Iter where &'a I: IntoParallelIterator, @@ -21,7 +21,7 @@ where input.par_iter() } -#[cfg(target_arch = "wasm32")] +#[cfg(not(threading))] pub fn dyn_mut_iter<'a, T>(input: &'a mut Vec) -> impl Iterator where &'a mut [T]: IntoIterator, @@ -29,7 +29,7 @@ where input.iter_mut() } -#[cfg(not(target_arch = "wasm32"))] +#[cfg(threading)] pub fn dyn_mut_iter<'a, I>(input: &'a mut I) -> <&'a mut I as IntoParallelIterator>::Iter where &'a mut I: IntoParallelIterator, @@ -37,6 +37,35 @@ where input.par_iter_mut() } +pub struct FunctionHelper<'a> { + #[cfg(threading)] + f: async_lock::Mutex f64 + 'a + Sync + Send>>, + + #[cfg(not(threading))] + f: Box f64 + 'a>, +} + +impl<'a> FunctionHelper<'a> { + #[cfg(threading)] + pub fn new(f: impl Fn(f64, f64) -> f64 + 'a) -> FunctionHelper<'a> { + FunctionHelper { + f: async_lock::Mutex::new(Box::new(f)), + } + } + + pub fn new(f: impl Fn(f64, f64) -> f64 + 'a) -> FunctionHelper<'a> { + FunctionHelper { f: Box::new(f) } + } + + // pub fn get(&self, x: f64, x1: f64) -> f64 { (self.f.lock())(x, x1) } + + #[cfg(threading)] + pub async fn get(&self, x: f64, x1: f64) -> f64 { (self.f.lock().await)(x, x1) } + + #[cfg(not(threading))] + pub fn get(&self, x: f64, x1: f64) -> f64 { (self.f)(x, x1) } +} + pub trait VecValueToTuple { fn to_tuple(&self) -> Vec<(f64, f64)>; }