more refactoring

This commit is contained in:
Simon Gardling 2022-03-10 10:38:42 -05:00
parent 3e00657ade
commit 3f5a81b16c
3 changed files with 46 additions and 69 deletions

View File

@ -464,8 +464,6 @@ impl MathApp {
Some(self.settings.integral_max_x), Some(self.settings.integral_max_x),
Some(self.settings.integral_num), Some(self.settings.integral_num),
Some(self.settings.sum), Some(self.settings.sum),
self.settings.extrema,
self.settings.roots,
); );
self.last_error = self self.last_error = self
.last_error .last_error
@ -652,7 +650,14 @@ impl epi::App for MathApp {
return f64::NAN; return f64::NAN;
} }
function.display(plot_ui, minx_bounds, maxx_bounds, available_width) function.display(
plot_ui,
minx_bounds,
maxx_bounds,
available_width,
self.settings.extrema,
self.settings.roots,
)
}) })
.collect(); .collect();
self.last_info = (area_list, start.elapsed()); self.last_info = (area_list, start.elapsed());

View File

@ -42,8 +42,6 @@ pub struct FunctionEntry {
integral_max_x: f64, integral_max_x: f64,
integral_num: usize, integral_num: usize,
sum: RiemannSum, sum: RiemannSum,
roots: bool,
extrema: bool,
} }
impl FunctionEntry { impl FunctionEntry {
@ -62,15 +60,12 @@ impl FunctionEntry {
integral_max_x: f64::NAN, integral_max_x: f64::NAN,
integral_num: 0, integral_num: 0,
sum: DEFAULT_RIEMANN, sum: DEFAULT_RIEMANN,
roots: true,
extrema: true,
} }
} }
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: Option<f64>,
integral_max_x: Option<f64>, integral_num: Option<usize>, sum: Option<RiemannSum>, integral_max_x: Option<f64>, integral_num: Option<usize>, sum: Option<RiemannSum>,
extrema: bool, roots: bool,
) { ) {
// 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 {
@ -81,8 +76,6 @@ impl FunctionEntry {
self.derivative = derivative; self.derivative = derivative;
self.integral = integral; self.integral = integral;
self.extrema = extrema;
self.roots = roots;
// Makes sure proper arguments are passed when integral is enabled // Makes sure proper arguments are passed when integral is enabled
if integral if integral
@ -99,6 +92,8 @@ impl FunctionEntry {
} }
} }
// TODO: refactor this
// 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> = {
@ -225,42 +220,9 @@ impl FunctionEntry {
self self
} }
// Finds roots
fn roots(&mut self) {
let resolution: f64 = (self.pixel_width as f64 / (self.max_x - self.min_x).abs()) as f64;
self.output.roots = Some(
newtons_method(
resolution,
self.min_x..self.max_x,
self.output.back.to_owned().unwrap(),
&|x: f64| self.function.get(x),
&|x: f64| self.function.get_derivative_1(x),
)
.iter()
.map(|x| Value::new(*x, self.function.get(*x)))
.collect(),
);
}
// Finds extrema
fn extrema(&mut self) {
let resolution: f64 = (self.pixel_width as f64 / (self.max_x - self.min_x).abs()) as f64;
self.output.extrema = Some(
newtons_method(
resolution,
self.min_x..self.max_x,
self.output.derivative.to_owned().unwrap(),
&|x: f64| self.function.get_derivative_1(x),
&|x: f64| self.function.get_derivative_2(x),
)
.iter()
.map(|x| Value::new(*x, self.function.get(*x)))
.collect(),
);
}
pub fn display( pub fn display(
&mut self, plot_ui: &mut PlotUi, min_x: f64, max_x: f64, pixel_width: usize, &mut self, plot_ui: &mut PlotUi, min_x: f64, max_x: f64, pixel_width: usize, extrema: bool,
roots: bool,
) -> f64 { ) -> f64 {
if pixel_width != self.pixel_width { if pixel_width != self.pixel_width {
self.output.invalidate_back(); self.output.invalidate_back();
@ -311,40 +273,51 @@ impl FunctionEntry {
self.pixel_width = pixel_width; self.pixel_width = pixel_width;
} }
if self.extrema { let do_extrema = extrema
if (min_x != self.min_x) | (max_x != self.max_x) { && ((min_x != self.min_x) | (max_x != self.max_x) | self.output.extrema.is_none());
self.extrema(); let do_roots =
} roots && ((min_x != self.min_x) | (max_x != self.max_x) | self.output.roots.is_none());
} else {
self.output.extrema = None;
}
if self.roots {
if (min_x != self.min_x) | (max_x != self.max_x) {
self.roots();
}
} else {
self.output.roots = None;
}
self.min_x = min_x; self.min_x = min_x;
self.max_x = max_x; self.max_x = max_x;
let resolution: f64 = (self.pixel_width as f64 / (self.max_x - self.min_x).abs()) as f64;
let (back_values, integral, derivative) = self.run_back(); let (back_values, integral, derivative) = self.run_back();
self.output.back = Some(back_values); self.output.back = Some(back_values);
self.output.integral = integral; self.output.integral = integral;
self.output.derivative = derivative; self.output.derivative = derivative;
if self.extrema { // Calculates extrema
self.extrema(); if do_extrema {
} else { self.output.extrema = Some(
self.output.extrema = None; newtons_method(
resolution,
self.min_x..self.max_x,
self.output.derivative.to_owned().unwrap(),
&|x: f64| self.function.get_derivative_1(x),
&|x: f64| self.function.get_derivative_2(x),
)
.iter()
.map(|x| Value::new(*x, self.function.get(*x)))
.collect(),
);
} }
if self.roots { // Calculates roots
self.roots(); if do_roots {
} else { self.output.roots = Some(
self.output.roots = None; newtons_method(
resolution,
self.min_x..self.max_x,
self.output.back.to_owned().unwrap(),
&|x: f64| self.function.get(x),
&|x: f64| self.function.get_derivative_1(x),
)
.iter()
.map(|x| Value::new(*x, self.function.get(*x)))
.collect(),
);
} }
self.output.display( self.output.display(

View File

@ -95,7 +95,6 @@ pub fn digits_precision(x: f64, digits: usize) -> f64 {
(x * large_number).round() / large_number (x * large_number).round() / large_number
} }
/// 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 point won't display anyways)