Moved * / % and ^ to units.rs, added support for 1km/1km
This commit is contained in:
parent
c7141e87ad
commit
1e83f50fbd
@ -1,6 +1,6 @@
|
||||
use decimal::d128;
|
||||
use crate::Token;
|
||||
use crate::units::{Unit, UnitType, Number, convert, add, subtract};
|
||||
use crate::units::{Unit, UnitType, Number, convert, add, subtract, multiply, divide, modulo, pow};
|
||||
use crate::parser::AstNode;
|
||||
use crate::Operator::{Caret, Divide, Minus, Modulo, Multiply, Plus};
|
||||
use crate::Constant::{Pi, E};
|
||||
@ -245,51 +245,20 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
|
||||
Ok(subtract(left, right)?)
|
||||
},
|
||||
Multiply => {
|
||||
if left.unit == Unit::NoUnit && right.unit == Unit::NoUnit {
|
||||
// 3 * 2
|
||||
return Ok(Number::new(left.value * right.value, left.unit))
|
||||
} else if left.unit == Unit::NoUnit && right.unit != Unit::NoUnit {
|
||||
// 3 * 1 km
|
||||
return Ok(Number::new(left.value * right.value, right.unit))
|
||||
} else if right.unit == Unit::NoUnit && left.unit != Unit::NoUnit {
|
||||
// 1 km * 3
|
||||
return Ok(Number::new(left.value * right.value, left.unit))
|
||||
} else {
|
||||
return Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit))
|
||||
}
|
||||
Ok(multiply(left, right)?)
|
||||
// }
|
||||
},
|
||||
Divide => {
|
||||
if left.unit == Unit::NoUnit && right.unit == Unit::NoUnit {
|
||||
// 3 / 2
|
||||
return Ok(Number::new(left.value / right.value, left.unit))
|
||||
} else if left.unit != Unit::NoUnit && right.unit == Unit::NoUnit {
|
||||
// 1 km / 2
|
||||
return Ok(Number::new(left.value / right.value, right.unit))
|
||||
} else {
|
||||
return Err(format!("Cannot divide {:?} by {:?}", left.unit, right.unit))
|
||||
}
|
||||
Ok(divide(left, right)?)
|
||||
// }
|
||||
},
|
||||
Modulo => {
|
||||
if left.unit == Unit::NoUnit && right.unit == Unit::NoUnit {
|
||||
// 3 / 2
|
||||
return Ok(Number::new(left.value % right.value, left.unit))
|
||||
} else if left.unit != Unit::NoUnit && right.unit == Unit::NoUnit {
|
||||
// 1 km / 2
|
||||
return Ok(Number::new(left.value % right.value, right.unit))
|
||||
} else {
|
||||
return Err(format!("Cannot modulo {:?} by {:?}", left.unit, right.unit))
|
||||
}
|
||||
Ok(modulo(left, right)?)
|
||||
// }
|
||||
},
|
||||
Caret => {
|
||||
if left.unit == Unit::NoUnit && right.unit == Unit::NoUnit {
|
||||
// 3 ^ 2
|
||||
return Ok(Number::new(left.value.pow(right.value), left.unit))
|
||||
} else if right.unit == Unit::NoUnit && left.unit != Unit::NoUnit {
|
||||
// 1 km ^ 3
|
||||
return Ok(Number::new(left.value.pow(right.value), left.unit))
|
||||
} else {
|
||||
return Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit))
|
||||
}
|
||||
Ok(pow(left, right)?)
|
||||
// }
|
||||
},
|
||||
_ => {
|
||||
Err(format!("Unexpected operator {:?}", operator))
|
||||
|
||||
91
src/units.rs
91
src/units.rs
@ -254,38 +254,97 @@ pub fn convert(number: Number, to_unit: Unit) -> Result<Number, String> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(left: Number, right: Number) -> Result<Number, String> {
|
||||
if left.unit == right.unit {
|
||||
Ok(Number::new(left.value + right.value, left.unit))
|
||||
} else if left.unit.category() == right.unit.category() && left.unit.category() != Temperature {
|
||||
if left.unit.weight() > right.unit.weight() {
|
||||
pub fn convert_to_lowest(left: Number, right: Number) -> Result<(Number, Number), String> {
|
||||
if left.unit.weight() == right.unit.weight() {
|
||||
Ok((left, right))
|
||||
} else if left.unit.weight() > right.unit.weight() {
|
||||
let left_converted = convert(left, right.unit)?;
|
||||
Ok(Number::new(left_converted.value + right.value, right.unit))
|
||||
Ok((left_converted, right))
|
||||
} else {
|
||||
let right_converted = convert(right, left.unit)?;
|
||||
Ok(Number::new(right_converted.value + left.value, left.unit))
|
||||
Ok((left, right_converted))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(left: Number, right: Number) -> Result<Number, String> {
|
||||
if left.unit.category() == right.unit.category() && left.unit.category() != Temperature {
|
||||
let (left, right) = convert_to_lowest(left, right)?;
|
||||
Ok(Number::new(left.value + right.value, left.unit))
|
||||
} else {
|
||||
return Err(format!("Cannot add {:?} and {:?}", left.unit, right.unit))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn subtract(left: Number, right: Number) -> Result<Number, String> {
|
||||
if left.unit == right.unit {
|
||||
if left.unit.category() == right.unit.category() && left.unit.category() != Temperature {
|
||||
let (left, right) = convert_to_lowest(left, right)?;
|
||||
Ok(Number::new(left.value - right.value, left.unit))
|
||||
} else if left.unit.category() == right.unit.category() && left.unit.category() != Temperature {
|
||||
if left.unit.weight() > right.unit.weight() {
|
||||
let left_converted = convert(left, right.unit)?;
|
||||
Ok(Number::new(left_converted.value - right.value, right.unit))
|
||||
} else {
|
||||
let right_converted = convert(right, left.unit)?;
|
||||
Ok(Number::new(right_converted.value - left.value, left.unit))
|
||||
}
|
||||
} else {
|
||||
return Err(format!("Cannot subtract {:?} by {:?}", left.unit, right.unit))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn multiply(left: Number, right: Number) -> Result<Number, String> {
|
||||
if left.unit == Unit::NoUnit && right.unit == Unit::NoUnit {
|
||||
// 3 * 2
|
||||
return Ok(Number::new(left.value * right.value, left.unit))
|
||||
} else if left.unit.category() == Temperature || right.unit.category() == Temperature {
|
||||
// if temperature
|
||||
return Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit))
|
||||
} else if left.unit == Unit::NoUnit && right.unit != Unit::NoUnit {
|
||||
// 3 * 1 km
|
||||
return Ok(Number::new(left.value * right.value, right.unit))
|
||||
} else if right.unit == Unit::NoUnit && left.unit != Unit::NoUnit {
|
||||
// 1 km * 3
|
||||
return Ok(Number::new(left.value * right.value, left.unit))
|
||||
} else {
|
||||
return Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn divide(left: Number, right: Number) -> Result<Number, String> {
|
||||
if left.unit == Unit::NoUnit && right.unit == Unit::NoUnit {
|
||||
// 3 / 2
|
||||
Ok(Number::new(left.value / right.value, left.unit))
|
||||
} else if left.unit.category() == Temperature || right.unit.category() == Temperature {
|
||||
// if temperature
|
||||
return Err(format!("Cannot divide {:?} by {:?}", left.unit, right.unit))
|
||||
} else if left.unit != Unit::NoUnit && right.unit == Unit::NoUnit {
|
||||
// 1 km / 2
|
||||
Ok(Number::new(left.value / right.value, right.unit))
|
||||
} else if left.unit.category() == right.unit.category() {
|
||||
// 1 km / 1 km
|
||||
let (left, right) = convert_to_lowest(left, right)?;
|
||||
Ok(Number::new(left.value * right.value, Unit::NoUnit))
|
||||
} else {
|
||||
Err(format!("Cannot divide {:?} by {:?}", left.unit, right.unit))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modulo(left: Number, right: Number) -> Result<Number, String> {
|
||||
if left.unit == Unit::NoUnit && right.unit == Unit::NoUnit {
|
||||
// 3 / 2
|
||||
return Ok(Number::new(left.value % right.value, left.unit))
|
||||
} else if left.unit != Unit::NoUnit && right.unit == Unit::NoUnit {
|
||||
// 1 km / 2
|
||||
return Ok(Number::new(left.value % right.value, right.unit))
|
||||
} else {
|
||||
return Err(format!("Cannot modulo {:?} by {:?}", left.unit, right.unit))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pow(left: Number, right: Number) -> Result<Number, String> {
|
||||
if left.unit == Unit::NoUnit && right.unit == Unit::NoUnit {
|
||||
// 3 ^ 2
|
||||
return Ok(Number::new(left.value.pow(right.value), left.unit))
|
||||
} else if right.unit == Unit::NoUnit && left.unit != Unit::NoUnit {
|
||||
// 1 km ^ 3
|
||||
return Ok(Number::new(left.value.pow(right.value), left.unit))
|
||||
} else {
|
||||
return Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user