diff --git a/src/nodes/eval.rs b/src/nodes/eval.rs index 33c606b..2ebfee0 100644 --- a/src/nodes/eval.rs +++ b/src/nodes/eval.rs @@ -83,41 +83,111 @@ fn collapse_toplevel(nodes: &mut Vec, mut end: usize) -> Result<(), Error> return Err(Error::MissingArgument(node.clone())); }; - function.apply_to(n); + function.for_float()(n); nodes.remove(start + index); end -= 1; } - macro_rules! collapse_operator { - ($operator:expr) => { - while let Some(index) = nodes[start..end] - .iter() - .position(|n| *n == Node::Operator($operator)) - { - let lhs = match nodes.remove(start + index - 1) { - Node::Number(n) => n, - n => return Err(Error::InvalidOperand(n)), - }; - end -= 1; - match nodes.get_mut(start + index) { - None => return Err(Error::OutOfBounds(Nodes(nodes.clone()), start + index)), - - Some(Node::Number(n)) => $operator.apply_to(n, lhs), - Some(n) => return Err(Error::InvalidOperand(n.clone())), - }; - - nodes.remove(start + index - 1); - end -= 1; - } + while let Some(operator) = nodes[start..end] + .iter() + .position(|n| *n == Node::Operator(Operator::Exp)) + { + let lhs = match nodes.remove(start + operator - 1) { + Node::Number(n) => n, + n => return Err(Error::InvalidOperand(n)), }; + end -= 1; + match nodes.get_mut(start + operator) { + None => return Err(Error::OutOfBounds(Nodes(nodes.clone()), start + operator)), + + Some(Node::Number(n)) => n.pow_from(lhs), + Some(n) => return Err(Error::InvalidOperand(n.clone())), + }; + + nodes.remove(start + operator - 1); + end -= 1; } - collapse_operator!(Operator::Exp); - collapse_operator!(Operator::Div); - collapse_operator!(Operator::Mult); - collapse_operator!(Operator::Minus); - collapse_operator!(Operator::Plus); + while let Some(operator) = nodes[start..end] + .iter() + .position(|n| *n == Node::Operator(Operator::Div)) + { + let lhs = match nodes.remove(start + operator - 1) { + Node::Number(n) => n, + n => return Err(Error::InvalidOperand(n)), + }; + end -= 1; + match nodes.get_mut(start + operator) { + None => return Err(Error::OutOfBounds(Nodes(nodes.clone()), start + operator)), + + Some(Node::Number(n)) => n.div_from(lhs), + Some(n) => return Err(Error::InvalidOperand(n.clone())), + }; + + nodes.remove(start + operator - 1); + end -= 1; + } + + while let Some(operator) = nodes[start..end] + .iter() + .position(|n| *n == Node::Operator(Operator::Mult)) + { + let lhs = match nodes.remove(start + operator - 1) { + Node::Number(n) => n, + n => return Err(Error::InvalidOperand(n)), + }; + end -= 1; + match nodes.get_mut(start + operator) { + None => return Err(Error::OutOfBounds(Nodes(nodes.clone()), start + operator)), + + Some(Node::Number(n)) => n.mul_from(lhs), + Some(n) => return Err(Error::InvalidOperand(n.clone())), + }; + + nodes.remove(start + operator - 1); + end -= 1; + } + + while let Some(operator) = nodes[start..end] + .iter() + .position(|n| *n == Node::Operator(Operator::Minus)) + { + let lhs = match nodes.remove(start + operator - 1) { + Node::Number(n) => n, + n => return Err(Error::InvalidOperand(n)), + }; + end -= 1; + match nodes.get_mut(start + operator) { + None => return Err(Error::OutOfBounds(Nodes(nodes.clone()), start + operator)), + + Some(Node::Number(n)) => n.sub_from(lhs), + Some(n) => return Err(Error::InvalidOperand(n.clone())), + }; + + nodes.remove(start + operator - 1); + end -= 1; + } + + while let Some(operator) = nodes[start..end] + .iter() + .position(|n| *n == Node::Operator(Operator::Plus)) + { + let lhs = match nodes.remove(start + operator - 1) { + Node::Number(n) => n, + n => return Err(Error::InvalidOperand(n)), + }; + end -= 1; + match nodes.get_mut(start + operator) { + None => return Err(Error::OutOfBounds(Nodes(nodes.clone()), start + operator)), + + Some(Node::Number(n)) => n.add_from(lhs), + Some(n) => return Err(Error::InvalidOperand(n.clone())), + }; + + nodes.remove(start + operator - 1); + end -= 1; + } if nodes.len() > 1 { nodes.remove(end); @@ -127,32 +197,21 @@ fn collapse_toplevel(nodes: &mut Vec, mut end: usize) -> Result<(), Error> Ok(()) } -impl Operator { - fn apply_to(&self, rhs: &mut Float, lhs: Float) { - match self { - Self::Plus => Float::add_from(rhs, lhs), - Self::Minus => Float::sub_from(rhs, lhs), - Self::Mult => Float::mul_from(rhs, lhs), - Self::Div => Float::div_from(rhs, lhs), - Self::Exp => Float::pow_from(rhs, lhs), - } - } -} impl Function { - fn apply_to(&self, n: &mut Float) { + fn for_float(&self) -> impl FnMut(&mut Float) { match self { - Self::Sqrt => Float::sqrt_mut(n), + Function::Sqrt => Float::sqrt_mut, - Self::Ln => Float::ln_mut(n), + Function::Ln => Float::ln_mut, - Self::Sine => Float::sin_mut(n), - Self::ArcSine => Float::asin_mut(n), - Self::Cosine => Float::cos_mut(n), - Self::ArcCosine => Float::acos_mut(n), - Self::Tangent => Float::tan_mut(n), - Self::ArcTangent => Float::atan_mut(n), - Self::Secant => Float::sec_mut(n), - Self::CoSecant => Float::csc_mut(n), + Function::Sine => Float::sin_mut, + Function::ArcSine => Float::asin_mut, + Function::Cosine => Float::cos_mut, + Function::ArcCosine => Float::acos_mut, + Function::Tangent => Float::tan_mut, + Function::ArcTangent => Float::atan_mut, + Function::Secant => Float::sec_mut, + Function::CoSecant => Float::csc_mut, } } } diff --git a/src/nodes/parse.rs b/src/nodes/parse.rs index e3da6e6..96d4236 100644 --- a/src/nodes/parse.rs +++ b/src/nodes/parse.rs @@ -1,10 +1,7 @@ use core::f64; use std::str::FromStr; -use rug::{ - Float, - float::{self, ParseFloatError}, -}; +use rug::{Float, float::ParseFloatError}; use crate::nodes::{Function, Node, Nodes, Operator}; @@ -13,7 +10,7 @@ impl Node { Ok(match s { "c" => Self::from(299_792_458), "A" => Self::from(6.02214076e23), - "pi" | "π" => Self::from(float::Constant::Pi), + "pi" | "π" => Self::from(f64::consts::PI), // Planck's constant, in J*s (joule-seconds) "h" => Self::from(6.62607015e-34), "e" => Self::from(f64::consts::E), diff --git a/src/nodes/tests.rs b/src/nodes/tests.rs index 2f22d8a..15b6c21 100644 --- a/src/nodes/tests.rs +++ b/src/nodes/tests.rs @@ -51,8 +51,3 @@ fn constant_implicit_mult() { assert_eq!(eval("2pi"), 6.283185307179586); assert_eq!(eval("pi2"), 6.283185307179586); } - -#[test] -fn pi_precision() { - assert_eq!(eval("sin(pi)"), 0.) -}