documentation, comments, and cleanup
This commit is contained in:
parent
a8597374c2
commit
9935285c98
@ -462,10 +462,10 @@ impl MathApp {
|
|||||||
proc_func_str,
|
proc_func_str,
|
||||||
integral_enabled,
|
integral_enabled,
|
||||||
derivative_enabled,
|
derivative_enabled,
|
||||||
Some(self.settings.integral_min_x),
|
self.settings.integral_min_x,
|
||||||
Some(self.settings.integral_max_x),
|
self.settings.integral_max_x,
|
||||||
Some(self.settings.integral_num),
|
self.settings.integral_num,
|
||||||
Some(self.settings.sum),
|
self.settings.sum,
|
||||||
);
|
);
|
||||||
self.last_error = self
|
self.last_error = self
|
||||||
.last_error
|
.last_error
|
||||||
|
|||||||
@ -11,6 +11,7 @@ use eframe::egui::plot::PlotUi;
|
|||||||
use eframe::egui::{plot::Value, widgets::plot::Bar};
|
use eframe::egui::{plot::Value, widgets::plot::Bar};
|
||||||
use std::fmt::{self, Debug};
|
use std::fmt::{self, Debug};
|
||||||
|
|
||||||
|
/// Represents the possible variations of Riemann Sums
|
||||||
#[derive(PartialEq, Debug, Copy, Clone)]
|
#[derive(PartialEq, Debug, Copy, Clone)]
|
||||||
pub enum RiemannSum {
|
pub enum RiemannSum {
|
||||||
Left,
|
Left,
|
||||||
@ -26,26 +27,44 @@ 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
|
||||||
#[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)`
|
||||||
function: BackingFunction,
|
function: BackingFunction,
|
||||||
|
|
||||||
|
/// 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
|
||||||
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)
|
||||||
pixel_width: usize,
|
pixel_width: usize,
|
||||||
|
|
||||||
|
/// output/cached data
|
||||||
output: FunctionOutput,
|
output: FunctionOutput,
|
||||||
|
|
||||||
|
/// 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)
|
||||||
pub(crate) derivative: bool,
|
pub(crate) derivative: bool,
|
||||||
|
|
||||||
|
/// Minumum and maximum range of integral
|
||||||
integral_min_x: f64,
|
integral_min_x: f64,
|
||||||
integral_max_x: f64,
|
integral_max_x: f64,
|
||||||
|
|
||||||
|
/// Number of rectangles used to approximate the integral via a Riemann Sum
|
||||||
integral_num: usize,
|
integral_num: usize,
|
||||||
|
|
||||||
|
/// The type of RiemannSum to use
|
||||||
sum: RiemannSum,
|
sum: RiemannSum,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionEntry {
|
impl FunctionEntry {
|
||||||
// Creates Empty Function instance
|
/// Creates Empty Function instance
|
||||||
pub fn empty() -> Self {
|
pub fn empty() -> Self {
|
||||||
Self {
|
Self {
|
||||||
function: BackingFunction::new(DEFAULT_FUNCION),
|
function: BackingFunction::new(DEFAULT_FUNCION),
|
||||||
@ -63,9 +82,10 @@ impl FunctionEntry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update function settings
|
||||||
pub fn update(
|
pub fn update(
|
||||||
&mut self, func_str: String, integral: bool, derivative: bool, integral_min_x: Option<f64>,
|
&mut self, func_str: String, integral: bool, derivative: bool, integral_min_x: f64,
|
||||||
integral_max_x: Option<f64>, integral_num: Option<usize>, sum: Option<RiemannSum>,
|
integral_max_x: f64, integral_num: usize, sum: RiemannSum,
|
||||||
) {
|
) {
|
||||||
// If the function string changes, just wipe and restart from scratch
|
// If the function string changes, just wipe and restart from scratch
|
||||||
if func_str != self.func_str {
|
if func_str != self.func_str {
|
||||||
@ -79,21 +99,21 @@ impl FunctionEntry {
|
|||||||
|
|
||||||
// Makes sure proper arguments are passed when integral is enabled
|
// Makes sure proper arguments are passed when integral is enabled
|
||||||
if integral
|
if integral
|
||||||
&& (integral_min_x != Some(self.integral_min_x))
|
&& (integral_min_x != self.integral_min_x)
|
||||||
| (integral_max_x != Some(self.integral_max_x))
|
| (integral_max_x != self.integral_max_x)
|
||||||
| (integral_num != Some(self.integral_num))
|
| (integral_num != self.integral_num)
|
||||||
| (sum != Some(self.sum))
|
| (sum != self.sum)
|
||||||
{
|
{
|
||||||
self.output.invalidate_integral();
|
self.output.invalidate_integral();
|
||||||
self.integral_min_x = integral_min_x.expect("integral_min_x is None");
|
self.integral_min_x = integral_min_x;
|
||||||
self.integral_max_x = integral_max_x.expect("integral_max_x is None");
|
self.integral_max_x = integral_max_x;
|
||||||
self.integral_num = integral_num.expect("integral_num is None");
|
self.integral_num = integral_num;
|
||||||
self.sum = sum.expect("sum is None");
|
self.sum = sum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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> = {
|
||||||
@ -137,7 +157,7 @@ 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")
|
||||||
@ -180,9 +200,10 @@ impl FunctionEntry {
|
|||||||
(data2, area)
|
(data2, area)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `func_str`
|
||||||
pub fn get_func_str(&self) -> &str { &self.func_str }
|
pub fn get_func_str(&self) -> &str { &self.func_str }
|
||||||
|
|
||||||
// Updates riemann value and invalidates integral_cache if needed
|
/// Updates riemann value and invalidates integral_cache if needed
|
||||||
pub fn update_riemann(mut self, riemann: RiemannSum) -> Self {
|
pub fn update_riemann(mut self, riemann: RiemannSum) -> Self {
|
||||||
if self.sum != riemann {
|
if self.sum != riemann {
|
||||||
self.sum = riemann;
|
self.sum = riemann;
|
||||||
@ -191,24 +212,27 @@ impl FunctionEntry {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggles integral
|
/// Sets whether integral is enabled or not
|
||||||
pub fn integral(mut self, integral: bool) -> Self {
|
pub fn integral(mut self, enabled: bool) -> Self {
|
||||||
self.integral = integral;
|
self.integral = enabled;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets number of rectangles to use to calculate the integral
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn integral_num(mut self, integral_num: usize) -> Self {
|
pub fn integral_num(mut self, integral_num: usize) -> Self {
|
||||||
self.integral_num = integral_num;
|
self.integral_num = integral_num;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the number of horizontal pixels
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn pixel_width(mut self, pixel_width: usize) -> Self {
|
pub fn pixel_width(mut self, pixel_width: usize) -> Self {
|
||||||
self.pixel_width = pixel_width;
|
self.pixel_width = pixel_width;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the bounds of the integral
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn integral_bounds(mut self, min_x: f64, max_x: f64) -> Self {
|
pub fn integral_bounds(mut self, min_x: f64, max_x: f64) -> Self {
|
||||||
if min_x >= max_x {
|
if min_x >= max_x {
|
||||||
@ -220,6 +244,7 @@ impl FunctionEntry {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculates and displays the function on PlotUI `plot_ui`
|
||||||
pub fn display(
|
pub fn display(
|
||||||
&mut self, plot_ui: &mut PlotUi, min_x: f64, max_x: f64, pixel_width: usize, extrema: bool,
|
&mut self, plot_ui: &mut PlotUi, min_x: f64, max_x: f64, pixel_width: usize, extrema: bool,
|
||||||
roots: bool,
|
roots: bool,
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use crate::misc::decimal_round;
|
||||||
use eframe::{
|
use eframe::{
|
||||||
egui::{
|
egui::{
|
||||||
plot::{BarChart, Line, PlotUi, Points, Value, Values},
|
plot::{BarChart, Line, PlotUi, Points, Value, Values},
|
||||||
@ -6,8 +7,6 @@ use eframe::{
|
|||||||
epaint::Color32,
|
epaint::Color32,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::misc::digits_precision;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct FunctionOutput {
|
pub struct FunctionOutput {
|
||||||
pub(crate) back: Option<Vec<Value>>,
|
pub(crate) back: Option<Vec<Value>>,
|
||||||
@ -18,6 +17,7 @@ pub struct FunctionOutput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionOutput {
|
impl FunctionOutput {
|
||||||
|
/// Creates empty instance of `FunctionOutput`
|
||||||
pub fn new_empty() -> Self {
|
pub fn new_empty() -> Self {
|
||||||
Self {
|
Self {
|
||||||
back: None,
|
back: None,
|
||||||
@ -28,6 +28,7 @@ impl FunctionOutput {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Invalidate all data (setting it all to `None`)
|
||||||
pub fn invalidate_whole(&mut self) {
|
pub fn invalidate_whole(&mut self) {
|
||||||
self.back = None;
|
self.back = None;
|
||||||
self.integral = None;
|
self.integral = None;
|
||||||
@ -36,22 +37,29 @@ impl FunctionOutput {
|
|||||||
self.roots = None;
|
self.roots = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Invalidate `back` data
|
||||||
pub fn invalidate_back(&mut self) { self.back = None; }
|
pub fn invalidate_back(&mut self) { self.back = None; }
|
||||||
|
|
||||||
|
/// Invalidate Integral data
|
||||||
pub fn invalidate_integral(&mut self) { self.integral = None; }
|
pub fn invalidate_integral(&mut self) { self.integral = None; }
|
||||||
|
|
||||||
|
/// Invalidate Derivative data
|
||||||
pub fn invalidate_derivative(&mut self) { self.derivative = None; }
|
pub fn invalidate_derivative(&mut self) { self.derivative = None; }
|
||||||
|
|
||||||
|
/// Display output on PlotUi `plot_ui`
|
||||||
|
/// 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,
|
||||||
) -> f64 {
|
) -> f64 {
|
||||||
|
// Plot back data
|
||||||
plot_ui.line(
|
plot_ui.line(
|
||||||
Line::new(Values::from_values(self.back.clone().unwrap()))
|
Line::new(Values::from_values(self.back.clone().unwrap()))
|
||||||
.color(Color32::RED)
|
.color(Color32::RED)
|
||||||
.name(func_str),
|
.name(func_str),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Plot derivative data
|
||||||
if derivative_enabled {
|
if derivative_enabled {
|
||||||
if let Some(derivative_data) = self.derivative.clone() {
|
if let Some(derivative_data) = self.derivative.clone() {
|
||||||
plot_ui.line(
|
plot_ui.line(
|
||||||
@ -62,6 +70,7 @@ impl FunctionOutput {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Plot extrema points
|
||||||
if let Some(extrema_data) = self.extrema.clone() {
|
if let Some(extrema_data) = self.extrema.clone() {
|
||||||
plot_ui.points(
|
plot_ui.points(
|
||||||
Points::new(Values::from_values(extrema_data))
|
Points::new(Values::from_values(extrema_data))
|
||||||
@ -71,6 +80,7 @@ impl FunctionOutput {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Plot roots points
|
||||||
if let Some(roots_data) = self.roots.clone() {
|
if let Some(roots_data) = self.roots.clone() {
|
||||||
plot_ui.points(
|
plot_ui.points(
|
||||||
Points::new(Values::from_values(roots_data))
|
Points::new(Values::from_values(roots_data))
|
||||||
@ -80,6 +90,7 @@ impl FunctionOutput {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Plot integral data
|
||||||
if let Some(integral_data) = self.integral.clone() {
|
if let Some(integral_data) = self.integral.clone() {
|
||||||
plot_ui.bar_chart(
|
plot_ui.bar_chart(
|
||||||
BarChart::new(integral_data.0)
|
BarChart::new(integral_data.0)
|
||||||
@ -87,9 +98,9 @@ impl FunctionOutput {
|
|||||||
.width(step),
|
.width(step),
|
||||||
);
|
);
|
||||||
|
|
||||||
digits_precision(integral_data.1, 8)
|
decimal_round(integral_data.1, 8) // return value rounded to 8 decimal places
|
||||||
} else {
|
} else {
|
||||||
f64::NAN
|
f64::NAN // return NaN if integrals are disabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
51
src/misc.rs
51
src/misc.rs
@ -2,22 +2,24 @@ 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
|
||||||
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::*;
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
// Use `js_namespace` here to bind `console.log(..)` instead of just
|
// `console.log(...)`
|
||||||
// `log(..)`
|
|
||||||
#[wasm_bindgen(js_namespace = console)]
|
#[wasm_bindgen(js_namespace = console)]
|
||||||
fn log(s: &str);
|
fn log(s: &str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used for logging normal messages
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn log_helper(s: &str) {
|
pub fn log_helper(s: &str) {
|
||||||
log(s);
|
log(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used for debug messages, only does anything if `debug_assertions` is enabled
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
pub fn debug_log(s: &str) {
|
pub fn debug_log(s: &str) {
|
||||||
@ -25,11 +27,13 @@ cfg_if::cfg_if! {
|
|||||||
log(s);
|
log(s);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
/// Used for logging normal messages
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn log_helper(s: &str) {
|
pub fn log_helper(s: &str) {
|
||||||
println!("{}", s);
|
println!("{}", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used for debug messages, only does anything if `debug_assertions` is enabled
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
pub fn debug_log(s: &str) {
|
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 {
|
pub struct SteppedVector {
|
||||||
|
// Actual data being referenced. HAS to be sorted from maximum value to minumum
|
||||||
data: Vec<f64>,
|
data: Vec<f64>,
|
||||||
|
|
||||||
|
// Minimum value
|
||||||
min: f64,
|
min: f64,
|
||||||
|
|
||||||
|
// Maximum value
|
||||||
max: f64,
|
max: f64,
|
||||||
|
|
||||||
|
// 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`
|
||||||
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 > self.max) | (self.min > x) {
|
if (x > self.max) | (self.min > x) {
|
||||||
return None;
|
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;
|
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 {
|
if self.data[possible_i] == x {
|
||||||
|
// It is valid!
|
||||||
Some(possible_i)
|
Some(possible_i)
|
||||||
} else {
|
} else {
|
||||||
|
// (For some reason) it wasn't!
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not really needed as the above code should handle everything
|
// Old (inefficent) code
|
||||||
/*
|
/*
|
||||||
for (i, ele) in self.data.iter().enumerate() {
|
for (i, ele) in self.data.iter().enumerate() {
|
||||||
if ele > &x {
|
if ele > &x {
|
||||||
@ -74,12 +93,16 @@ impl 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 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 {
|
fn from(data: Vec<f64>) -> SteppedVector {
|
||||||
let max = data[0];
|
let max = data[0]; // The max value should be the first element
|
||||||
let min = data[data.len() - 1];
|
let min = data[data.len() - 1]; // The minimum value should be the last element
|
||||||
let step = (max - min).abs() / ((data.len() - 1) as f64);
|
let step = (max - min).abs() / ((data.len() - 1) as f64); // Calculate the step between elements
|
||||||
|
|
||||||
|
// Create and return the struct
|
||||||
SteppedVector {
|
SteppedVector {
|
||||||
data,
|
data,
|
||||||
min,
|
min,
|
||||||
@ -89,10 +112,10 @@ impl From<Vec<f64>> for SteppedVector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rounds f64 to specific number of digits
|
// Rounds f64 to specific number of decimal places
|
||||||
pub fn digits_precision(x: f64, digits: usize) -> f64 {
|
pub fn decimal_round(x: f64, n: usize) -> f64 {
|
||||||
let large_number: f64 = 10.0_f64.powf(digits as f64);
|
let large_number: f64 = 10.0_f64.powf(n as f64); // 10^n
|
||||||
(x * large_number).round() / large_number
|
(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.
|
||||||
@ -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)
|
/// `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)
|
/// `data` is the data to iterate over (a Vector of egui's `Value` struct)
|
||||||
/// `f` is f(x)
|
/// `f` is f(x)
|
||||||
/// `f_` is f'(x)
|
/// `f_1` is f'(x)
|
||||||
/// The function returns a list 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(
|
||||||
threshold: f64, range: Range<f64>, data: Vec<Value>, f: &dyn Fn(f64) -> f64,
|
threshold: f64, range: Range<f64>, data: Vec<Value>, f: &dyn Fn(f64) -> f64,
|
||||||
f_1: &dyn Fn(f64) -> f64,
|
f_1: &dyn Fn(f64) -> f64,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user