tiffany352 / rink-rs

Unit conversion tool and library written in rust

Home Page:https://rinkcalc.app/about

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

trigonometric functions have confusing unit behavior

xeniarose opened this issue · comments

commented

The following in eval.rs clones the input units for all trig functions

Function::Sin => func!(
fn sin(num: Number) {
Ok(Value::Number(Number {
value: Numeric::Float(num.value.to_f64().sin()),
unit: num.unit.clone(),
}))
}
),
Function::Cos => func!(
fn cos(num: Number) {
Ok(Value::Number(Number {
value: Numeric::Float(num.value.to_f64().cos()),
unit: num.unit.clone(),
}))
}
),
Function::Tan => func!(
fn tan(num: Number) {
Ok(Value::Number(Number {
value: Numeric::Float(num.value.to_f64().tan()),
unit: num.unit.clone(),
}))
}
),
Function::Asin => func!(
fn asin(num: Number) {
Ok(Value::Number(Number {
value: Numeric::Float(num.value.to_f64().asin()),
unit: num.unit.clone(),
}))
}
),
Function::Acos => func!(
fn acos(num: Number) {
Ok(Value::Number(Number {
value: Numeric::Float(num.value.to_f64().acos()),
unit: num.unit.clone(),
}))
}
),
Function::Atan => func!(
fn atan(num: Number) {
Ok(Value::Number(Number {
value: Numeric::Float(num.value.to_f64().atan()),
unit: num.unit.clone(),
}))
}
),
Function::Atan2 => func!(
fn atan2(x: Number, y: Number) {
if x.unit != y.unit {
Err("Arguments to atan2 must have matching dimensionality".to_string())
} else {
Ok(Value::Number(Number {
value: Numeric::Float(x.value.to_f64().atan2(y.value.to_f64())),
unit: x.unit.clone(),
}))
}
}
),

this results in some confusing behavior when running trig functions with units

> sin(10 deg)
approx. 173.6481 milliradian (angle)
> atan2(5 ft, 2 ft)
approx. 1.190289 meter (length)

i think that the following behavior would make more sense:

  • sin, cos, and tan should require either dimensionless or angle units as input, and provide a dimensionless output
  • asin, acos, atan, should require dimensionless input and provide angle output
  • atan2 should provide angle output, and retain its current check for the dimensionality of the two inputs being the same

if you think input unit constraints would be too much, implementing just the output unit changes would also be fine. i can make a PR for this if these changes are wanted

Sorry it took so long to get around to this. I agree, this is a much better way to handle the units on these functions.