use lieval::*;
#[test]
fn operator_test() {
assert_eq!(eval_from_str("1 + 2"), Ok(vec![3.0]));
assert_eq!(eval_from_str("1 + -2"), Ok(vec![-1.0]));
assert_eq!(eval_from_str("-1 + 2"), Ok(vec![1.0]));
assert_eq!(eval_from_str("1 - 2"), Ok(vec![-1.0]));
assert_eq!(eval_from_str("2 * 3"), Ok(vec![6.0]));
assert_eq!(eval_from_str("2 * -3"), Ok(vec![-6.0]));
assert_eq!(eval_from_str("2 / 4"), Ok(vec![0.5]));
assert_eq!(eval_from_str("-2 / 4"), Ok(vec![-0.5]));
assert_eq!(eval_from_str("-1.0"), Ok(vec![-1.0]));
assert_eq!(eval_from_str("7 % 3.0"), Ok(vec![1.0]));
assert_eq!(eval_from_str("7.0 % -3.0"), Ok(vec![1.0]));
assert_eq!(eval_from_str("-7 % 3"), Ok(vec![-1.0]));
}
#[test]
fn function_test() {
assert_eq!(eval_from_str("sin(-1 + 2 * 3)"), Ok(vec![(5f64).sin()]));
assert_eq!(eval_from_str("cos(-1 + 2 * 3)"), Ok(vec![(5f64).cos()]));
assert_eq!(eval_from_str("tan(-1 + 2 * 3)"), Ok(vec![(5f64).tan()]));
assert_eq!(eval_from_str("exp(-1 + 2 * 3)"), Ok(vec![(5f64).exp()]));
assert_eq!(eval_from_str("sqrt(-1 + 2 * 3)"), Ok(vec![(5f64).sqrt()]));
assert_eq!(eval_from_str("ln(-1 + 2 * 3)"), Ok(vec![(5f64).ln()]));
assert_eq!(eval_from_str("powi(1 - 2 * 3, 2)"), Ok(vec![25.0]));
assert_eq!(eval_from_str("pow(1 - 2 * 3, 2)"), Ok(vec![(-5f64).powf(2.0)]));
assert_eq!(eval_from_str("-powf(1 - 2 * 3, 2)"), Ok(vec![-5f64.powf(2.0)]));
assert_eq!(eval_from_str("cos(PI)"), Ok(vec![-1.0]));
assert_eq!(eval_from_str("cos(TAU)"), Ok(vec![1.0]));
assert_eq!(eval_from_str("ln(E)"), Ok(vec![1.0]));
assert_eq!(eval_from_str("max(1, 2)"), Ok(vec![2.0]));
assert_eq!(eval_from_str("min(1, 2)"), Ok(vec![1.0]));
assert_eq!(eval_from_str("abs(-1)"), Ok(vec![1.0]));
assert_eq!(eval_from_str("acos(-1)"), Ok(vec![std::f64::consts::PI]));
assert_eq!(eval_from_str("sinh(1)"), Ok(vec![1.0f64.sinh()]));
assert_eq!(eval_from_str("hypot(3,4)"), Ok(vec![5.0]));
assert_eq!(eval_from_str("div_euclid(7,2)"), Ok(vec![3.0]));
assert_eq!(eval_from_str("floor(1.49)"), Ok(vec![1.0]));
assert_eq!(eval_from_str("log(5,2)"), Ok(vec![5.0f64.log(2.0)]));
}
#[test]
fn assoc_test() {
assert_eq!(eval_from_str("1 + 2 * 3"), Ok(vec![7.0]));
assert_eq!(eval_from_str("(1 + 2) * 3"), Ok(vec![9.0]));
assert_eq!(eval_from_str("((1 + 2)) * 3"), Ok(vec![9.0]));
assert_eq!(eval_from_str("(1 - (2 + 3)) * 5"), Ok(vec![-20.0]));
assert_eq!(eval_from_str("powf((3-2)*5, sin(5-(3-1)))"), Ok(vec![((3f64-2.0)*5.0).powf(3f64.sin())]));
assert_eq!(eval_from_str("-(-(-1))+2"), Ok(vec![1.0]));
assert_eq!(eval_from_str("-(-(-1*2)+3)+4"), Ok(vec![-1.0]));
}
#[test]
fn custom_func_test() {
let mut context = Context::new();
assert_eq!(
eval_from_str_with_context("1 + func()", context.set_func("func", 0, |_| 2.0)),
Ok(vec![3.0])
);
assert_eq!(
eval_from_str_with_context("1 + func(2)", context.set_func("func", 1, |x| x[0])),
Ok(vec![3.0])
);
assert_eq!(
eval_from_str_with_context("1 + func(2,3)", context.set_func("func", 2, |x| x[0] + x[1])),
Ok(vec![6.0])
);
assert_eq!(
eval_from_str_with_context("1 + func(2,3,4,5)", context.set_func("func", 4, |x| -x[0] - x[1] + x[2] + x[3])),
Ok(vec![5.0])
);
assert_eq!(
eval_from_str_with_context("1 + func(x)", context.set_func("func", 1, |x| x[0] * 2.0).set_value("x", 1.0)),
Ok(vec![3.0])
);
assert_eq!(
eval_from_str_with_context("1 + func(sin(x))", context.set_func("func", 1, |x| x[0] * 2.0).set_value("x", 1.0)),
Ok(vec![1.0 + (1.0f64.sin()) * 2.0])
);
assert_eq!(
eval_from_str_with_context("1 + func(func(x))", context.set_func("func", 1, |x| x[0] * 2.0).set_value("x", 1.0)),
Ok(vec![5.0])
);
assert_eq!(
eval_from_str_with_context("1 + func(x) + func2(y)",
context.set_func("func", 1, |x| x[0] * 2.0).set_func("func2", 1, |x| x[0] + 3.0).set_value("x", 1.0).set_value("y", 2.0)),
Ok(vec![8.0])
);
assert_eq!(
eval_from_str_with_context("1 + func(1,x,y,4)",
context.set_func("func", 4, |x| x[0] + x[1] * x[2] + x[3])
.set_value("x", 2.0)
.set_value("y", 3.0)
),
Ok(vec![12.0])
);
let mut expr_obj = Expr::new("1 + func(x)").unwrap();
assert_eq!(expr_obj.set_var("x", 3.0).set_func("func", 1, |x| x[0] * 2.0).eval(), Ok(7.0));
let mut expr_obj = Expr::new("1 + func1(x) + func2()").unwrap();
assert_eq!(
expr_obj.set_var("x", 3.0)
.set_func("func1", 1, |x| x[0] * 2.0)
.partial_eval().unwrap()
.set_func("func2", 0, |_| 1.5).eval(),
Ok(8.5)
);
let mut expr_obj = Expr::new("1 + func1(1, x, y, 4) + z + func2(x, y)").unwrap();
assert_eq!(
expr_obj.set_func("func1", 4, |x| x[0] + x[1] * x[2] + x[3])
.set_func("func2", 2, |x| x[0] + x[1])
.set_var("x", 2.0)
.set_var("y", 3.0)
.partial_eval().unwrap()
.set_var("z", -12.0).eval(),
Ok(5.0)
);
}
#[test]
fn expr_test() {
assert_eq!(
eval_from_str("0.5 + 3.0 * -cos(sin(1.0 - 2.0) + 1.5) + 5.5"),
Ok(vec![0.5 + 3.0 * -((1f64 - 2.0).sin() + 1.5).cos() + 5.5])
);
assert_eq!(eval_from_str("1.0 + 2 * (3 - 1)"), Ok(vec![5.0]));
assert_eq!(
eval_from_str("1.0 - sin(3.14 / 2) * powf(1.5, 2.5)"),
Ok(vec![1.0 - (3.14f64 / 2.0).sin() * 1.5f64.powf(2.5)])
);
assert_eq!(eval_from_str("1 + 2, sin(3 + 0.14), 7 % 3"), Ok(vec![3.0, (3.14f64).sin(), 7.0 % 3.0]));
}
#[test]
fn expr_with_context_test() {
let mut context = Context::new();
assert_eq!(
eval_from_str_with_context("1 / x", context.set_value("x", 2.0)),
Ok(vec![0.5])
);
assert_eq!(
eval_from_str_with_context("0.5 + x * -cos(sin(1.0 - 2.0) + 1.5) + 5.5", context.set_value("x", 3.0)),
Ok(vec![0.5 + 3.0 * -((1f64 - 2.0).sin() + 1.5).cos() + 5.5])
);
assert_eq!(
eval_from_str_with_context("0.5 + x * -cos(sin(1.0 - 2.0) + 1.5) + 5.5", context.set_value("x", -1.5)),
Ok(vec![0.5 + -1.5 * -((1f64 - 2.0).sin() + 1.5).cos() + 5.5])
);
}
#[test]
fn expr_object_test() {
let expr_obj = Expr::new("sqrt(4)").unwrap();
assert_eq!(expr_obj.eval(), Ok(2.0));
let mut expr_obj = Expr::new("sqrt(2+x)").unwrap();
assert_eq!(expr_obj.set_var("x", 2.0).eval(), Ok(2.0));
let mut expr_obj = Expr::new("sqrt(2+x+y)").unwrap();
assert_eq!(expr_obj.set_var("x", 2.0).set_var("y", 5.0).eval(), Ok(3.0));
let expr1 = "0.5 + 3.0 * -cos(sin(1.0 - 2.0) + 1.5) + 5.5";
let expr2 = "0.5 + x * -cos(sin(1.0 - 2.0) + 1.5) + 5.5";
let result1 = Ok(0.5 + 3.0 * -((1f64 - 2.0).sin() + 1.5).cos() + 5.5);
let result2 = Ok(0.5 + -1.5 * -((1f64 - 2.0).sin() + 1.5).cos() + 5.5);
let expr_obj = Expr::new(&expr1).unwrap();
assert_eq!(expr_obj.eval(), result1);
let mut expr_obj = Expr::new(&expr2).unwrap();
assert_eq!(expr_obj.set_var("x", 3.0).eval(), result1);
assert_eq!(expr_obj.set_var("x", -1.5).eval(), result2);
let mut expr_obj = Expr::new(&expr2).unwrap();
expr_obj.partial_eval().unwrap();
assert_eq!(expr_obj.set_var("x", 3.0).eval(), result1);
assert_eq!(expr_obj.set_var("x", -1.5).eval(), result2);
let expr_obj = Expr::new("1+1, 2*3+1, sin(PI)").unwrap();
assert_eq!(expr_obj.eval(), Ok(2.0));
assert_eq!(expr_obj.evals(), Ok(vec![2.0, 7.0, std::f64::consts::PI.sin()]));
let mut expr_obj = Expr::new("x+1, 2*3+y; sin(PI)").unwrap();
expr_obj.partial_evals().unwrap();
assert_eq!(expr_obj.set_var("x", 1.0).eval(), Ok(2.0));
assert_eq!(expr_obj.set_var("y", 1.0).eval_index(1), Ok(7.0));
assert_eq!(expr_obj.evals(), Ok(vec![2.0, 7.0, std::f64::consts::PI.sin()]));
let mut expr_obj = Expr::new("x+1, 2*3+y; sin(PI)").unwrap();
expr_obj.set_var("x", 1.0).set_var("y", 1.0).partial_evals().unwrap();
assert_eq!(expr_obj.eval(), Ok(2.0));
assert_eq!(expr_obj.eval_index(1), Ok(7.0));
assert_eq!(expr_obj.evals(), Ok(vec![2.0, 7.0, std::f64::consts::PI.sin()]));
assert_eq!(ex!("x+1, 2*3+y; sin(PI)").set_var("x", 1.0).set_var("y", 1.0).evals(), Ok(vec![2.0, 7.0, std::f64::consts::PI.sin()]));
}
#[test]
fn partial_eval_test() {
let mut expr_obj = Expr::new("a1 + a2 * sin(x)").unwrap();
expr_obj.set_var("a1", 1.0)
.set_var("a2", 0.5)
.partial_eval()
.unwrap();
let mut x = 1.0;
for _ in 0..10 {
x = expr_obj.set_var("x", x).eval().unwrap();
assert_eq!(expr_obj.set_var("x", x).eval(), Ok(1.0 + 0.5 * x.sin()));
}
}
#[test]
fn expr_opeation_test() {
let expr1 = Expr::new("1+x").unwrap();
let expr2 = Expr::new("2*x").unwrap();
assert_eq!((expr1 + expr2).set_var("x", 2.0).eval(), Ok(7.0));
let expr1 = Expr::new("1+x").unwrap();
let mut expr2 = Expr::new("2*x").unwrap();
expr2.set_var("x", 3.0).partial_eval().unwrap();
assert_eq!((expr1 * expr2).set_var("x", 2.0).eval(), Ok(18.0));
let expr1 = Expr::new("1+x").unwrap();
let expr2 = Expr::new("2*x").unwrap();
assert_eq!((expr1 - expr2).set_var("x", 2.0).eval(), Ok(-1.0));
let expr1 = Expr::new("1+x").unwrap();
let expr2 = Expr::new("2*x").unwrap();
assert_eq!((expr1 / expr2).set_var("x", 2.0).eval(), Ok(3.0f64/4.0));
let expr1 = Expr::new("1+x, 2+x, 3+x").unwrap();
let expr2 = Expr::new("2*x, 3*x, 4*x").unwrap();
assert_eq!((expr1 + expr2).set_var("x", 2.0).evals(), Ok(vec![7.0, 10.0, 13.0]));
let expr1 = Expr::new("1+x").unwrap();
let expr2 = Expr::new("2*x, 3*x, 4*x").unwrap();
assert_eq!((expr1 * expr2).set_var("x", 2.0).evals(), Ok(vec![12.0, 18.0, 24.0]));
let expr2 = Expr::new("2*x, 3*x, 4*x").unwrap();
assert_eq!((3.0 * expr2).set_var("x", 2.0).evals(), Ok(vec![12.0, 18.0, 24.0]));
let expr2 = Expr::new("2*x, 3*x, 4*x").unwrap();
assert_eq!((-expr2 * 3.0).set_var("x", 2.0).evals(), Ok(vec![-12.0, -18.0, -24.0]));
let expr1 = Expr::new("1+x").unwrap();
let expr2 = Expr::new("2*x, 3*x, 4*x").unwrap();
assert_eq!((expr2 * 3.0 + expr1).set_var("x", 2.0).evals(), Ok(vec![15.0, 21.0, 27.0]));
let expr1 = Expr::new("1+x").unwrap();
let expr2 = Expr::new("2*x, 3*x, 4*x").unwrap();
assert_eq!((expr2 + ex!("x") * expr1).set_var("x", 2.0).evals(), Ok(vec![10.0, 12.0, 14.0]));
}