use symplex::prelude::*;
#[test]
fn apart_simple() {
let ctx = Context::new();
let x = ctx.symbol("x");
let expr = 1 / (&x.powi(2) - 1);
let decomposed = expr.partial_fractions(&x);
let s = format!("{decomposed}");
assert!(
s != format!("{expr}") || s.contains("1/"),
"should decompose: {s}"
);
}
#[test]
fn apart_already_simple() {
let ctx = Context::new();
let x = ctx.symbol("x");
let expr = &x + 1;
let result = expr.partial_fractions(&x);
assert_eq!(format!("{result}"), "x + 1");
}
#[test]
fn nsolve_x_minus_cos_x() {
let ctx = Context::new();
let x = ctx.symbol("x");
let expr = &x - &x.cos();
let root = expr.solve_numeric(&x, 1.0, 50, 1e-12).unwrap();
assert!((root - 0.7390851332).abs() < 1e-6, "got: {root}");
}
#[test]
fn nsolve_x_squared_minus_2() {
let ctx = Context::new();
let x = ctx.symbol("x");
let expr = &x.powi(2) - 2;
let root = expr.solve_numeric(&x, 1.5, 50, 1e-12).unwrap();
assert!(
(root - std::f64::consts::SQRT_2).abs() < 1e-8,
"got: {root}"
);
}
#[test]
fn nsolve_exp_minus_2() {
let ctx = Context::new();
let x = ctx.symbol("x");
let expr = &x.exp() - 2;
let root = expr.solve_numeric(&x, 1.0, 50, 1e-12).unwrap();
assert!((root - 2.0_f64.ln()).abs() < 1e-8, "got: {root}");
}
#[test]
fn expand_trig_sin_sum() {
let ctx = Context::new();
let (x, y) = (ctx.symbol("x"), ctx.symbol("y"));
let expr = (&x + &y).sin();
let expanded = expr.expand_trig();
let s = format!("{expanded}");
assert!(s.contains("sin(x)"), "should contain sin(x): {s}");
assert!(s.contains("cos(y)"), "should contain cos(y): {s}");
}
#[test]
fn expand_trig_cos_sum() {
let ctx = Context::new();
let (x, y) = (ctx.symbol("x"), ctx.symbol("y"));
let expr = (&x + &y).cos();
let expanded = expr.expand_trig();
let s = format!("{expanded}");
assert!(s.contains("cos(x)"), "should contain cos(x): {s}");
assert!(s.contains("sin(x)"), "should contain sin(x): {s}");
}
#[test]
fn expand_trig_bare_sin_unchanged() {
let ctx = Context::new();
let x = ctx.symbol("x");
let expr = x.sin();
let expanded = expr.expand_trig();
assert_eq!(format!("{expanded}"), "sin(x)");
}
#[test]
fn poly_gcd_common_factor() {
let ctx = Context::new();
let x = ctx.symbol("x");
let a = &x.powi(2) - 1;
let b = &x - 1;
let g = a.poly_gcd(&b, &x).unwrap();
let s = format!("{g}");
assert!(s.contains("x"), "gcd should involve x: {s}");
}
#[test]
fn poly_gcd_coprime() {
let ctx = Context::new();
let x = ctx.symbol("x");
let a = &x + 1;
let b = &x + 2;
let g = a.poly_gcd(&b, &x).unwrap();
assert_eq!(format!("{g}"), "1");
}
#[test]
fn poly_lcm_basic() {
let ctx = Context::new();
let x = ctx.symbol("x");
let a = &x - 1;
let b = &x + 1;
let lcm = a.poly_lcm(&b, &x).unwrap();
let s = format!("{lcm}");
assert!(s.contains("x^2"), "lcm should be degree 2: {s}");
}
#[test]
fn eval_sin_neg_x() {
let ctx = Context::new();
let x = ctx.symbol("x");
let expr = (-&x).sin();
let evaled = expr.eval();
assert_eq!(format!("{evaled}"), "-sin(x)");
}
#[test]
fn eval_cos_neg_x() {
let ctx = Context::new();
let x = ctx.symbol("x");
let expr = (-&x).cos();
let evaled = expr.eval();
assert_eq!(format!("{evaled}"), "cos(x)");
}
#[test]
fn eval_tan_neg_x() {
let ctx = Context::new();
let x = ctx.symbol("x");
let expr = (-&x).tan();
let evaled = expr.eval();
assert_eq!(format!("{evaled}"), "-tan(x)");
}
#[test]
fn display_inverse_hyperbolic() {
let ctx = Context::new();
let x = ctx.symbol("x");
assert_eq!(format!("{}", x.asinh()), "asinh(x)");
assert_eq!(format!("{}", x.acosh()), "acosh(x)");
assert_eq!(format!("{}", x.atanh()), "atanh(x)");
}
#[test]
fn eval_asinh_zero() {
let ctx = Context::new();
let result = ctx.int(0).asinh().eval();
assert_eq!(format!("{result}"), "0");
}
#[test]
fn eval_acosh_one() {
let ctx = Context::new();
let result = ctx.int(1).acosh().eval();
assert_eq!(format!("{result}"), "0");
}
#[test]
fn eval_atanh_zero() {
let ctx = Context::new();
let result = ctx.int(0).atanh().eval();
assert_eq!(format!("{result}"), "0");
}
#[test]
fn diff_asinh() {
let ctx = Context::new();
let x = ctx.symbol("x");
let d = x.asinh().diff(&x);
let s = format!("{d}");
assert!(s.contains("sqrt"), "should contain sqrt: {s}");
}
#[test]
fn parse_inverse_hyperbolic() {
let ctx = Context::new();
let e = symplex::parse::parse(&ctx, "asinh(x) + acosh(x) + atanh(x)").unwrap();
let s = format!("{e}");
assert!(
s.contains("asinh") && s.contains("acosh") && s.contains("atanh"),
"got: {s}"
);
}