more janky caching
This commit is contained in:
parent
37a818d1c7
commit
3b0c2df9e0
3
TODO.md
3
TODO.md
@ -6,5 +6,4 @@
|
|||||||
- Dynamically delete inputs
|
- Dynamically delete inputs
|
||||||
- Different colors
|
- Different colors
|
||||||
- Better Handling of area and integrals
|
- Better Handling of area and integrals
|
||||||
2. Cache data when not zooming.
|
2. Non `y=` functions.
|
||||||
3. Non `y=` functions.
|
|
||||||
@ -17,7 +17,7 @@ const INTEGRAL_NUM_RANGE: RangeInclusive<usize> = 10..=100000;
|
|||||||
const MIN_X_TOTAL: f64 = -1000.0;
|
const MIN_X_TOTAL: f64 = -1000.0;
|
||||||
const MAX_X_TOTAL: f64 = 1000.0;
|
const MAX_X_TOTAL: f64 = 1000.0;
|
||||||
const X_RANGE: RangeInclusive<f64> = MIN_X_TOTAL..=MAX_X_TOTAL;
|
const X_RANGE: RangeInclusive<f64> = MIN_X_TOTAL..=MAX_X_TOTAL;
|
||||||
const DEFAULT_FUNCION: &str = "x^2";
|
const DEFAULT_FUNCION: &str = "x^2"; // Default function that appears when adding a new function
|
||||||
|
|
||||||
pub struct MathApp {
|
pub struct MathApp {
|
||||||
functions: Vec<Function>,
|
functions: Vec<Function>,
|
||||||
@ -61,13 +61,6 @@ impl Default for MathApp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MathApp {
|
|
||||||
#[inline]
|
|
||||||
pub fn get_step(&self) -> f64 {
|
|
||||||
(self.integral_min_x - self.integral_max_x).abs() / (self.integral_num as f64)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl epi::App for MathApp {
|
impl epi::App for MathApp {
|
||||||
// The name of the program (displayed when running natively as the window title)
|
// The name of the program (displayed when running natively as the window title)
|
||||||
fn name(&self) -> &str { "Integral Demonstration" }
|
fn name(&self) -> &str { "Integral Demonstration" }
|
||||||
@ -82,15 +75,6 @@ impl epi::App for MathApp {
|
|||||||
// Called each time the UI needs repainting, which may be many times per second.
|
// Called each time the UI needs repainting, which may be many times per second.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn update(&mut self, ctx: &egui::Context, _frame: &epi::Frame) {
|
fn update(&mut self, ctx: &egui::Context, _frame: &epi::Frame) {
|
||||||
let Self {
|
|
||||||
functions,
|
|
||||||
func_strs,
|
|
||||||
integral_min_x,
|
|
||||||
integral_max_x,
|
|
||||||
integral_num,
|
|
||||||
help_open,
|
|
||||||
} = self;
|
|
||||||
|
|
||||||
// Note: This Instant implementation does not show microseconds when using wasm.
|
// Note: This Instant implementation does not show microseconds when using wasm.
|
||||||
let start = instant::Instant::now();
|
let start = instant::Instant::now();
|
||||||
|
|
||||||
@ -98,7 +82,7 @@ impl epi::App for MathApp {
|
|||||||
// TODO: add more detail
|
// TODO: add more detail
|
||||||
egui::Window::new("Supported Functions")
|
egui::Window::new("Supported Functions")
|
||||||
.default_pos([200.0, 200.0])
|
.default_pos([200.0, 200.0])
|
||||||
.open(help_open)
|
.open(&mut self.help_open)
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
ui.label("- sqrt, abs");
|
ui.label("- sqrt, abs");
|
||||||
ui.label("- exp, ln, log10 (log10 can also be called as log)");
|
ui.label("- exp, ln, log10 (log10 can also be called as log)");
|
||||||
@ -112,7 +96,7 @@ impl epi::App for MathApp {
|
|||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
if ui.add(egui::Button::new("Add function")).clicked() {
|
if ui.add(egui::Button::new("Add function")).clicked() {
|
||||||
// min_x and max_x will be updated later, doesn't matter here
|
// min_x and max_x will be updated later, doesn't matter here
|
||||||
functions.push(Function::new(
|
self.functions.push(Function::new(
|
||||||
String::from(DEFAULT_FUNCION),
|
String::from(DEFAULT_FUNCION),
|
||||||
-1.0,
|
-1.0,
|
||||||
1.0,
|
1.0,
|
||||||
@ -122,11 +106,11 @@ impl epi::App for MathApp {
|
|||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
func_strs.push(String::from(DEFAULT_FUNCION));
|
self.func_strs.push(String::from(DEFAULT_FUNCION));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ui.add(egui::Button::new("Open Help")).clicked() {
|
if ui.add(egui::Button::new("Open Help")).clicked() {
|
||||||
*help_open = true;
|
self.help_open = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -137,35 +121,35 @@ impl epi::App for MathApp {
|
|||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
ui.heading("Side Panel");
|
ui.heading("Side Panel");
|
||||||
|
|
||||||
let min_x_old = *integral_min_x;
|
let min_x_old = self.integral_min_x;
|
||||||
let min_x_response =
|
let min_x_response =
|
||||||
ui.add(egui::Slider::new(integral_min_x, X_RANGE.clone()).text("Min X"));
|
ui.add(egui::Slider::new(&mut self.integral_min_x, X_RANGE.clone()).text("Min X"));
|
||||||
|
|
||||||
let max_x_old = *integral_max_x;
|
let max_x_old = self.integral_max_x;
|
||||||
let max_x_response = ui.add(egui::Slider::new(integral_max_x, X_RANGE).text("Max X"));
|
let max_x_response = ui.add(egui::Slider::new(&mut self.integral_max_x, X_RANGE).text("Max X"));
|
||||||
|
|
||||||
// Checks bounds, and if they are invalid, fix them
|
// Checks bounds, and if they are invalid, fix them
|
||||||
if integral_min_x >= integral_max_x {
|
if self.integral_min_x >= self.integral_max_x {
|
||||||
if max_x_response.changed() {
|
if max_x_response.changed() {
|
||||||
*integral_max_x = max_x_old;
|
self.integral_max_x = max_x_old;
|
||||||
} else if min_x_response.changed() {
|
} else if min_x_response.changed() {
|
||||||
*integral_min_x = min_x_old;
|
self.integral_min_x = min_x_old;
|
||||||
} else {
|
} else {
|
||||||
*integral_min_x = -10.0;
|
self.integral_min_x = -10.0;
|
||||||
*integral_max_x = 10.0;
|
self.integral_max_x = 10.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.add(egui::Slider::new(integral_num, INTEGRAL_NUM_RANGE).text("Interval"));
|
ui.add(egui::Slider::new(&mut self.integral_num, INTEGRAL_NUM_RANGE).text("Interval"));
|
||||||
|
|
||||||
for (i, function) in functions.iter_mut().enumerate() {
|
for (i, function) in self.functions.iter_mut().enumerate() {
|
||||||
let mut integral_toggle: bool = false;
|
let mut integral_toggle: bool = false;
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.label("Function: ");
|
ui.label("Function: ");
|
||||||
if ui.add(Button::new("Toggle Integrals")).clicked() {
|
if ui.add(Button::new("Toggle Integrals")).clicked() {
|
||||||
integral_toggle = true;
|
integral_toggle = true;
|
||||||
}
|
}
|
||||||
ui.text_edit_singleline(&mut func_strs[i]);
|
ui.text_edit_singleline(&mut self.func_strs[i]);
|
||||||
});
|
});
|
||||||
|
|
||||||
let integral: bool = if integral_toggle {
|
let integral: bool = if integral_toggle {
|
||||||
@ -174,13 +158,13 @@ impl epi::App for MathApp {
|
|||||||
function.is_integral()
|
function.is_integral()
|
||||||
};
|
};
|
||||||
|
|
||||||
if !func_strs[i].is_empty() {
|
if !self.func_strs[i].is_empty() {
|
||||||
let proc_func_str = add_asterisks(func_strs[i].clone());
|
let proc_func_str = add_asterisks(self.func_strs[i].clone());
|
||||||
let func_test_output = test_func(proc_func_str.clone());
|
let func_test_output = test_func(proc_func_str.clone());
|
||||||
if !func_test_output.is_empty() {
|
if !func_test_output.is_empty() {
|
||||||
parse_error += &func_test_output;
|
parse_error += &func_test_output;
|
||||||
} else {
|
} else {
|
||||||
function.update(proc_func_str, integral, Some(*integral_min_x), Some(*integral_max_x), Some(*integral_num));
|
function.update(proc_func_str, integral, Some(self.integral_min_x), Some(self.integral_max_x), Some(self.integral_num));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,6 +197,8 @@ impl epi::App for MathApp {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let step = (self.integral_min_x - self.integral_max_x).abs() / (self.integral_num as f64);
|
||||||
|
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
if !parse_error.is_empty() {
|
if !parse_error.is_empty() {
|
||||||
ui.label(format!("Error: {}", parse_error));
|
ui.label(format!("Error: {}", parse_error));
|
||||||
@ -220,7 +206,6 @@ impl epi::App for MathApp {
|
|||||||
}
|
}
|
||||||
let available_width: usize = ui.available_width() as usize;
|
let available_width: usize = ui.available_width() as usize;
|
||||||
|
|
||||||
let step = self.get_step();
|
|
||||||
let mut area_list: Vec<f64> = Vec::new();
|
let mut area_list: Vec<f64> = Vec::new();
|
||||||
Plot::new("plot")
|
Plot::new("plot")
|
||||||
.set_margin_fraction(Vec2::ZERO)
|
.set_margin_fraction(Vec2::ZERO)
|
||||||
@ -232,7 +217,10 @@ impl epi::App for MathApp {
|
|||||||
let minx_bounds: f64 = bounds.min()[0];
|
let minx_bounds: f64 = bounds.min()[0];
|
||||||
let maxx_bounds: f64 = bounds.max()[0];
|
let maxx_bounds: f64 = bounds.max()[0];
|
||||||
|
|
||||||
for (i, function) in self.functions.iter_mut().enumerate() {
|
let mut i: usize = 0;
|
||||||
|
let mut functions_2: Vec<Function> = Vec::new();
|
||||||
|
for function_1 in self.functions.iter_mut() {
|
||||||
|
let function = function_1;
|
||||||
function.update_bounds(minx_bounds, maxx_bounds, available_width);
|
function.update_bounds(minx_bounds, maxx_bounds, available_width);
|
||||||
|
|
||||||
if self.func_strs[i].is_empty() {
|
if self.func_strs[i].is_empty() {
|
||||||
@ -252,7 +240,10 @@ impl epi::App for MathApp {
|
|||||||
} else {
|
} else {
|
||||||
area_list.push(0.0);
|
area_list.push(0.0);
|
||||||
}
|
}
|
||||||
|
i += 1;
|
||||||
|
functions_2.push(function.clone());
|
||||||
}
|
}
|
||||||
|
self.functions = functions_2;
|
||||||
});
|
});
|
||||||
|
|
||||||
let duration = start.elapsed();
|
let duration = start.elapsed();
|
||||||
|
|||||||
108
src/function.rs
108
src/function.rs
@ -1,4 +1,3 @@
|
|||||||
use crate::misc::Cache;
|
|
||||||
use egui::plot::Value;
|
use egui::plot::Value;
|
||||||
use egui::widgets::plot::Bar;
|
use egui::widgets::plot::Bar;
|
||||||
use meval::Expr;
|
use meval::Expr;
|
||||||
@ -38,8 +37,8 @@ pub struct Function {
|
|||||||
max_x: f64,
|
max_x: f64,
|
||||||
pixel_width: usize,
|
pixel_width: usize,
|
||||||
|
|
||||||
back_cache: Cache<Vec<Value>>,
|
back_cache: Option<Vec<Value>>,
|
||||||
front_cache: Cache<(Vec<Bar>, f64)>,
|
front_cache: Option<(Vec<Bar>, f64)>,
|
||||||
|
|
||||||
integral: bool,
|
integral: bool,
|
||||||
integral_min_x: f64,
|
integral_min_x: f64,
|
||||||
@ -47,6 +46,26 @@ pub struct Function {
|
|||||||
integral_num: usize,
|
integral_num: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Clone for Function {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
let expr: Expr = self.func_str.parse().unwrap();
|
||||||
|
let func = expr.bind("x").unwrap();
|
||||||
|
Self {
|
||||||
|
function: Box::new(func),
|
||||||
|
func_str: self.func_str.clone(),
|
||||||
|
min_x: self.min_x.clone(),
|
||||||
|
max_x: self.max_x.clone(),
|
||||||
|
pixel_width: self.pixel_width.clone(),
|
||||||
|
back_cache: self.back_cache.clone(),
|
||||||
|
front_cache: self.front_cache.clone(),
|
||||||
|
integral: self.integral.clone(),
|
||||||
|
integral_min_x: self.integral_min_x.clone(),
|
||||||
|
integral_max_x: self.integral_max_x.clone(),
|
||||||
|
integral_num: self.integral_num.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
func_str: String, min_x: f64, max_x: f64, pixel_width: usize, integral: bool,
|
func_str: String, min_x: f64, max_x: f64, pixel_width: usize, integral: bool,
|
||||||
@ -65,14 +84,14 @@ impl Function {
|
|||||||
|
|
||||||
let expr: Expr = func_str.parse().unwrap();
|
let expr: Expr = func_str.parse().unwrap();
|
||||||
let func = expr.bind("x").unwrap();
|
let func = expr.bind("x").unwrap();
|
||||||
let mut output = Self {
|
Self {
|
||||||
function: Box::new(func),
|
function: Box::new(func),
|
||||||
func_str,
|
func_str,
|
||||||
min_x,
|
min_x,
|
||||||
max_x,
|
max_x,
|
||||||
pixel_width,
|
pixel_width,
|
||||||
back_cache: Cache::new_empty(),
|
back_cache: None,
|
||||||
front_cache: Cache::new_empty(),
|
front_cache: None,
|
||||||
integral,
|
integral,
|
||||||
integral_min_x: match integral_min_x {
|
integral_min_x: match integral_min_x {
|
||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
@ -83,10 +102,7 @@ impl Function {
|
|||||||
None => f64::NAN,
|
None => f64::NAN,
|
||||||
},
|
},
|
||||||
integral_num: integral_num.unwrap_or(0),
|
integral_num: integral_num.unwrap_or(0),
|
||||||
};
|
}
|
||||||
|
|
||||||
output.func_str = "".to_string();
|
|
||||||
output
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Runs the internal function to get values
|
// Runs the internal function to get values
|
||||||
@ -136,7 +152,7 @@ impl Function {
|
|||||||
| (integral_max_x != Some(self.integral_max_x))
|
| (integral_max_x != Some(self.integral_max_x))
|
||||||
| (integral_num != Some(self.integral_num))
|
| (integral_num != Some(self.integral_num))
|
||||||
{
|
{
|
||||||
self.front_cache.invalidate();
|
self.front_cache = None;
|
||||||
self.integral_min_x = integral_min_x.expect("");
|
self.integral_min_x = integral_min_x.expect("");
|
||||||
self.integral_max_x = integral_max_x.expect("");
|
self.integral_max_x = integral_max_x.expect("");
|
||||||
self.integral_num = integral_num.expect("");
|
self.integral_num = integral_num.expect("");
|
||||||
@ -145,8 +161,46 @@ impl Function {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_bounds(&mut self, min_x: f64, max_x: f64, pixel_width: usize) {
|
pub fn update_bounds(&mut self, min_x: f64, max_x: f64, pixel_width: usize) {
|
||||||
if (min_x != self.min_x) | (max_x != self.max_x) | (pixel_width != self.pixel_width) {
|
if pixel_width != self.pixel_width {
|
||||||
self.back_cache.invalidate();
|
self.back_cache = None;
|
||||||
|
self.min_x = min_x;
|
||||||
|
self.max_x = max_x;
|
||||||
|
self.pixel_width = pixel_width;
|
||||||
|
} else if ((min_x != self.min_x) | (max_x != self.max_x))
|
||||||
|
&& self.back_cache.is_some()
|
||||||
|
&& false
|
||||||
|
{
|
||||||
|
println!("rebuilding cache");
|
||||||
|
let range_new: f64 = max_x.abs() + min_x.abs();
|
||||||
|
|
||||||
|
let resolution: f64 = (self.pixel_width as f64 / range_new) as f64;
|
||||||
|
let movement_right = min_x > self.min_x;
|
||||||
|
let mut new_back: Vec<Value> = self
|
||||||
|
.back_cache
|
||||||
|
.as_ref()
|
||||||
|
.expect("")
|
||||||
|
.clone()
|
||||||
|
.iter()
|
||||||
|
.filter(|ele| (ele.x >= min_x) && (min_x >= ele.x))
|
||||||
|
.map(|ele| *ele)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let x_to_go = match movement_right {
|
||||||
|
true => ((self.max_x - max_x) * resolution) as usize,
|
||||||
|
false => ((self.min_x - min_x) * resolution) as usize,
|
||||||
|
};
|
||||||
|
|
||||||
|
new_back.append(
|
||||||
|
&mut (1..x_to_go)
|
||||||
|
.map(|x| (x as f64 / resolution as f64) + min_x)
|
||||||
|
.map(|x| (x, self.run_func(x)))
|
||||||
|
.map(|(x, y)| Value::new(x, y))
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
|
||||||
|
self.back_cache = Some(new_back);
|
||||||
|
} else {
|
||||||
|
self.back_cache = None;
|
||||||
self.min_x = min_x;
|
self.min_x = min_x;
|
||||||
self.max_x = max_x;
|
self.max_x = max_x;
|
||||||
self.pixel_width = pixel_width;
|
self.pixel_width = pixel_width;
|
||||||
@ -163,40 +217,38 @@ impl Function {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn run(&mut self) -> FunctionOutput {
|
pub fn run(&mut self) -> FunctionOutput {
|
||||||
let front_values: Vec<Value> = match self.back_cache.is_valid() {
|
let front_values: Vec<Value> = match self.back_cache.is_some() {
|
||||||
|
true => self.back_cache.as_ref().expect("").clone(),
|
||||||
false => {
|
false => {
|
||||||
let absrange = (self.max_x - self.min_x).abs();
|
let absrange = (self.max_x - self.min_x).abs();
|
||||||
let resolution: f64 = (self.pixel_width as f64 / absrange) as f64;
|
let resolution: f64 = (self.pixel_width as f64 / absrange) as f64;
|
||||||
let front_data: Vec<(f64, f64)> = (1..=self.pixel_width)
|
let front_data: Vec<Value> = (1..=self.pixel_width)
|
||||||
.map(|x| (x as f64 / resolution as f64) + self.min_x)
|
.map(|x| (x as f64 / resolution as f64) + self.min_x)
|
||||||
// .step_by()
|
|
||||||
.map(|x| (x, self.run_func(x)))
|
.map(|x| (x, self.run_func(x)))
|
||||||
|
.map(|(x, y)| Value::new(x, y))
|
||||||
.collect();
|
.collect();
|
||||||
// println!("{} {}", front_data.len(), front_data.len() as f64/absrange);
|
// println!("{} {}", front_data.len(), front_data.len() as f64/absrange);
|
||||||
|
|
||||||
let output: Vec<Value> =
|
self.back_cache = Some(front_data.clone());
|
||||||
front_data.iter().map(|(x, y)| Value::new(*x, *y)).collect();
|
front_data
|
||||||
self.back_cache.set(output.clone());
|
|
||||||
output
|
|
||||||
}
|
}
|
||||||
true => self.back_cache.get().clone(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.integral {
|
if self.integral {
|
||||||
let back_bars: (Vec<Bar>, f64) = match self.front_cache.is_valid() {
|
let back_bars: (Vec<Bar>, f64) = match self.front_cache.is_some() {
|
||||||
|
true => {
|
||||||
|
let cache = self.front_cache.as_ref().expect("");
|
||||||
|
let vec_bars: Vec<Bar> = cache.0.to_vec();
|
||||||
|
(vec_bars, cache.1)
|
||||||
|
}
|
||||||
false => {
|
false => {
|
||||||
let (data, area) = self.integral_rectangles();
|
let (data, area) = self.integral_rectangles();
|
||||||
let bars: Vec<Bar> = data.iter().map(|(x, y)| Bar::new(*x, *y)).collect();
|
let bars: Vec<Bar> = data.iter().map(|(x, y)| Bar::new(*x, *y)).collect();
|
||||||
|
|
||||||
let output = (bars, area);
|
let output = (bars, area);
|
||||||
self.front_cache.set(output.clone());
|
self.front_cache = Some(output.clone());
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
true => {
|
|
||||||
let cache = self.front_cache.get();
|
|
||||||
let vec_bars: Vec<Bar> = cache.0.to_vec();
|
|
||||||
(vec_bars, cache.1)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
FunctionOutput::new(front_values, Some(back_bars))
|
FunctionOutput::new(front_values, Some(back_bars))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
56
src/misc.rs
56
src/misc.rs
@ -116,40 +116,6 @@ pub fn digits_precision(x: f64, digits: usize) -> f64 {
|
|||||||
(x * large_number).round() / large_number
|
(x * large_number).round() / large_number
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Cache<T> {
|
|
||||||
backing_data: Option<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Cache<T> {
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[inline]
|
|
||||||
pub fn new(backing_data: T) -> Self {
|
|
||||||
Self {
|
|
||||||
backing_data: Some(backing_data),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn new_empty() -> Self { Self { backing_data: None } }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn get(&self) -> &T {
|
|
||||||
match &self.backing_data {
|
|
||||||
Some(x) => x,
|
|
||||||
None => panic!("self.backing_data is None"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn set(&mut self, data: T) { self.backing_data = Some(data); }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn invalidate(&mut self) { self.backing_data = None; }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn is_valid(&self) -> bool { self.backing_data.is_some() }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests to make sure my cursed function works as intended
|
// Tests to make sure my cursed function works as intended
|
||||||
#[test]
|
#[test]
|
||||||
fn asterisk_test() {
|
fn asterisk_test() {
|
||||||
@ -185,25 +151,3 @@ fn asterisk_test() {
|
|||||||
// assert_eq!(&add_asterisks("emax(x)".to_string()), "e*max(x)");
|
// assert_eq!(&add_asterisks("emax(x)".to_string()), "e*max(x)");
|
||||||
// assert_eq!(&add_asterisks("pisin(x)".to_string()), "pi*sin(x)");
|
// assert_eq!(&add_asterisks("pisin(x)".to_string()), "pi*sin(x)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests cache when initialized with value
|
|
||||||
#[test]
|
|
||||||
fn cache_test_full() {
|
|
||||||
let mut cache = Cache::new("data");
|
|
||||||
assert!(cache.is_valid());
|
|
||||||
cache.invalidate();
|
|
||||||
assert!(!cache.is_valid());
|
|
||||||
cache.set("data2");
|
|
||||||
assert!(cache.is_valid());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests cache when initialized without value
|
|
||||||
#[test]
|
|
||||||
fn cache_test_empty() {
|
|
||||||
let mut cache: Cache<&str> = Cache::new_empty();
|
|
||||||
assert!(!cache.is_valid());
|
|
||||||
cache.invalidate();
|
|
||||||
assert!(!cache.is_valid());
|
|
||||||
cache.set("data");
|
|
||||||
assert!(cache.is_valid());
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user