use mathhook_core::calculus::integrals::table::try_table_lookup;
use mathhook_core::{symbol, Expression};
#[test]
fn test_table_power_rule_positive() {
let x = symbol!(x);
let expr = Expression::pow(Expression::symbol(x.clone()), Expression::integer(2));
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate x^2");
let integrated = result.unwrap();
if let Expression::Mul(factors) = &integrated {
assert_eq!(factors.len(), 2);
assert!(
matches!(&factors[0], Expression::Number(_)),
"First factor should be coefficient 1/3"
);
}
}
#[test]
fn test_table_power_rule_x_cubed() {
let x = symbol!(x);
let expr = Expression::pow(Expression::symbol(x.clone()), Expression::integer(3));
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate x^3");
}
#[test]
fn test_table_power_rule_linear() {
let x = symbol!(x);
let expr = Expression::symbol(x.clone());
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate x");
let integrated = result.unwrap();
if let Expression::Mul(factors) = &integrated {
assert_eq!(factors.len(), 2);
}
}
#[test]
fn test_table_reciprocal() {
let x = symbol!(x);
let expr = Expression::pow(Expression::symbol(x.clone()), Expression::integer(-1));
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate 1/x");
let integrated = result.unwrap();
assert!(
matches!(&integrated, Expression::Function { name, .. } if name.as_ref() == "ln"),
"Result should be ln function"
);
}
#[test]
fn test_table_with_coefficient() {
let x = symbol!(x);
let expr = Expression::mul(vec![
Expression::integer(3),
Expression::pow(Expression::symbol(x.clone()), Expression::integer(2)),
]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate 3x^2");
}
#[test]
fn test_table_exponential_simple() {
let x = symbol!(x);
let expr = Expression::function("exp", vec![Expression::symbol(x.clone())]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate e^x");
let integrated = result.unwrap();
assert!(
matches!(&integrated, Expression::Function { name, .. } if name.as_ref() == "exp"),
"Result should be exp function"
);
}
#[test]
fn test_table_exponential_with_coefficient() {
let x = symbol!(x);
let two_x = Expression::mul(vec![Expression::integer(2), Expression::symbol(x.clone())]);
let expr = Expression::function("exp", vec![two_x]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate e^(2x)");
}
#[test]
fn test_table_exponential_coefficient_3x() {
let x = symbol!(x);
let three_x = Expression::mul(vec![Expression::integer(3), Expression::symbol(x.clone())]);
let expr = Expression::function("exp", vec![three_x]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate e^(3x)");
}
#[test]
fn test_table_natural_log() {
let x = symbol!(x);
let expr = Expression::function("ln", vec![Expression::symbol(x.clone())]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate ln(x)");
let integrated = result.unwrap();
assert!(
matches!(&integrated, Expression::Add(_)),
"Result should be sum of terms"
);
}
#[test]
fn test_table_sine() {
let x = symbol!(x);
let expr = Expression::function("sin", vec![Expression::symbol(x.clone())]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate sin(x)");
let integrated = result.unwrap();
if let Expression::Mul(factors) = &integrated {
assert!(factors.len() >= 2, "Should have coefficient and cos");
}
}
#[test]
fn test_table_cosine() {
let x = symbol!(x);
let expr = Expression::function("cos", vec![Expression::symbol(x.clone())]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate cos(x)");
let integrated = result.unwrap();
assert!(
matches!(&integrated, Expression::Function { name, .. } if name.as_ref() == "sin"),
"Result should be sin(x)"
);
}
#[test]
fn test_table_sine_with_coefficient() {
let x = symbol!(x);
let two_x = Expression::mul(vec![Expression::integer(2), Expression::symbol(x.clone())]);
let expr = Expression::function("sin", vec![two_x]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate sin(2x)");
}
#[test]
fn test_table_cosine_with_coefficient() {
let x = symbol!(x);
let three_x = Expression::mul(vec![Expression::integer(3), Expression::symbol(x.clone())]);
let expr = Expression::function("cos", vec![three_x]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate cos(3x)");
}
#[test]
fn test_table_tangent() {
let x = symbol!(x);
let expr = Expression::function("tan", vec![Expression::symbol(x.clone())]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate tan(x)");
}
#[test]
fn test_table_cotangent() {
let x = symbol!(x);
let expr = Expression::function("cot", vec![Expression::symbol(x.clone())]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate cot(x)");
}
#[test]
fn test_table_secant() {
let x = symbol!(x);
let expr = Expression::function("sec", vec![Expression::symbol(x.clone())]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate sec(x)");
}
#[test]
fn test_table_cosecant() {
let x = symbol!(x);
let expr = Expression::function("csc", vec![Expression::symbol(x.clone())]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate csc(x)");
}
#[test]
fn test_table_hyperbolic_sine() {
let x = symbol!(x);
let expr = Expression::function("sinh", vec![Expression::symbol(x.clone())]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate sinh(x)");
let integrated = result.unwrap();
assert!(
matches!(&integrated, Expression::Function { name, .. } if name.as_ref() == "cosh"),
"Result should be cosh(x)"
);
}
#[test]
fn test_table_hyperbolic_cosine() {
let x = symbol!(x);
let expr = Expression::function("cosh", vec![Expression::symbol(x.clone())]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate cosh(x)");
let integrated = result.unwrap();
assert!(
matches!(&integrated, Expression::Function { name, .. } if name.as_ref() == "sinh"),
"Result should be sinh(x)"
);
}
#[test]
fn test_table_hyperbolic_tangent() {
let x = symbol!(x);
let expr = Expression::function("tanh", vec![Expression::symbol(x.clone())]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate tanh(x)");
}
#[test]
fn test_table_coefficient_times_sine() {
let x = symbol!(x);
let expr = Expression::mul(vec![
Expression::integer(5),
Expression::function("sin", vec![Expression::symbol(x.clone())]),
]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate 5*sin(x)");
}
#[test]
fn test_table_coefficient_times_exp() {
let x = symbol!(x);
let expr = Expression::mul(vec![
Expression::integer(2),
Expression::function("exp", vec![Expression::symbol(x.clone())]),
]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate 2*e^x");
}
#[test]
fn test_table_coefficient_times_power() {
let x = symbol!(x);
let expr = Expression::mul(vec![
Expression::integer(4),
Expression::pow(Expression::symbol(x.clone()), Expression::integer(3)),
]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate 4*x^3");
}
#[test]
fn test_table_does_not_match_complex_product() {
let x = symbol!(x);
let expr = Expression::mul(vec![
Expression::symbol(x.clone()),
Expression::function("sin", vec![Expression::symbol(x.clone())]),
]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_none(), "Should not match x*sin(x) pattern");
}
#[test]
fn test_table_does_not_match_composition() {
let x = symbol!(x);
let x_squared = Expression::pow(Expression::symbol(x.clone()), Expression::integer(2));
let expr = Expression::function("sin", vec![x_squared]);
let result = try_table_lookup(&expr, &x);
assert!(result.is_none(), "Should not match sin(x^2) pattern");
}
#[test]
fn test_table_does_not_match_wrong_variable() {
let x = symbol!(x);
let y = symbol!(y);
let expr = Expression::function("sin", vec![Expression::symbol(y)]);
let result = try_table_lookup(&expr, &x);
assert!(
result.is_none(),
"Should not match sin(y) when integrating wrt x"
);
}
#[test]
fn test_table_negative_power() {
let x = symbol!(x);
let expr = Expression::pow(Expression::symbol(x.clone()), Expression::integer(-2));
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate x^(-2)");
}
#[test]
fn test_table_negative_power_3() {
let x = symbol!(x);
let expr = Expression::pow(Expression::symbol(x.clone()), Expression::integer(-3));
let result = try_table_lookup(&expr, &x);
assert!(result.is_some(), "Should integrate x^(-3)");
}