fmt
This commit is contained in:
parent
32e4699c5f
commit
5e9dc18469
@ -1,4 +1,5 @@
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
fn_args_layout = "Compressed"
|
fn_args_layout = "Compressed"
|
||||||
fn_single_line = true
|
fn_single_line = true
|
||||||
hard_tabs = true
|
hard_tabs = true
|
||||||
|
wrap_comments = true
|
||||||
@ -289,13 +289,16 @@ pub struct MathApp {
|
|||||||
// Stores vector of functions
|
// Stores vector of functions
|
||||||
functions: Vec<FunctionEntry>,
|
functions: Vec<FunctionEntry>,
|
||||||
|
|
||||||
// Stores vector containing the string representation of the functions. This is used because of hacky reasons
|
// Stores vector containing the string representation of the functions. This is used because of
|
||||||
|
// hacky reasons
|
||||||
func_strs: Vec<String>,
|
func_strs: Vec<String>,
|
||||||
|
|
||||||
// Stores last error from parsing functions (used to display the same error when side panel is minimized)
|
// Stores last error from parsing functions (used to display the same error when side panel is
|
||||||
|
// minimized)
|
||||||
last_error: Vec<(usize, String)>,
|
last_error: Vec<(usize, String)>,
|
||||||
|
|
||||||
// Contains the list of Areas calculated (the vector of f64) and time it took for the last frame (the Duration). Stored in a Tuple.
|
// Contains the list of Areas calculated (the vector of f64) and time it took for the last
|
||||||
|
// frame (the Duration). Stored in a Tuple.
|
||||||
last_info: (Vec<f64>, Duration),
|
last_info: (Vec<f64>, Duration),
|
||||||
|
|
||||||
// Stores Settings (pretty self-explanatory)
|
// Stores Settings (pretty self-explanatory)
|
||||||
@ -316,7 +319,8 @@ impl Default for MathApp {
|
|||||||
|
|
||||||
impl MathApp {
|
impl MathApp {
|
||||||
fn side_panel(&mut self, ctx: &Context) {
|
fn side_panel(&mut self, ctx: &Context) {
|
||||||
// Side Panel which contains vital options to the operation of the application (such as adding functions and other options)
|
// Side Panel which contains vital options to the operation of the application
|
||||||
|
// (such as adding functions and other options)
|
||||||
SidePanel::left("side_panel")
|
SidePanel::left("side_panel")
|
||||||
.resizable(false)
|
.resizable(false)
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
@ -432,7 +436,8 @@ impl MathApp {
|
|||||||
})
|
})
|
||||||
.clicked();
|
.clicked();
|
||||||
|
|
||||||
// Toggle showing the derivative (even though it's already calculated, this option just toggles if it's displayed or not)
|
// Toggle showing the derivative (even though it's already calculated, this
|
||||||
|
// option just toggles if it's displayed or not)
|
||||||
derivative_toggle = ui
|
derivative_toggle = ui
|
||||||
.add(Button::new("d/dx"))
|
.add(Button::new("d/dx"))
|
||||||
.on_hover_text(match derivative_enabled {
|
.on_hover_text(match derivative_enabled {
|
||||||
@ -496,7 +501,10 @@ impl epi::App for MathApp {
|
|||||||
fn name(&self) -> &str { "(Yet-to-be-named) Graphing Software" }
|
fn name(&self) -> &str { "(Yet-to-be-named) Graphing Software" }
|
||||||
|
|
||||||
// Called once before the first frame.
|
// Called once before the first frame.
|
||||||
fn setup(&mut self, _ctx: &Context, _frame: &Frame, _storage: Option<&dyn Storage>, _gl: &std::rc::Rc<epi::glow::Context>,) {
|
fn setup(
|
||||||
|
&mut self, _ctx: &Context, _frame: &Frame, _storage: Option<&dyn Storage>,
|
||||||
|
_gl: &std::rc::Rc<epi::glow::Context>,
|
||||||
|
) {
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
stop_loading();
|
stop_loading();
|
||||||
log_helper("egui app initialized.");
|
log_helper("egui app initialized.");
|
||||||
@ -632,9 +640,11 @@ impl epi::App for MathApp {
|
|||||||
self.side_panel(ctx);
|
self.side_panel(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut area_list: Vec<f64> = Vec::new(); // Referenced in plotting code, but needs to be here so it can be later referenced when storing `last_info`
|
let mut area_list: Vec<f64> = Vec::new(); // Referenced in plotting code, but needs to be here so it can be later
|
||||||
|
// referenced when storing `last_info`
|
||||||
|
|
||||||
// Central panel which contains the central plot (or an error created when parsing)
|
// Central panel which contains the central plot (or an error created when
|
||||||
|
// parsing)
|
||||||
CentralPanel::default().show(ctx, |ui| {
|
CentralPanel::default().show(ctx, |ui| {
|
||||||
// Display an error if it exists
|
// Display an error if it exists
|
||||||
if !self.last_error.is_empty() {
|
if !self.last_error.is_empty() {
|
||||||
@ -679,9 +689,12 @@ impl epi::App for MathApp {
|
|||||||
.collect();
|
.collect();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
self.last_info = (area_list, start.elapsed()); // Store list of functions' areas along with the time it took to process.
|
self.last_info = (area_list, start.elapsed()); // Store list of functions' areas
|
||||||
|
// along with the time it took to
|
||||||
|
// process.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uncaps max canvas size. This was capped in egui due to a bug in Firefox. But it's fixed now.
|
// Uncaps max canvas size. This was capped in egui due to a bug in Firefox. But
|
||||||
|
// it's fixed now.
|
||||||
fn max_size_points(&self) -> Vec2 { Vec2::new(f32::MAX, f32::MAX) }
|
fn max_size_points(&self) -> Vec2 { Vec2::new(f32::MAX, f32::MAX) }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,20 +27,24 @@ lazy_static::lazy_static! {
|
|||||||
pub static ref EMPTY_FUNCTION_ENTRY: FunctionEntry = FunctionEntry::empty();
|
pub static ref EMPTY_FUNCTION_ENTRY: FunctionEntry = FunctionEntry::empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `FunctionEntry` is a function that can calculate values, integrals, derivatives, etc etc
|
/// `FunctionEntry` is a function that can calculate values, integrals,
|
||||||
|
/// derivatives, etc etc
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct FunctionEntry {
|
pub struct FunctionEntry {
|
||||||
/// The `BackingFunction` instance that is used to generate `f(x)`, `f'(x)`, and `f''(x)`
|
/// The `BackingFunction` instance that is used to generate `f(x)`, `f'(x)`,
|
||||||
|
/// and `f''(x)`
|
||||||
function: BackingFunction,
|
function: BackingFunction,
|
||||||
|
|
||||||
/// Stores a function string (that hasn't been processed via `process_func_str`) to display to the user
|
/// Stores a function string (that hasn't been processed via
|
||||||
|
/// `process_func_str`) to display to the user
|
||||||
func_str: String,
|
func_str: String,
|
||||||
|
|
||||||
/// Minimum and Maximum values of what do display
|
/// Minimum and Maximum values of what do display
|
||||||
min_x: f64,
|
min_x: f64,
|
||||||
max_x: f64,
|
max_x: f64,
|
||||||
|
|
||||||
/// How many horizontal pixels? (used for calculating the step at which to generate values at)
|
/// How many horizontal pixels? (used for calculating the step at which to
|
||||||
|
/// generate values at)
|
||||||
pixel_width: usize,
|
pixel_width: usize,
|
||||||
|
|
||||||
/// output/cached data
|
/// output/cached data
|
||||||
@ -49,7 +53,8 @@ pub struct FunctionEntry {
|
|||||||
/// If calculating/displayingintegrals are enabled
|
/// If calculating/displayingintegrals are enabled
|
||||||
pub(crate) integral: bool,
|
pub(crate) integral: bool,
|
||||||
|
|
||||||
/// If displaying derivatives are enabled (note, they are still calculated for other purposes)
|
/// If displaying derivatives are enabled (note, they are still calculated
|
||||||
|
/// for other purposes)
|
||||||
pub(crate) derivative: bool,
|
pub(crate) derivative: bool,
|
||||||
|
|
||||||
/// Minumum and maximum range of integral
|
/// Minumum and maximum range of integral
|
||||||
@ -113,7 +118,8 @@ impl FunctionEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: refactor this
|
// TODO: refactor this
|
||||||
/// Returns back values, integral data (Bars and total area), and Derivative values
|
/// Returns back values, integral data (Bars and total area), and Derivative
|
||||||
|
/// values
|
||||||
pub fn run_back(&mut self) -> (Vec<Value>, Option<(Vec<Bar>, f64)>, Option<Vec<Value>>) {
|
pub fn run_back(&mut self) -> (Vec<Value>, Option<(Vec<Bar>, f64)>, Option<Vec<Value>>) {
|
||||||
let resolution: f64 = (self.pixel_width as f64 / (self.max_x - self.min_x).abs()) as f64;
|
let resolution: f64 = (self.pixel_width as f64 / (self.max_x - self.min_x).abs()) as f64;
|
||||||
let back_values: Vec<Value> = {
|
let back_values: Vec<Value> = {
|
||||||
@ -157,7 +163,8 @@ impl FunctionEntry {
|
|||||||
(back_values, integral_data, derivative_values)
|
(back_values, integral_data, derivative_values)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates and does the math for creating all the rectangles under the graph
|
/// Creates and does the math for creating all the rectangles under the
|
||||||
|
/// graph
|
||||||
fn integral_rectangles(&self) -> (Vec<(f64, f64)>, f64) {
|
fn integral_rectangles(&self) -> (Vec<(f64, f64)>, f64) {
|
||||||
if self.integral_min_x.is_nan() {
|
if self.integral_min_x.is_nan() {
|
||||||
panic!("integral_min_x is NaN")
|
panic!("integral_min_x is NaN")
|
||||||
|
|||||||
@ -47,7 +47,8 @@ impl FunctionOutput {
|
|||||||
pub fn invalidate_derivative(&mut self) { self.derivative = None; }
|
pub fn invalidate_derivative(&mut self) { self.derivative = None; }
|
||||||
|
|
||||||
/// Display output on PlotUi `plot_ui`
|
/// Display output on PlotUi `plot_ui`
|
||||||
/// Returns `f64` containing rounded integral area (if integrals are disabled, it returns `f64::NAN`)
|
/// Returns `f64` containing rounded integral area (if integrals are
|
||||||
|
/// disabled, it returns `f64::NAN`)
|
||||||
pub fn display(
|
pub fn display(
|
||||||
&self, plot_ui: &mut PlotUi, func_str: &str, derivative_str: &str, step: f64,
|
&self, plot_ui: &mut PlotUi, func_str: &str, derivative_str: &str, step: f64,
|
||||||
derivative_enabled: bool,
|
derivative_enabled: bool,
|
||||||
|
|||||||
34
src/misc.rs
34
src/misc.rs
@ -2,7 +2,8 @@ use std::ops::Range;
|
|||||||
|
|
||||||
use eframe::egui::plot::Value;
|
use eframe::egui::plot::Value;
|
||||||
|
|
||||||
// Handles logging based on if the target is wasm (or not) and if `debug_assertions` is enabled or not
|
// Handles logging based on if the target is wasm (or not) and if
|
||||||
|
// `debug_assertions` is enabled or not
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(target_arch = "wasm32")] {
|
if #[cfg(target_arch = "wasm32")] {
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
@ -43,8 +44,11 @@ cfg_if::cfg_if! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `SteppedVector` is used in order to efficiently sort through an ordered `Vec<f64>`
|
/// `SteppedVector` is used in order to efficiently sort through an ordered
|
||||||
/// Used in order to speedup the processing of cached data when moving horizontally without zoom in `FunctionEntry`. Before this struct, the index was calculated with `.iter().position(....` which was horribly inefficient
|
/// `Vec<f64>` Used in order to speedup the processing of cached data when
|
||||||
|
/// moving horizontally without zoom in `FunctionEntry`. Before this struct, the
|
||||||
|
/// index was calculated with `.iter().position(....` which was horribly
|
||||||
|
/// inefficient
|
||||||
pub struct SteppedVector {
|
pub struct SteppedVector {
|
||||||
// Actual data being referenced. HAS to be sorted from maximum value to minumum
|
// Actual data being referenced. HAS to be sorted from maximum value to minumum
|
||||||
data: Vec<f64>,
|
data: Vec<f64>,
|
||||||
@ -55,14 +59,17 @@ pub struct SteppedVector {
|
|||||||
// Maximum value
|
// Maximum value
|
||||||
max: f64,
|
max: f64,
|
||||||
|
|
||||||
// Since all entries in `data` are evenly spaced, this field stores the step between 2 adjacent elements
|
// Since all entries in `data` are evenly spaced, this field stores the step between 2 adjacent
|
||||||
|
// elements
|
||||||
step: f64,
|
step: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SteppedVector {
|
impl SteppedVector {
|
||||||
/// Returns `Option<usize>` with index of element with value `x`. and `None` if `x` does not exist in `data`
|
/// Returns `Option<usize>` with index of element with value `x`. and `None`
|
||||||
|
/// if `x` does not exist in `data`
|
||||||
pub fn get_index(&self, x: f64) -> Option<usize> {
|
pub fn get_index(&self, x: f64) -> Option<usize> {
|
||||||
// if `x` is outside range, just go ahead and return `None` as it *shouldn't* be in `data`
|
// if `x` is outside range, just go ahead and return `None` as it *shouldn't* be
|
||||||
|
// in `data`
|
||||||
if (x > self.max) | (self.min > x) {
|
if (x > self.max) | (self.min > x) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@ -70,7 +77,8 @@ impl SteppedVector {
|
|||||||
// Do some math in order to calculate the expected index value
|
// Do some math in order to calculate the expected index value
|
||||||
let possible_i = ((x + self.min) / self.step) as usize;
|
let possible_i = ((x + self.min) / self.step) as usize;
|
||||||
|
|
||||||
// Make sure that the index is valid by checking the data returned vs the actual data (just in case)
|
// Make sure that the index is valid by checking the data returned vs the actual
|
||||||
|
// data (just in case)
|
||||||
if self.data[possible_i] == x {
|
if self.data[possible_i] == x {
|
||||||
// It is valid!
|
// It is valid!
|
||||||
Some(possible_i)
|
Some(possible_i)
|
||||||
@ -96,7 +104,8 @@ impl SteppedVector {
|
|||||||
// Convert `Vec<f64>` into `SteppedVector`
|
// Convert `Vec<f64>` into `SteppedVector`
|
||||||
impl From<Vec<f64>> for SteppedVector {
|
impl From<Vec<f64>> for SteppedVector {
|
||||||
/// Note: input `data` is assumed to be sorted properly
|
/// Note: input `data` is assumed to be sorted properly
|
||||||
/// `data` is a Vector of 64 bit floating point numbers ordered from max -> min
|
/// `data` is a Vector of 64 bit floating point numbers ordered from max ->
|
||||||
|
/// min
|
||||||
fn from(data: Vec<f64>) -> SteppedVector {
|
fn from(data: Vec<f64>) -> SteppedVector {
|
||||||
let max = data[0]; // The max value should be the first element
|
let max = data[0]; // The max value should be the first element
|
||||||
let min = data[data.len() - 1]; // The minimum value should be the last element
|
let min = data[data.len() - 1]; // The minimum value should be the last element
|
||||||
@ -115,14 +124,15 @@ impl From<Vec<f64>> for SteppedVector {
|
|||||||
// Rounds f64 to specific number of decimal places
|
// Rounds f64 to specific number of decimal places
|
||||||
pub fn decimal_round(x: f64, n: usize) -> f64 {
|
pub fn decimal_round(x: f64, n: usize) -> f64 {
|
||||||
let large_number: f64 = 10.0_f64.powf(n as f64); // 10^n
|
let large_number: f64 = 10.0_f64.powf(n as f64); // 10^n
|
||||||
(x * large_number).round() / large_number // round and devide in order to cut off after the `n`th decimal place
|
(x * large_number).round() / large_number // round and devide in order to cut
|
||||||
|
// off after the `n`th decimal place
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implements newton's method of finding roots.
|
/// Implements newton's method of finding roots.
|
||||||
/// `threshold` is the target accuracy threshold
|
/// `threshold` is the target accuracy threshold
|
||||||
/// `range` is the range of valid x values (used to stop calculation when the point won't display anyways)
|
/// `range` is the range of valid x values (used to stop calculation when the
|
||||||
/// `data` is the data to iterate over (a Vector of egui's `Value` struct)
|
/// point won't display anyways) `data` is the data to iterate over (a Vector of
|
||||||
/// `f` is f(x)
|
/// egui's `Value` struct) `f` is f(x)
|
||||||
/// `f_1` is f'(x)
|
/// `f_1` is f'(x)
|
||||||
/// The function returns a Vector of `x` values where roots occur
|
/// The function returns a Vector of `x` values where roots occur
|
||||||
pub fn newtons_method(
|
pub fn newtons_method(
|
||||||
|
|||||||
@ -133,7 +133,8 @@ pub fn process_func_str(function_in: String) -> String {
|
|||||||
output_string.replace("log(", "log10(")
|
output_string.replace("log(", "log10(")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests function to make sure it's able to be parsed. Returns the string of the Error produced, or an empty string if it runs successfully.
|
// Tests function to make sure it's able to be parsed. Returns the string of the
|
||||||
|
// Error produced, or an empty string if it runs successfully.
|
||||||
pub fn test_func(function_string: &str) -> Option<String> {
|
pub fn test_func(function_string: &str) -> Option<String> {
|
||||||
let parse_result = exmex::parse::<f64>(function_string);
|
let parse_result = exmex::parse::<f64>(function_string);
|
||||||
|
|
||||||
@ -169,7 +170,8 @@ pub fn test_func(function_string: &str) -> Option<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used for testing: passes function to `add_asterisks` before running `test_func`
|
// Used for testing: passes function to `add_asterisks` before running
|
||||||
|
// `test_func`
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn test_func_helper(function_string: &str) -> Option<String> {
|
fn test_func_helper(function_string: &str) -> Option<String> {
|
||||||
test_func(&process_func_str(function_string.to_string()))
|
test_func(&process_func_str(function_string.to_string()))
|
||||||
@ -225,7 +227,8 @@ fn func_process_test() {
|
|||||||
test_process_helper("10pi", "10*π");
|
test_process_helper("10pi", "10*π");
|
||||||
test_process_helper("pi10", "π*10");
|
test_process_helper("pi10", "π*10");
|
||||||
|
|
||||||
// Need to fix these checks, maybe I need to rewrite the whole asterisk adding system... (or just implement these changes into meval-rs, idk)
|
// Need to fix these checks, maybe I need to rewrite the whole asterisk
|
||||||
|
// adding system... (or just implement these changes into meval-rs, idk)
|
||||||
// test_process_helper("emax(x)", "e*max(x)");
|
// test_process_helper("emax(x)", "e*max(x)");
|
||||||
// test_process_helper("pisin(x)", "pi*sin(x)");
|
// test_process_helper("pisin(x)", "pi*sin(x)");
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user