diff --git a/src/evaluate/function.rs b/src/evaluate/function.rs index 57c07e3..382165f 100644 --- a/src/evaluate/function.rs +++ b/src/evaluate/function.rs @@ -11,6 +11,13 @@ pub fn eval_function(f: &Function, args: &VecDeque) -> Result { return Ok(Token::Quantity(q.without_unit())); } + Function::ToBase => { return Ok(Token::Quantity(q.convert_to_base())); } + _ => {} + } + if !q.unitless() { return Err(EvalError::IncompatibleUnit); } @@ -89,5 +96,8 @@ pub fn eval_function(f: &Function, args: &VecDeque) -> Result panic!() } } \ No newline at end of file diff --git a/src/parser/token/function.rs b/src/parser/token/function.rs index bf3f7d1..d1efd74 100644 --- a/src/parser/token/function.rs +++ b/src/parser/token/function.rs @@ -28,10 +28,14 @@ pub enum Function { Csch, Sech, Coth, + + NoUnit, + ToBase } -impl Function { - pub fn to_string(&self) -> String { + +impl ToString for Function { + fn to_string(&self) -> String { match self { Function::Abs => { String::from("abs") }, Function::Floor => { String::from("floor") }, @@ -57,6 +61,45 @@ impl Function { Function::Csch => { String::from("csch") }, Function::Sech => { String::from("sech") }, Function::Coth => { String::from("coth") }, + Function::NoUnit => { String::from("nounit") }, + Function::ToBase => { String::from("tobase") }, + } + } + +} + +impl Function { + #[inline(always)] + pub fn from_string(s: &str) -> Option { + match s { + "abs" => {Some(Function::Abs)}, + "floor" => {Some(Function::Floor)}, + "ceil" => {Some(Function::Ceil)}, + "round" => {Some(Function::Round)}, + "ln" => {Some(Function::NaturalLog)}, + "log" => {Some(Function::TenLog)}, + "sin" => {Some(Function::Sin)}, + "cos" => {Some(Function::Cos)}, + "tan" => {Some(Function::Tan)}, + "asin" => {Some(Function::Asin)}, + "acos" => {Some(Function::Acos)}, + "atan" => {Some(Function::Atan)}, + "csc" => {Some(Function::Csc)}, + "secant" => {Some(Function::Sec)}, + "cot" => {Some(Function::Cot)}, + "sinh" => {Some(Function::Sinh)}, + "cosh" => {Some(Function::Cosh)}, + "tanh" => {Some(Function::Tanh)}, + "asinh" => {Some(Function::Asinh)}, + "acosh" => {Some(Function::Acosh)}, + "atanh" => {Some(Function::Atanh)}, + "csch" => {Some(Function::Csch)}, + "sech" => {Some(Function::Sech)}, + "coth" => {Some(Function::Coth)}, + + "nounit" => {Some(Function::NoUnit)}, + "tobase" => {Some(Function::ToBase)} + _ => None } } } \ No newline at end of file diff --git a/src/parser/token/operator.rs b/src/parser/token/operator.rs index d43b1c5..7cd0bd2 100644 --- a/src/parser/token/operator.rs +++ b/src/parser/token/operator.rs @@ -61,7 +61,13 @@ impl Operator { #[inline(always)] pub fn from_string(s: &str) -> Option { - match s { + + let f = Function::from_string(s); + if let Some(f) = f { + return Some(Operator::Function(f)); + } + + return match s { "+" => {Some( Operator::Add )}, "-" => {Some( Operator::Subtract )}, "neg" => {Some( Operator::Negative )}, @@ -76,32 +82,8 @@ impl Operator { "!" => {Some( Operator::Factorial )}, "sqrt"|"rt"|"√" => {Some( Operator::Sqrt )}, - "abs" => {Some( Operator::Function(Function::Abs) )}, - "floor" => {Some( Operator::Function(Function::Floor) )}, - "ceil" => {Some( Operator::Function(Function::Ceil) )}, - "round" => {Some( Operator::Function(Function::Round) )}, - "ln" => {Some( Operator::Function(Function::NaturalLog) )}, - "log" => {Some( Operator::Function(Function::TenLog) )}, - "sin" => {Some( Operator::Function(Function::Sin) )}, - "cos" => {Some( Operator::Function(Function::Cos) )}, - "tan" => {Some( Operator::Function(Function::Tan) )}, - "asin" => {Some( Operator::Function(Function::Asin) )}, - "acos" => {Some( Operator::Function(Function::Acos) )}, - "atan" => {Some( Operator::Function(Function::Atan) )}, - "csc" => {Some( Operator::Function(Function::Csc) )}, - "secant" => {Some( Operator::Function(Function::Sec) )}, - "cot" => {Some( Operator::Function(Function::Cot) )}, - "sinh" => {Some( Operator::Function(Function::Sinh) )}, - "cosh" => {Some( Operator::Function(Function::Cosh) )}, - "tanh" => {Some( Operator::Function(Function::Tanh) )}, - "asinh" => {Some( Operator::Function(Function::Asinh) )}, - "acosh" => {Some( Operator::Function(Function::Acosh) )}, - "atanh" => {Some( Operator::Function(Function::Atanh) )}, - "csch" => {Some( Operator::Function(Function::Csch) )}, - "sech" => {Some( Operator::Function(Function::Sech) )}, - "coth" => {Some( Operator::Function(Function::Coth) )}, _ => None - } + }; } #[inline(always)] diff --git a/src/quantity/quantity.rs b/src/quantity/quantity.rs index b31dc3f..9175c37 100644 --- a/src/quantity/quantity.rs +++ b/src/quantity/quantity.rs @@ -99,16 +99,19 @@ impl Quantity { pub fn insert_unit(&mut self, ui: FreeUnit, pi: Scalar) { self.unit.insert(ui, pi) } pub fn set_unit(&mut self, u: Unit) { self.unit = u; } + pub fn without_unit(&self) -> Quantity { Quantity::from_scalar(self.scalar.clone()) } - - pub fn convert_to(self, other: Quantity) -> Option { + pub fn convert_to(&self, other: Quantity) -> Option { if !self.unit.compatible_with(&other.unit) { return None; } + let n = self.clone(); let fa = self.unit.to_base_factor(); let fb = other.unit.to_base_factor(); - return Some(self.mul_no_convert(fa).div_no_convert(fb)) + return Some(n.mul_no_convert(fa).div_no_convert(fb)) } + + pub fn convert_to_base(&self) -> Quantity { self.convert_to(self.unit.to_base()).unwrap() } } diff --git a/src/quantity/unit/freeunit.rs b/src/quantity/unit/freeunit.rs index 5c371cd..6aea210 100644 --- a/src/quantity/unit/freeunit.rs +++ b/src/quantity/unit/freeunit.rs @@ -51,7 +51,7 @@ impl FreeUnit { } // Get this unit in terms of base units - pub fn get_base(&self) -> Quantity { + pub fn to_base(&self) -> Quantity { let q = self.whole.base_factor(); let mut q = q.unwrap_or(Quantity::new_rational_from_string("1").unwrap()); diff --git a/src/quantity/unit/unit.rs b/src/quantity/unit/unit.rs index 0bc77b9..5884c6b 100644 --- a/src/quantity/unit/unit.rs +++ b/src/quantity/unit/unit.rs @@ -123,7 +123,7 @@ impl Unit { flag = false; for (uo, po) in other.get_val() { if { - us.get_base().unit.compatible_with(&uo.get_base().unit) + us.to_base().unit.compatible_with(&uo.to_base().unit) } { factor.insert_unit(us.clone(), po.clone()); flag = true; @@ -141,7 +141,7 @@ impl Unit { flag = false; for (us, _) in self.get_val() { if { - us.get_base().unit.compatible_with(&uo.get_base().unit) + us.to_base().unit.compatible_with(&uo.to_base().unit) } { factor.insert_unit(us.clone(), po.clone()); flag = true; @@ -186,11 +186,21 @@ impl Unit { return q; } + + pub fn to_base(&self) -> Quantity { + let mut q = Quantity::new_rational(1f64).unwrap(); + + for (u, p) in self.get_val().iter() { + let b = u.to_base(); + q.mul_assign_no_convert(b.pow(Quantity::from_scalar(p.clone()))); + } + + return q; + } } impl Unit { pub fn from_string(s: &str) -> Option { - let b = freeunit_from_string(s); if b.is_none() { return None; } let b = Unit::from_free(b.unwrap());