diff --git a/README.md b/README.md index c4a0f32..7029bf5 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,10 @@ Daisy instead provides four functions (`fromCelsius`, `toCelsius`, `fromFahrenhe - "from" functions take a scalar and return a value in Kelvin: `fromCelsius(0) = 273.15K` - "to" functions take a value in Kelvin and return a scalar: `toCelsius(273.15 K) = 0` +Functions `FtoC` and `CtoF` are also provided: + - `FtoC(x) = toCelsius(fromFahrenheit(x))` + - `CtoF(x) = toFahrenheit(fromCelsius(x))` + ## Multiplication Order diff --git a/src/command/mod.rs b/src/command/mod.rs index ee7bdf5..6d06278 100644 --- a/src/command/mod.rs +++ b/src/command/mod.rs @@ -152,6 +152,9 @@ pub fn do_command( " Fahrenheit to Kelvin [c]fromF, fromFahrenheit[n]\n", " Kelvin to Fahrenheit [c]toF, toFahrenheit[n]\n", "\n", + " Celsius to Fahrenheit [c]CtoF[n]\n", + " Fahrenheit to Celsius [c]FtoC[n]\n", + "\n", " convert to base unit [c]tobase[n]\n", " remove units [c]nounit[n]\n", "\n\n" diff --git a/src/evaluate/function.rs b/src/evaluate/function.rs index 5f3b101..ad8efc4 100644 --- a/src/evaluate/function.rs +++ b/src/evaluate/function.rs @@ -1,3 +1,5 @@ +use std::collections::VecDeque; + use crate::parser::Expression; use crate::parser::Function; use crate::parser::Operator; @@ -9,6 +11,7 @@ use crate::quantity::Quantity; use crate::quantity::Scalar; use crate::errors::DaisyError; use crate::context::Context; +use super::evaluate; // If unitless, do nothing // If compatible with radians, convert to radians and return unitless @@ -151,6 +154,33 @@ pub fn eval_function(context: &mut Context, g: &Expression) -> Result { + return Ok(evaluate(context, + &Expression::Operator( + *l + *loc, + Operator::Function(Function::ToFahrenheit), + VecDeque::from(vec![Expression::Operator( + *l + *loc, + Operator::Function(Function::FromCelsius), + VecDeque::from(vec![Expression::Quantity(*l, q.clone())]) + )]) + ) + ).ok()); + }, + + Function::FtoC => { + return Ok(evaluate(context, + &Expression::Operator( + *l + *loc, + Operator::Function(Function::ToCelsius), + VecDeque::from(vec![Expression::Operator( + *l + *loc, + Operator::Function(Function::FromFahrenheit), + VecDeque::from(vec![Expression::Quantity(*l, q.clone())]) + )]) + ) + ).ok()); + }, Function::ToCelsius => { let mut k = Quantity::new_rational(1f64).unwrap(); diff --git a/src/parser/expression/function.rs b/src/parser/expression/function.rs index 24482f7..b65f11c 100644 --- a/src/parser/expression/function.rs +++ b/src/parser/expression/function.rs @@ -37,7 +37,9 @@ pub enum Function { FromCelsius, ToCelsius, FromFahrenheit, - ToFahrenheit + ToFahrenheit, + CtoF, + FtoC, } @@ -74,6 +76,8 @@ impl ToString for Function { Function::ToCelsius => {String::from("tocelsius") }, Function::FromFahrenheit => { String::from("fromfahrenheit") }, Function::ToFahrenheit => { String::from("tofahrenheit") }, + Function::FtoC => { String::from("FtoC") }, + Function::CtoF => { String::from("CtoF") }, } } @@ -126,6 +130,11 @@ impl Function { "fromF" => {Some(Function::FromFahrenheit)}, "fromfahrenheit" => {Some(Function::FromFahrenheit)}, "fromFahrenheit" => {Some(Function::FromFahrenheit)}, + + "FtoC" => {Some(Function::FtoC)}, + "ftoc" => {Some(Function::FtoC)}, + "ctof" => {Some(Function::CtoF)}, + "CtoF" => {Some(Function::CtoF)}, _ => None } } diff --git a/src/tests.rs b/src/tests.rs index e765a57..c5d2e9d 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -232,5 +232,11 @@ fn functions() { good_expr("2", "nounit(2 mm)"); good_expr("2", "nounit(2 meter * second)"); + + good_expr("37.778", "FtoC(100)"); + good_expr("73.399", "CtoF(23)"); + good_expr("-17.778", "FtoC(0)"); + good_expr("31.999", "CtoF(0)"); + //good_expr("5000 m²·g/(s²·A²)", "tobase(5H)"); } \ No newline at end of file