documentation, comments, and cleanup
This commit is contained in:
51
src/misc.rs
51
src/misc.rs
@@ -2,22 +2,24 @@ use std::ops::Range;
|
||||
|
||||
use eframe::egui::plot::Value;
|
||||
|
||||
// Handles logging based on if the target is wasm (or not) and if `debug_assertions` is enabled or not
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_arch = "wasm32")] {
|
||||
use wasm_bindgen::prelude::*;
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
// Use `js_namespace` here to bind `console.log(..)` instead of just
|
||||
// `log(..)`
|
||||
// `console.log(...)`
|
||||
#[wasm_bindgen(js_namespace = console)]
|
||||
fn log(s: &str);
|
||||
}
|
||||
|
||||
/// Used for logging normal messages
|
||||
#[allow(dead_code)]
|
||||
pub fn log_helper(s: &str) {
|
||||
log(s);
|
||||
}
|
||||
|
||||
/// Used for debug messages, only does anything if `debug_assertions` is enabled
|
||||
#[allow(dead_code)]
|
||||
#[allow(unused_variables)]
|
||||
pub fn debug_log(s: &str) {
|
||||
@@ -25,11 +27,13 @@ cfg_if::cfg_if! {
|
||||
log(s);
|
||||
}
|
||||
} else {
|
||||
/// Used for logging normal messages
|
||||
#[allow(dead_code)]
|
||||
pub fn log_helper(s: &str) {
|
||||
println!("{}", s);
|
||||
}
|
||||
|
||||
/// Used for debug messages, only does anything if `debug_assertions` is enabled
|
||||
#[allow(dead_code)]
|
||||
#[allow(unused_variables)]
|
||||
pub fn debug_log(s: &str) {
|
||||
@@ -39,28 +43,43 @@ cfg_if::cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
/// `SteppedVector` is used in order to efficiently sort through an ordered `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 {
|
||||
// Actual data being referenced. HAS to be sorted from maximum value to minumum
|
||||
data: Vec<f64>,
|
||||
|
||||
// Minimum value
|
||||
min: f64,
|
||||
|
||||
// Maximum value
|
||||
max: f64,
|
||||
|
||||
// Since all entries in `data` are evenly spaced, this field stores the step between 2 adjacent elements
|
||||
step: f64,
|
||||
}
|
||||
|
||||
impl SteppedVector {
|
||||
/// 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> {
|
||||
// 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) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Should work....
|
||||
// Do some math in order to calculate the expected index value
|
||||
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)
|
||||
if self.data[possible_i] == x {
|
||||
// It is valid!
|
||||
Some(possible_i)
|
||||
} else {
|
||||
// (For some reason) it wasn't!
|
||||
None
|
||||
}
|
||||
|
||||
// Not really needed as the above code should handle everything
|
||||
// Old (inefficent) code
|
||||
/*
|
||||
for (i, ele) in self.data.iter().enumerate() {
|
||||
if ele > &x {
|
||||
@@ -74,12 +93,16 @@ impl SteppedVector {
|
||||
}
|
||||
}
|
||||
|
||||
// Convert `Vec<f64>` into `SteppedVector`
|
||||
impl From<Vec<f64>> for SteppedVector {
|
||||
// Note: input `data` is assumed to be sorted from min to max
|
||||
/// Note: input `data` is assumed to be sorted properly
|
||||
/// `data` is a Vector of 64 bit floating point numbers ordered from max -> min
|
||||
fn from(data: Vec<f64>) -> SteppedVector {
|
||||
let max = data[0];
|
||||
let min = data[data.len() - 1];
|
||||
let step = (max - min).abs() / ((data.len() - 1) as f64);
|
||||
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 step = (max - min).abs() / ((data.len() - 1) as f64); // Calculate the step between elements
|
||||
|
||||
// Create and return the struct
|
||||
SteppedVector {
|
||||
data,
|
||||
min,
|
||||
@@ -89,10 +112,10 @@ impl From<Vec<f64>> for SteppedVector {
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
(x * large_number).round() / large_number
|
||||
// Rounds f64 to specific number of decimal places
|
||||
pub fn decimal_round(x: f64, n: usize) -> f64 {
|
||||
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
|
||||
}
|
||||
|
||||
/// Implements newton's method of finding roots.
|
||||
@@ -100,8 +123,8 @@ pub fn digits_precision(x: f64, digits: usize) -> f64 {
|
||||
/// `range` is the range of valid x values (used to stop calculation when the point won't display anyways)
|
||||
/// `data` is the data to iterate over (a Vector of egui's `Value` struct)
|
||||
/// `f` is f(x)
|
||||
/// `f_` is f'(x)
|
||||
/// The function returns a list of `x` values where roots occur
|
||||
/// `f_1` is f'(x)
|
||||
/// The function returns a Vector of `x` values where roots occur
|
||||
pub fn newtons_method(
|
||||
threshold: f64, range: Range<f64>, data: Vec<Value>, f: &dyn Fn(f64) -> f64,
|
||||
f_1: &dyn Fn(f64) -> f64,
|
||||
|
||||
Reference in New Issue
Block a user