use mathhook_core::{Expression, Simplify};
#[test]
fn test_sqrt_of_perfect_squares() {
let test_cases = vec![(0, 0), (1, 1), (4, 2), (9, 3), (16, 4), (25, 5), (100, 10)];
for (input, expected) in test_cases {
let result = Expression::function("sqrt", vec![Expression::integer(input)]).simplify();
assert_eq!(
result,
Expression::integer(expected),
"sqrt({}) should be {}",
input,
expected
);
}
}
#[test]
#[ignore = "BUG: sqrt simplification doesn't keep irrational sqrts as sqrt expressions"]
fn test_sqrt_of_non_perfect_squares() {
let non_perfect = vec![2, 3, 5, 7, 8, 10];
for n in non_perfect {
let result = Expression::function("sqrt", vec![Expression::integer(n)]).simplify();
match result {
Expression::Function { ref name, .. } if name.as_ref() == "sqrt" => {
}
Expression::Number(_) => {
panic!("sqrt({}) should not reduce to a number", n);
}
_ => {
}
}
}
}
#[test]
fn test_sqrt_of_negative_returns_imaginary() {
let result = Expression::function("sqrt", vec![Expression::integer(-1)]).simplify();
match result {
Expression::Constant(c) => {
assert_eq!(
c,
mathhook_core::core::MathConstant::I,
"sqrt(-1) should be i"
);
}
_ => {
panic!(
"sqrt(-1) should simplify to imaginary unit i, got {}",
result
);
}
}
}
#[test]
fn test_sqrt_of_negative_four() {
let result = Expression::function("sqrt", vec![Expression::integer(-4)]).simplify();
match result {
Expression::Mul(_) => {
}
_ => {
}
}
}
#[test]
fn test_division_structure() {
let a = Expression::integer(6);
let b = Expression::integer(2);
let division = Expression::div(a.clone(), b.clone());
let simplified = division.simplify();
assert_eq!(simplified, Expression::integer(3), "6 / 2 should be 3");
}
#[test]
fn test_zero_divided_by_nonzero() {
let test_cases = vec![1, 2, 5, 100, -3];
for n in test_cases {
let result = Expression::div(Expression::integer(0), Expression::integer(n)).simplify();
assert_eq!(result, Expression::integer(0), "0 / {} should be 0", n);
}
}
#[test]
fn test_log_of_one_is_zero() {
let result = Expression::function("ln", vec![Expression::integer(1)]).simplify();
assert_eq!(result, Expression::integer(0), "ln(1) should be 0");
}
#[test]
fn test_log_of_e_is_one() {
let result = Expression::function("ln", vec![Expression::e()]).simplify();
assert_eq!(result, Expression::integer(1), "ln(e) should be 1");
}
#[test]
fn test_exp_of_zero_is_one() {
let result = Expression::function("exp", vec![Expression::integer(0)]).simplify();
assert_eq!(result, Expression::integer(1), "exp(0) should be 1");
}
#[test]
fn test_trig_special_values_sin() {
let result = Expression::function("sin", vec![Expression::integer(0)]).simplify();
assert_eq!(result, Expression::integer(0), "sin(0) should be 0");
}
#[test]
fn test_trig_special_values_cos() {
let result = Expression::function("cos", vec![Expression::integer(0)]).simplify();
assert_eq!(result, Expression::integer(1), "cos(0) should be 1");
}
#[test]
fn test_tan_of_zero() {
let result = Expression::function("tan", vec![Expression::integer(0)]).simplify();
assert_eq!(result, Expression::integer(0), "tan(0) should be 0");
}
#[test]
fn test_rational_division_reduces() {
let result = Expression::div(Expression::integer(6), Expression::integer(4)).simplify();
assert_eq!(
result,
Expression::rational(3, 2),
"6/4 should reduce to 3/2"
);
}
#[test]
fn test_power_of_zero_base() {
let test_cases = vec![1, 2, 3, 5, 100];
for n in test_cases {
let result = Expression::pow(Expression::integer(0), Expression::integer(n)).simplify();
assert_eq!(result, Expression::integer(0), "0^{} should be 0", n);
}
}
#[test]
fn test_negative_exponents() {
let result = Expression::pow(Expression::integer(2), Expression::integer(-1)).simplify();
assert_eq!(result, Expression::rational(1, 2), "2^(-1) should be 1/2");
let result = Expression::pow(Expression::integer(2), Expression::integer(-2)).simplify();
assert_eq!(result, Expression::rational(1, 4), "2^(-2) should be 1/4");
}
#[test]
fn test_factorial_base_cases() {
let result = Expression::function("factorial", vec![Expression::integer(0)]).simplify();
assert_eq!(result, Expression::integer(1), "0! should be 1");
let result = Expression::function("factorial", vec![Expression::integer(1)]).simplify();
assert_eq!(result, Expression::integer(1), "1! should be 1");
}
#[test]
fn test_factorial_small_values() {
let test_cases = vec![(2, 2), (3, 6), (4, 24), (5, 120), (6, 720)];
for (n, expected) in test_cases {
let result = Expression::function("factorial", vec![Expression::integer(n)]).simplify();
assert_eq!(
result,
Expression::integer(expected),
"{}! should be {}",
n,
expected
);
}
}