mod consts;
mod table;
use crate::primitive::int;
use crate::symbolic::{
expr::{SymExpr, Primary},
simplify::{
fraction::{extract_explicit_frac, make_fraction},
rules::do_call,
step::Step,
self,
},
step_collector::StepCollector,
};
use std::collections::HashMap;
fn simplify_trig(arg: SymExpr, table: &HashMap<&SymExpr, table::TrigOut>) -> Option<SymExpr> {
let mut expr = {
let two_pi = SymExpr::Primary(Primary::Integer(int(2))) * SymExpr::Primary(Primary::Symbol("pi".to_string()));
let raw = make_fraction(arg, two_pi);
simplify::simplify(&raw)
};
let (numerator, denominator) = extract_explicit_frac(&mut expr)?;
let fraction = {
if numerator.is_zero() {
SymExpr::Primary(Primary::Integer(int(0)))
} else if denominator == 1 {
SymExpr::Primary(Primary::Integer(numerator))
} else {
let numerator = (numerator % &denominator + &denominator) % &denominator;
make_fraction(
SymExpr::Primary(Primary::Integer(numerator)),
SymExpr::Primary(Primary::Integer(denominator)),
)
}
};
table.get(&fraction)
.map(|out| {
if out.neg {
-out.output.clone()
} else {
out.output.clone()
}
})
}
pub fn sin(expr: &SymExpr, step_collector: &mut dyn StepCollector<Step>) -> Option<SymExpr> {
let opt = do_call(expr, "sin", |args| {
simplify_trig(args.first().cloned()?, &table::SIN_TABLE)
})?;
step_collector.push(Step::Sin);
Some(opt)
}
pub fn cos(expr: &SymExpr, step_collector: &mut dyn StepCollector<Step>) -> Option<SymExpr> {
let opt = do_call(expr, "cos", |args| {
simplify_trig(args.first().cloned()?, &table::COS_TABLE)
})?;
step_collector.push(Step::Cos);
Some(opt)
}
pub fn tan(expr: &SymExpr, step_collector: &mut dyn StepCollector<Step>) -> Option<SymExpr> {
let opt = do_call(expr, "tan", |args| {
simplify_trig(args.first().cloned()?, &table::TAN_TABLE)
})?;
step_collector.push(Step::Tan);
Some(opt)
}
pub fn all(expr: &SymExpr, step_collector: &mut dyn StepCollector<Step>) -> Option<SymExpr> {
sin(expr, step_collector)
.or_else(|| cos(expr, step_collector))
.or_else(|| tan(expr, step_collector))
}