use super::strategy::SimplificationStrategy;
use crate::core::Expression;
pub struct SinSimplificationStrategy;
impl SimplificationStrategy for SinSimplificationStrategy {
fn simplify(&self, args: &[Expression]) -> Expression {
if args.len() == 1 {
let arg = &args[0];
if arg.is_zero() {
Expression::integer(0)
} else {
Expression::function("sin", args.to_vec())
}
} else {
Expression::function("sin", args.to_vec())
}
}
fn applies_to(&self, args: &[Expression]) -> bool {
args.len() == 1
}
fn name(&self) -> &str {
"SinSimplificationStrategy"
}
}
pub struct CosSimplificationStrategy;
impl SimplificationStrategy for CosSimplificationStrategy {
fn simplify(&self, args: &[Expression]) -> Expression {
if args.len() == 1 {
let arg = &args[0];
if arg.is_zero() {
Expression::integer(1)
} else {
Expression::function("cos", args.to_vec())
}
} else {
Expression::function("cos", args.to_vec())
}
}
fn applies_to(&self, args: &[Expression]) -> bool {
args.len() == 1
}
fn name(&self) -> &str {
"CosSimplificationStrategy"
}
}
pub struct TanSimplificationStrategy;
impl SimplificationStrategy for TanSimplificationStrategy {
fn simplify(&self, args: &[Expression]) -> Expression {
if args.len() == 1 {
let arg = &args[0];
if arg.is_zero() {
Expression::integer(0)
} else {
Expression::function("tan", args.to_vec())
}
} else {
Expression::function("tan", args.to_vec())
}
}
fn applies_to(&self, args: &[Expression]) -> bool {
args.len() == 1
}
fn name(&self) -> &str {
"TanSimplificationStrategy"
}
}
pub struct GenericTrigSimplificationStrategy {
function_name: String,
}
impl GenericTrigSimplificationStrategy {
pub fn new(function_name: &str) -> Self {
Self {
function_name: function_name.to_owned(),
}
}
}
impl SimplificationStrategy for GenericTrigSimplificationStrategy {
fn simplify(&self, args: &[Expression]) -> Expression {
Expression::function(&self.function_name, args.to_vec())
}
fn applies_to(&self, args: &[Expression]) -> bool {
args.len() == 1
}
fn name(&self) -> &str {
&self.function_name
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{expr, symbol};
#[test]
fn test_sin_of_zero() {
let strategy = SinSimplificationStrategy;
let result = strategy.simplify(&[expr!(0)]);
assert_eq!(result, expr!(0));
}
#[test]
fn test_sin_of_x() {
let strategy = SinSimplificationStrategy;
let x = symbol!(x);
let result = strategy.simplify(&[x.clone().into()]);
if let Expression::Function { name, args } = result {
assert_eq!(name.as_ref(), "sin");
assert_eq!(args.len(), 1);
assert_eq!(args[0], x.into());
} else {
panic!("Expected function call");
}
}
#[test]
fn test_cos_of_zero() {
let strategy = CosSimplificationStrategy;
let result = strategy.simplify(&[expr!(0)]);
assert_eq!(result, expr!(1));
}
#[test]
fn test_cos_of_x() {
let strategy = CosSimplificationStrategy;
let x = symbol!(x);
let result = strategy.simplify(&[x.clone().into()]);
if let Expression::Function { name, args } = result {
assert_eq!(name.as_ref(), "cos");
assert_eq!(args.len(), 1);
assert_eq!(args[0], x.into());
} else {
panic!("Expected function call");
}
}
#[test]
fn test_tan_of_zero() {
let strategy = TanSimplificationStrategy;
let result = strategy.simplify(&[expr!(0)]);
assert_eq!(result, expr!(0));
}
#[test]
fn test_tan_of_x() {
let strategy = TanSimplificationStrategy;
let x = symbol!(x);
let result = strategy.simplify(&[x.clone().into()]);
if let Expression::Function { name, args } = result {
assert_eq!(name.as_ref(), "tan");
assert_eq!(args.len(), 1);
assert_eq!(args[0], x.into());
} else {
panic!("Expected function call");
}
}
#[test]
fn test_generic_trig() {
let strategy = GenericTrigSimplificationStrategy::new("sinh");
let x = symbol!(x);
let result = strategy.simplify(&[x.clone().into()]);
if let Expression::Function { name, args } = result {
assert_eq!(name.as_ref(), "sinh");
assert_eq!(args.len(), 1);
assert_eq!(args[0], x.into());
} else {
panic!("Expected function call");
}
}
}