Added celsius and fahrenheit functions

pull/2/head
Mark 2023-08-02 11:39:36 -07:00
parent 578072a7e7
commit f8b1a11bb7
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
3 changed files with 124 additions and 36 deletions

View File

@ -39,7 +39,35 @@ pub fn eval_function(g: &Expression) -> Result<Expression, (LineLocation, EvalEr
Function::NoUnit => { return Ok(Expression::Quantity(*loc + *l, q.without_unit())); } Function::NoUnit => { return Ok(Expression::Quantity(*loc + *l, q.without_unit())); }
Function::ToBase => { return Ok(Expression::Quantity(*loc + *l, q.convert_to_base())); } Function::ToBase => { return Ok(Expression::Quantity(*loc + *l, q.convert_to_base())); }
// Trigonometry
Function::Abs => {
if !q.unitless() { return Err((*loc + *l, EvalError::IncompatibleUnit));}
return Ok(Expression::Quantity(*loc + *l, q.abs()));
},
Function::Floor => {
if !q.unitless() { return Err((*loc + *l, EvalError::IncompatibleUnit));}
return Ok(Expression::Quantity(*loc + *l, q.floor()));
},
Function::Ceil => {
if !q.unitless() { return Err((*loc + *l, EvalError::IncompatibleUnit));}
return Ok(Expression::Quantity(*loc + *l, q.ceil()));
},
Function::Round => {
if !q.unitless() { return Err((*loc + *l, EvalError::IncompatibleUnit));}
return Ok(Expression::Quantity(*loc + *l, q.round()));
},
Function::NaturalLog => {
if !q.unitless() { return Err((*loc + *l, EvalError::IncompatibleUnit));}
return Ok(Expression::Quantity(*loc + *l, q.ln()));
},
Function::TenLog => {
if !q.unitless() { return Err((*loc + *l, EvalError::IncompatibleUnit));}
return Ok(Expression::Quantity(*loc + *l, q.log10()));
},
Function::Sin => { Function::Sin => {
let Ok(q) = to_radians(q.clone()) else { return Err((*loc + *l, EvalError::IncompatibleUnit)); }; let Ok(q) = to_radians(q.clone()) else { return Err((*loc + *l, EvalError::IncompatibleUnit)); };
return Ok(Expression::Quantity(*loc + *l, q.sin())); return Ok(Expression::Quantity(*loc + *l, q.sin()));
@ -88,44 +116,73 @@ pub fn eval_function(g: &Expression) -> Result<Expression, (LineLocation, EvalEr
let Ok(q) = to_radians(q.clone()) else { return Err((*loc + *l, EvalError::IncompatibleUnit)); }; let Ok(q) = to_radians(q.clone()) else { return Err((*loc + *l, EvalError::IncompatibleUnit)); };
return Ok(Expression::Quantity(*loc + *l, q.coth())); return Ok(Expression::Quantity(*loc + *l, q.coth()));
}, },
_ => {} Function::Asin => {
if !q.unitless() { return Err((*loc + *l, EvalError::IncompatibleUnit));}
return Ok(Expression::Quantity(*loc + *l, q.asin()));
},
Function::Acos => {
if !q.unitless() { return Err((*loc + *l, EvalError::IncompatibleUnit));}
return Ok(Expression::Quantity(*loc + *l, q.acos()));
},
Function::Atan => {
if !q.unitless() { return Err((*loc + *l, EvalError::IncompatibleUnit));}
return Ok(Expression::Quantity(*loc + *l, q.atan()));
},
Function::Asinh => {
if !q.unitless() { return Err((*loc + *l, EvalError::IncompatibleUnit));}
return Ok(Expression::Quantity(*loc + *l, q.asinh()));
},
Function::Acosh => {
if !q.unitless() { return Err((*loc + *l, EvalError::IncompatibleUnit));}
return Ok(Expression::Quantity(*loc + *l, q.acosh()));
},
Function::Atanh => {
if !q.unitless() { return Err((*loc + *l, EvalError::IncompatibleUnit));}
return Ok(Expression::Quantity(*loc + *l, q.atanh()));
},
Function::ToCelsius => {
let mut k = Quantity::new_rational(1f64).unwrap();
k.insert_unit(FreeUnit::from_whole(WholeUnit::Kelvin), Scalar::new_rational(1f64).unwrap());
let Some(q) = q.convert_to(k) else { return Err((*loc + *l, EvalError::IncompatibleUnit)) };
let mut r = q.without_unit();
r += Quantity::new_rational(-273.15f64).unwrap();
return Ok(Expression::Quantity(*loc + *l, r));
},
Function::ToFahrenheit => {
let mut k = Quantity::new_rational(1f64).unwrap();
k.insert_unit(FreeUnit::from_whole(WholeUnit::Kelvin), Scalar::new_rational(1f64).unwrap());
let Some(q) = q.convert_to(k) else { return Err((*loc + *l, EvalError::IncompatibleUnit)) };
let mut r = q.without_unit();
r *= Quantity::new_rational_from_frac(9i64, 5i64).unwrap();
r += Quantity::new_rational(-459.67).unwrap();
return Ok(Expression::Quantity(*loc + *l, r));
},
Function::FromCelsius => {
if !q.unitless() { return Err((*loc + *l, EvalError::IncompatibleUnit));}
let mut r = Quantity::new_rational(273.15f64).unwrap();
r += q.clone();
r.insert_unit(FreeUnit::from_whole(WholeUnit::Kelvin), Scalar::new_rational(1f64).unwrap());
return Ok(Expression::Quantity(*loc + *l, r));
},
Function::FromFahrenheit => {
if !q.unitless() { return Err((*loc + *l, EvalError::IncompatibleUnit));}
let mut r = q.clone();
r += Quantity::new_rational(459.67).unwrap();
r *= Quantity::new_rational_from_frac(5i64, 9i64).unwrap();
r.insert_unit(FreeUnit::from_whole(WholeUnit::Kelvin), Scalar::new_rational(1f64).unwrap());
return Ok(Expression::Quantity(*loc + *l, r));
} }
if !q.unitless() {
return Err((*loc + *l, EvalError::IncompatibleUnit));
}
match f {
Function::Abs => { return Ok(Expression::Quantity(*loc + *l, q.abs())); },
Function::Floor => { return Ok(Expression::Quantity(*loc + *l, q.floor())); },
Function::Ceil => { return Ok(Expression::Quantity(*loc + *l, q.ceil())); },
Function::Round => { return Ok(Expression::Quantity(*loc + *l, q.round())); },
Function::NaturalLog => { return Ok(Expression::Quantity(*loc + *l, q.ln())); },
Function::TenLog => { return Ok(Expression::Quantity(*loc + *l, q.log10())); },
Function::Asin => { return Ok(Expression::Quantity(*loc + *l, q.asin())); },
Function::Acos => { return Ok(Expression::Quantity(*loc + *l, q.acos())); },
Function::Atan => { return Ok(Expression::Quantity(*loc + *l, q.atan())); },
Function::Asinh => { return Ok(Expression::Quantity(*loc + *l, q.asinh())); },
Function::Acosh => { return Ok(Expression::Quantity(*loc + *l, q.acosh())); },
Function::Atanh => { return Ok(Expression::Quantity(*loc + *l, q.atanh())); },
Function::ToBase
| Function::NoUnit
| Function::Sin
| Function::Cos
| Function::Tan
| Function::Csc
| Function::Sec
| Function::Cot
| Function::Sinh
| Function::Cosh
| Function::Tanh
| Function::Csch
| Function::Sech
| Function::Coth
=> unreachable!()
} }
} }

View File

@ -33,7 +33,11 @@ pub enum Function {
Coth, Coth,
NoUnit, NoUnit,
ToBase ToBase,
FromCelsius,
ToCelsius,
FromFahrenheit,
ToFahrenheit
} }
@ -66,6 +70,10 @@ impl ToString for Function {
Function::Coth => { String::from("coth") }, Function::Coth => { String::from("coth") },
Function::NoUnit => { String::from("nounit") }, Function::NoUnit => { String::from("nounit") },
Function::ToBase => { String::from("tobase") }, Function::ToBase => { String::from("tobase") },
Function::FromCelsius => { String::from("fromcelsius") },
Function::ToCelsius => {String::from("tocelsius") },
Function::FromFahrenheit => { String::from("fromfahrenheit") },
Function::ToFahrenheit => { String::from("tofahrenheit") },
} }
} }
@ -101,7 +109,20 @@ impl Function {
"coth" => {Some(Function::Coth)}, "coth" => {Some(Function::Coth)},
"nounit" => {Some(Function::NoUnit)}, "nounit" => {Some(Function::NoUnit)},
"tobase" => {Some(Function::ToBase)} "tobase" => {Some(Function::ToBase)},
"toC" => {Some(Function::ToCelsius)},
"fromC" => {Some(Function::FromCelsius)},
"toF" => {Some(Function::ToFahrenheit)},
"fromF" => {Some(Function::FromFahrenheit)},
"tocelsius" => {Some(Function::ToCelsius)},
"fromcelsius" => {Some(Function::FromCelsius)},
"tofahrenheit" => {Some(Function::ToFahrenheit)},
"fromfahrenheit" => {Some(Function::FromFahrenheit)},
"toCelsius" => {Some(Function::ToCelsius)},
"fromCelsius" => {Some(Function::FromCelsius)},
"toFahrenheit" => {Some(Function::ToFahrenheit)},
"fromFahrenheit" => {Some(Function::FromFahrenheit)},
_ => None _ => None
} }
} }

View File

@ -90,6 +90,16 @@ impl Quantity {
}); });
} }
pub fn new_rational_from_frac(a: i64, b: i64) -> Option<Quantity> {
let v = Scalar::new_rational_from_frac(a, b);
if v.is_none() { return None; }
return Some(Quantity{
scalar: v.unwrap(),
unit: Unit::new()
});
}
pub fn from_scalar(s: Scalar) -> Quantity { pub fn from_scalar(s: Scalar) -> Quantity {
return Quantity{ return Quantity{
scalar: s, scalar: s,