feat(eval): add functions and constants
added constants pi, e added functions sin, cos, tan, asin, acos, atan, abs, and sqrt fixed displaying decimals without normalizing them todo: add imaginary number support
This commit is contained in:
5 files changed
+58
-5
No files matched your search
+1
-1
@@ -19,7 +19,7 @@ impl Display for Operator {
|
||||
impl Display for Expression {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Expression::Number(num) => write!(f, "{}", num),
|
||||
Expression::Number(num) => write!(f, "{}", num.normalize()),
|
||||
Expression::Variable(var) => write!(f, "{}", var),
|
||||
Expression::Fraction(numerator, denominator) => {
|
||||
write!(f, "({} / {})", numerator, denominator)
|
||||
|
||||
+15
-4
@@ -1,11 +1,20 @@
|
||||
use rust_decimal::MathematicalOps;
|
||||
|
||||
use crate::math::types::{Expression, Operator};
|
||||
use crate::math::{
|
||||
functions, math_constants,
|
||||
types::{Expression, Operator},
|
||||
};
|
||||
|
||||
pub fn eval_expr(expr: Expression) -> Expression {
|
||||
match expr {
|
||||
Expression::Number(_) => expr,
|
||||
Expression::Variable(_) => expr,
|
||||
Expression::Variable(name) => {
|
||||
if let Some(value) = math_constants::get(&name) {
|
||||
Expression::Number(value)
|
||||
} else {
|
||||
Expression::Variable(name)
|
||||
}
|
||||
}
|
||||
Expression::Fraction(numberator, denominator) => {
|
||||
// TODO: implement proper fraction handling
|
||||
eval_expr(Expression::Operation(
|
||||
@@ -15,7 +24,10 @@ pub fn eval_expr(expr: Expression) -> Expression {
|
||||
))
|
||||
}
|
||||
Expression::Operation(operator, left, right) => eval_operation(operator, *left, *right),
|
||||
Expression::Function(_name, _params) => todo!(),
|
||||
Expression::Function(name, params) => {
|
||||
let params = params.into_iter().map(eval_expr).collect();
|
||||
functions::eval_function(&name, params)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +43,6 @@ fn eval_operation(operator: Operator, left: Expression, right: Expression) -> Ex
|
||||
Operator::Modulo => Expression::Number(left % right),
|
||||
Operator::Power => Expression::Number(left.powd(*right)),
|
||||
},
|
||||
// TODO: implement handling for variables
|
||||
_ => Expression::Operation(operator, Box::new(left), Box::new(right)),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
use crate::math::types::Expression;
|
||||
use rust_decimal::Decimal;
|
||||
use rust_decimal::MathematicalOps;
|
||||
use rust_decimal::prelude::ToPrimitive;
|
||||
|
||||
pub fn eval_function(func_name: &str, params: Vec<Expression>) -> Expression {
|
||||
match func_name {
|
||||
"sin" => map_decimal(¶ms[0], |d| d.sin()),
|
||||
"cos" => map_decimal(¶ms[0], |d| d.cos()),
|
||||
"tan" => map_decimal(¶ms[0], |d| d.tan()),
|
||||
"asin" => map_decimal(¶ms[0], |d| map_f64(&d, |f| f.asin())),
|
||||
"acos" => map_decimal(¶ms[0], |d| map_f64(&d, |f| f.acos())),
|
||||
"atan" => map_decimal(¶ms[0], |d| map_f64(&d, |f| f.atan())),
|
||||
"abs" => map_decimal(¶ms[0], |d| d.abs()),
|
||||
"sqrt" => map_decimal(¶ms[0], |d| d.abs().sqrt().expect("impossible")),
|
||||
_ => panic!("unknown function"),
|
||||
}
|
||||
}
|
||||
|
||||
fn map_decimal(expr: &Expression, f: fn(Decimal) -> Decimal) -> Expression {
|
||||
match expr {
|
||||
Expression::Number(d) => Expression::Number(f(*d)),
|
||||
_ => panic!("expected decimal"),
|
||||
}
|
||||
}
|
||||
|
||||
fn map_f64(decimal: &Decimal, f: fn(f64) -> f64) -> Decimal {
|
||||
let num = decimal.to_f64().expect("unable to unwrap decimal");
|
||||
let num = f(num);
|
||||
Decimal::from_f64_retain(num).expect("unable to wrap decimal")
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
use rust_decimal::Decimal;
|
||||
|
||||
pub fn get(name: &str) -> Option<Decimal> {
|
||||
match &name.to_lowercase()[..] {
|
||||
"pi" => Some(Decimal::PI),
|
||||
"e" => Some(Decimal::E),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,9 @@ use crate::math::types::Expression;
|
||||
|
||||
mod display;
|
||||
mod eval;
|
||||
mod functions;
|
||||
mod lexer;
|
||||
mod math_constants;
|
||||
mod parser;
|
||||
|
||||
pub mod types;
|
||||
|
||||
Reference in new issue
Block a user