exmex
This commit is contained in:
parent
8524d5f57e
commit
12023a3c55
@ -27,7 +27,7 @@ include-flate = { git = "https://github.com/Titaniumtown/include-flate.git" }
|
|||||||
shadow-rs = { version = "0.9", default-features = false }
|
shadow-rs = { version = "0.9", default-features = false }
|
||||||
const_format = { version = "0.2.22", default-features = false, features = ["fmt"] }
|
const_format = { version = "0.2.22", default-features = false, features = ["fmt"] }
|
||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
meval = { git = "https://github.com/Titaniumtown/meval-rs.git" }
|
exmex = { git = "https://github.com/bertiqwerty/exmex.git", branch = "main", features = ["partial"] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
shadow-rs = "0.9"
|
shadow-rs = "0.9"
|
||||||
|
|||||||
@ -271,7 +271,7 @@ impl MathApp {
|
|||||||
| self.last_error.iter().any(|ele| ele.0 == i)
|
| self.last_error.iter().any(|ele| ele.0 == i)
|
||||||
{
|
{
|
||||||
// let proc_func_str = self.func_strs[i].clone();
|
// let proc_func_str = self.func_strs[i].clone();
|
||||||
let func_test_output = test_func(proc_func_str.clone());
|
let func_test_output = test_func(&proc_func_str);
|
||||||
if let Some(test_output_value) = func_test_output {
|
if let Some(test_output_value) = func_test_output {
|
||||||
self.last_error.push((i, test_output_value));
|
self.last_error.push((i, test_output_value));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -1,39 +1,28 @@
|
|||||||
use meval::Expr;
|
use exmex::prelude::*;
|
||||||
|
|
||||||
pub const EPSILON: f64 = 5.0e-7;
|
|
||||||
pub const DOUBLE_EPSILON: f64 = 10.0e-7;
|
|
||||||
|
|
||||||
type BoxFunction = Box<dyn Fn(f64) -> f64>;
|
|
||||||
|
|
||||||
pub struct BackingFunction {
|
pub struct BackingFunction {
|
||||||
function: BoxFunction,
|
function: FlatEx<f64>,
|
||||||
|
derivative: FlatEx<f64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BackingFunction {
|
impl BackingFunction {
|
||||||
pub fn new(func_str: &str) -> Self {
|
pub fn new(func_str: &str) -> Self {
|
||||||
|
let function = exmex::parse::<f64>(func_str).unwrap();
|
||||||
Self {
|
Self {
|
||||||
function: Box::new({
|
function: function.clone(),
|
||||||
let expr: Expr = func_str.parse().unwrap();
|
derivative: function.partial(0).unwrap(),
|
||||||
expr.bind("x").unwrap()
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, x: f64) -> f64 { (self.function)(x) }
|
pub fn get(&self, x: f64) -> f64 { self.function.eval(&[x]).unwrap_or(f64::NAN) }
|
||||||
|
|
||||||
pub fn derivative(&self, x: f64, n: u64) -> f64 {
|
pub fn derivative(&self, x: f64, n: u64) -> f64 {
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return self.get(x);
|
self.get(x)
|
||||||
}
|
} else if n == 1 {
|
||||||
|
self.derivative.eval(&[x]).unwrap_or(f64::NAN)
|
||||||
let (y1, y2) = (
|
} else {
|
||||||
self.derivative(x - EPSILON, n - 1),
|
panic!("n > 1");
|
||||||
(self.derivative(x + EPSILON, n - 1)),
|
|
||||||
);
|
|
||||||
|
|
||||||
match y1 == y2 {
|
|
||||||
true => 0.0,
|
|
||||||
false => (y2 - y1) / DOUBLE_EPSILON,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,33 +99,11 @@ pub fn add_asterisks(function_in: String) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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: String) -> Option<String> {
|
pub fn test_func(function_string: &str) -> Option<String> {
|
||||||
// Factorials do not work, and it would be really difficult to make them work
|
match exmex::parse::<f64>(function_string) {
|
||||||
if function_string.contains('!') {
|
Err(e) => Some(e.to_string()),
|
||||||
return Some("Factorials are unsupported".to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
let new_func_str: String = add_asterisks(function_string);
|
|
||||||
let expr_result = new_func_str.parse();
|
|
||||||
let expr_error = match &expr_result {
|
|
||||||
Ok(_) => None,
|
Ok(_) => None,
|
||||||
Err(error) => Some(format!("{}", error)),
|
|
||||||
};
|
|
||||||
if expr_error.is_some() {
|
|
||||||
return expr_error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let expr: Expr = expr_result.unwrap();
|
|
||||||
let func_result = expr.bind("x");
|
|
||||||
let func_error = match &func_result {
|
|
||||||
Ok(_) => None,
|
|
||||||
Err(error) => Some(format!("{}", error)),
|
|
||||||
};
|
|
||||||
if func_error.is_some() {
|
|
||||||
return func_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests to make sure my cursed function works as intended
|
// Tests to make sure my cursed function works as intended
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user