diff --git a/Cargo.lock b/Cargo.lock index a8b3e18..a48b2dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,7 +22,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "daisy" -version = "0.2.0" +version = "0.2.1" dependencies = [ "cfg-if", "rug", diff --git a/Cargo.toml b/Cargo.toml index 7db077f..31ee3c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "daisy" -version = "0.2.0" +version = "0.2.1" edition = "2021" [profile.release] diff --git a/src/evaluate/constant.rs b/src/evaluate/constant.rs new file mode 100644 index 0000000..801065b --- /dev/null +++ b/src/evaluate/constant.rs @@ -0,0 +1,23 @@ +use crate::parser::Token; +use crate::parser::Constant; +use crate::quantity::Quantity; + +use super::EvalError; + +pub fn eval_constant(c: &Constant) -> Result { + Ok(match c { + // Mathematical constants + // 100 digits of each. + Constant::Pi => { Token::Quantity(Quantity::new_float_from_string( + "3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067" + ).unwrap())}, + + Constant::E => { Token::Quantity(Quantity::new_float_from_string( + "2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427" + ).unwrap()) }, + + Constant::Phi => { Token::Quantity(Quantity::new_float_from_string( + "1.618033988749894848204586834365638117720309179805762862135448622705260462818902449707207204189391137" + ).unwrap()) }, + }) +} \ No newline at end of file diff --git a/src/evaluate/evaluate.rs b/src/evaluate/evaluate.rs index fe66ef7..bc0503b 100644 --- a/src/evaluate/evaluate.rs +++ b/src/evaluate/evaluate.rs @@ -1,10 +1,12 @@ use crate::parser::Token; -use crate::parser::Constant; -use crate::quantity::Quantity; +use crate::parser::Operator; -use super::operator::op_apply; +use super::operator::eval_operator; +use super::constant::eval_constant; +use super::function::eval_function; use super::EvalError; + pub fn evaluate(t: &Token) -> Result { let mut g = t.clone(); let mut coords: Vec = Vec::with_capacity(16); @@ -21,30 +23,21 @@ pub fn evaluate(t: &Token) -> Result { let p = Token::get_at_coords(&mut g, &coords); + let mut e = p.clone(); - let e: Token = match p { - Token::Quantity(_) => { p.clone() }, - Token::Constant(c) => { - match c { - // Mathematical constants - // 100 digits of each. - Constant::Pi => { Token::Quantity(Quantity::new_float_from_string( - "3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067" - ).unwrap())}, + // Evaluate until we get a single number. + // This loop is necessary because some eval_* functions + // May return an incomplete result. + // ( For example, csc(x) is treated as 1/sin(x) ) + loop { + e = match e { + Token::Quantity(_) => { break; }, + Token::Constant(c) => { eval_constant(&c)? } + Token::Operator(Operator::Function(f), v) => { eval_function(&f, &v)? } + Token::Operator(o, v) => { eval_operator(&o, &v)? } + }; + } - Constant::E => { Token::Quantity(Quantity::new_float_from_string( - "2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427" - ).unwrap()) }, - - Constant::Phi => { Token::Quantity(Quantity::new_float_from_string( - "1.618033988749894848204586834365638117720309179805762862135448622705260462818902449707207204189391137" - ).unwrap()) }, - } - }, - Token::Operator(o,v) => { op_apply(o, &v)? } - }; - - //let e = p.eval()?; *p = e; if coords.len() == 0 { break 'outer; } diff --git a/src/evaluate/function.rs b/src/evaluate/function.rs index 3212145..57c07e3 100644 --- a/src/evaluate/function.rs +++ b/src/evaluate/function.rs @@ -4,18 +4,9 @@ use crate::parser::Token; use crate::parser::Function; use crate::parser::Operator; use super::EvalError; -use super::operator::op_apply; -use crate::quantity::Quantity; -fn eval(t: Token) -> Result { - Ok(match t { - Token::Quantity(_) => { t }, - Token::Constant(_) => { Token::Quantity( Quantity::new_rational_from_string("1").unwrap() ) }, - Token::Operator(mut o, v) => { op_apply(&mut o, &v)? } - }) -} -pub fn func_apply(f: &Function, args: &VecDeque) -> Result { +pub fn eval_function(f: &Function, args: &VecDeque) -> Result { if args.len() != 1 {panic!()}; let a = &args[0]; let Token::Quantity(q) = a else {panic!()}; @@ -42,26 +33,26 @@ pub fn func_apply(f: &Function, args: &VecDeque) -> Result { return Ok( - eval(Token::Operator( + Token::Operator( Operator::Flip, VecDeque::from(vec!(Token::Quantity(q.sin()))) - ))? + ) ); }, Function::Sec => { return Ok( - eval(Token::Operator( + Token::Operator( Operator::Flip, VecDeque::from(vec!(Token::Quantity(q.cos()))) - ))? + ) ); }, Function::Cot => { return Ok( - eval(Token::Operator( + Token::Operator( Operator::Flip, VecDeque::from(vec!(Token::Quantity(q.tan()))) - ))? + ) ); }, @@ -75,26 +66,26 @@ pub fn func_apply(f: &Function, args: &VecDeque) -> Result { return Ok( - eval(Token::Operator( + Token::Operator( Operator::Flip, VecDeque::from(vec!(Token::Quantity(q.sinh()))) - ))? + ) ); }, Function::Sech => { return Ok( - eval(Token::Operator( + Token::Operator( Operator::Flip, VecDeque::from(vec!(Token::Quantity(q.cosh()))) - ))? + ) ); }, Function::Coth => { return Ok( - eval(Token::Operator( + Token::Operator( Operator::Flip, VecDeque::from(vec!(Token::Quantity(q.tanh()))) - ))? + ) ); }, diff --git a/src/evaluate/mod.rs b/src/evaluate/mod.rs index 5408ff2..09355b5 100644 --- a/src/evaluate/mod.rs +++ b/src/evaluate/mod.rs @@ -1,6 +1,8 @@ mod operator; mod function; +mod constant; mod evaluate; + pub use self::evaluate::evaluate; pub enum EvalError { diff --git a/src/evaluate/operator.rs b/src/evaluate/operator.rs index dd6c7bf..3dd7b92 100644 --- a/src/evaluate/operator.rs +++ b/src/evaluate/operator.rs @@ -4,11 +4,15 @@ use crate::quantity::Quantity; use crate::parser::Operator; use crate::parser::Token; use super::EvalError; -use super::function::func_apply; - -pub fn op_apply(op: &mut Operator, args: &VecDeque) -> Result { +pub fn eval_operator(op: &Operator, args: &VecDeque) -> Result { match op { + + // Handled seperately in evaluate.rs + Operator::Function(_) | + + // These are never evaluated, + // but are converted to one of the following instead. Operator::ImplicitMultiply | Operator::Sqrt | Operator::Divide | @@ -156,10 +160,6 @@ pub fn op_apply(op: &mut Operator, args: &VecDeque) -> Result { - return func_apply(f, args); } }; } \ No newline at end of file