use mathhook_core::algebra::polynomial_division::{polynomial_div, polynomial_quo, polynomial_rem};
use mathhook_core::{expr, symbol, Expression};
#[test]
fn test_division_exact_simple() {
let x = symbol!(x);
let dividend = expr!((x ^ 2) - 1);
let divisor = expr!(x - 1);
let (quot, rem) = polynomial_div(÷nd, &divisor, &x).unwrap();
println!("Test: (x^2 - 1) / (x - 1)");
println!("Quotient: {}, Remainder: {}", quot, rem);
assert!(rem.is_zero(), "Expected zero remainder");
}
#[test]
fn test_division_exact_cubic() {
let x = symbol!(x);
let dividend = expr!((x ^ 3) - 1);
let divisor = expr!(x - 1);
let (quot, rem) = polynomial_div(÷nd, &divisor, &x).unwrap();
println!("Test: (x^3 - 1) / (x - 1)");
println!("Quotient: {}, Remainder: {}", quot, rem);
assert!(rem.is_zero(), "Expected zero remainder for exact division");
}
#[test]
fn test_division_with_remainder_linear() {
let x = symbol!(x);
let dividend = expr!((x ^ 2) + 1);
let divisor = expr!(x - 1);
let (quot, rem) = polynomial_div(÷nd, &divisor, &x).unwrap();
println!("Test: (x^2 + 1) / (x - 1)");
println!("Quotient: {}, Remainder: {}", quot, rem);
assert!(!rem.is_zero(), "Expected non-zero remainder");
}
#[test]
fn test_division_with_remainder_quadratic() {
let x = symbol!(x);
let dividend = expr!((x ^ 3) + 2);
let divisor = expr!((x ^ 2) + 1);
let (quot, rem) = polynomial_div(÷nd, &divisor, &x).unwrap();
println!("Test: (x^3 + 2) / (x^2 + 1)");
println!("Quotient: {}, Remainder: {}", quot, rem);
assert!(!rem.is_zero(), "Expected non-zero remainder");
}
#[test]
fn test_division_by_constant() {
let x = symbol!(x);
let dividend = Expression::add(vec![expr!(x ^ 2), expr!(2 * x), Expression::integer(1)]);
let divisor = Expression::integer(2);
let (quot, rem) = polynomial_div(÷nd, &divisor, &x).unwrap();
println!("Test: (x^2 + 2x + 1) / 2");
println!("Quotient: {}, Remainder: {}", quot, rem);
assert!(
rem.is_zero(),
"Expected zero remainder for division by constant"
);
}
#[test]
fn test_division_constant_by_polynomial() {
let x = symbol!(x);
let dividend = Expression::integer(5);
let divisor = expr!(x + 1);
let (quot, rem) = polynomial_div(÷nd, &divisor, &x).unwrap();
println!("Test: 5 / (x + 1)");
println!("Quotient: {}, Remainder: {}", quot, rem);
assert_eq!(quot, Expression::integer(0), "Expected zero quotient");
assert_eq!(rem, Expression::integer(5), "Expected remainder = 5");
}
#[test]
fn test_division_equal_polynomials() {
let x = symbol!(x);
let dividend = expr!(x + 1);
let divisor = expr!(x + 1);
let (quot, rem) = polynomial_div(÷nd, &divisor, &x).unwrap();
println!("Test: (x + 1) / (x + 1)");
println!("Quotient: {}, Remainder: {}", quot, rem);
assert_eq!(quot, Expression::integer(1), "Expected quotient = 1");
assert!(rem.is_zero(), "Expected zero remainder");
}
#[test]
fn test_division_zero_dividend() {
let x = symbol!(x);
let dividend = Expression::integer(0);
let divisor = expr!(x + 1);
let (quot, rem) = polynomial_div(÷nd, &divisor, &x).unwrap();
assert_eq!(quot, Expression::integer(0));
assert_eq!(rem, Expression::integer(0));
}
#[test]
fn test_polynomial_quo_helper() {
let x = symbol!(x);
let dividend = expr!((x ^ 2) - 1);
let divisor = expr!(x - 1);
let quot = polynomial_quo(÷nd, &divisor, &x).unwrap();
println!("Test quotient only: (x^2 - 1) / (x - 1)");
println!("Quotient: {}", quot);
assert!(!quot.is_zero(), "Expected non-zero quotient");
}
#[test]
fn test_polynomial_rem_helper() {
let x = symbol!(x);
let dividend = expr!((x ^ 2) + 1);
let divisor = expr!(x - 1);
let rem = polynomial_rem(÷nd, &divisor, &x).unwrap();
println!("Test remainder only: (x^2 + 1) / (x - 1)");
println!("Remainder: {}", rem);
assert!(!rem.is_zero(), "Expected non-zero remainder");
}
#[test]
fn test_gcd_simple_linear() {
let a = expr!((x ^ 2) - 1);
let b = expr!(x - 1);
let result = a.gcd(&b);
println!("Test GCD: gcd(x^2 - 1, x - 1)");
println!("Result: {}", result);
assert!(!result.is_zero(), "Expected non-zero GCD");
}
#[test]
fn test_gcd_coprime_polynomials() {
let a = expr!(x + 1);
let b = expr!(x + 2);
let result = a.gcd(&b);
println!("Test GCD coprime: gcd(x + 1, x + 2)");
println!("Result: {}", result);
assert_eq!(
result,
Expression::integer(1),
"Expected GCD = 1 for coprime polynomials"
);
}
#[test]
fn test_gcd_common_factor_linear() {
let a = Expression::add(vec![expr!(x ^ 2), expr!(3 * x), Expression::integer(2)]);
let b = Expression::add(vec![expr!(x ^ 2), expr!(4 * x), Expression::integer(3)]);
let result = a.gcd(&b);
println!("Test GCD common factor: gcd((x+1)(x+2), (x+1)(x+3))");
println!("Result: {}", result);
assert!(!result.is_zero(), "Expected non-zero GCD");
}
#[test]
fn test_gcd_quadratic_common() {
let a = expr!((x ^ 4) - 1);
let b = expr!((x ^ 2) - 1);
let result = a.gcd(&b);
println!("Test GCD: gcd(x^4 - 1, x^2 - 1)");
println!("Result: {}", result);
assert!(!result.is_zero(), "Expected non-zero GCD");
}
#[test]
fn test_gcd_symmetric() {
let a = expr!((x ^ 3) - 1);
let b = expr!((x ^ 2) - 1);
let gcd_ab = a.gcd(&b);
let gcd_ba = b.gcd(&a);
println!("Test GCD symmetry: gcd(x^3 - 1, x^2 - 1)");
println!("gcd(a, b) = {}", gcd_ab);
println!("gcd(b, a) = {}", gcd_ba);
assert!(!gcd_ab.is_zero());
assert!(!gcd_ba.is_zero());
}
#[test]
fn test_gcd_identical_polynomials() {
let a = expr!(x + 1);
let result = a.gcd(&a);
assert_eq!(
result, a,
"GCD of identical polynomials should be the polynomial itself"
);
}
#[test]
fn test_gcd_with_zero() {
let a = expr!(x + 1);
let zero = Expression::integer(0);
let result1 = a.gcd(&zero);
let result2 = zero.gcd(&a);
assert_eq!(result1, a);
assert_eq!(result2, a);
}
#[test]
fn test_gcd_integer_coefficients() {
let a = expr!(6 * x);
let b = expr!(9 * x);
let result = a.gcd(&b);
println!("Test GCD integers: gcd(6x, 9x)");
println!("Result: {}", result);
assert!(!result.is_zero(), "Expected non-zero GCD");
}
#[test]
fn test_gcd_cubic_quadratic() {
let x = symbol!(x);
let a = Expression::add(vec![
expr!(x ^ 3),
expr!(x ^ 2),
Expression::mul(vec![Expression::integer(-1), Expression::symbol(x.clone())]),
Expression::integer(-1),
]);
let b = expr!((x ^ 2) - 1);
let result = a.gcd(&b);
println!("Test GCD cubic-quadratic: gcd(x^3 + x^2 - x - 1, x^2 - 1)");
println!("Result: {}", result);
assert!(!result.is_zero(), "Expected non-zero GCD");
}
#[test]
fn test_gcd_high_degree() {
let a = expr!((x ^ 6) - 1);
let b = expr!((x ^ 4) - 1);
let result = a.gcd(&b);
println!("Test GCD high degree: gcd(x^6 - 1, x^4 - 1)");
println!("Result: {}", result);
assert!(!result.is_zero(), "Expected non-zero GCD");
}
#[test]
fn test_lcm_basic() {
let a = expr!(x - 1);
let b = expr!(x + 1);
let result = a.lcm(&b);
println!("Test LCM: lcm(x - 1, x + 1)");
println!("Result: {}", result);
assert!(!result.is_zero(), "Expected non-zero LCM");
}
#[test]
fn test_lcm_common_factor() {
let a = expr!((x ^ 2) - 1);
let b = expr!(x - 1);
let result = a.lcm(&b);
println!("Test LCM common factor: lcm(x^2 - 1, x - 1)");
println!("Result: {}", result);
assert!(!result.is_zero(), "Expected non-zero LCM");
}
#[test]
fn test_division_verification_property() {
let x = symbol!(x);
let dividend = Expression::add(vec![
expr!(x ^ 3),
expr!(2 * (x ^ 2)),
Expression::mul(vec![Expression::integer(-1), Expression::symbol(x.clone())]),
Expression::integer(5),
]);
let divisor = expr!((x ^ 2) + 1);
let (quot, rem) = polynomial_div(÷nd, &divisor, &x).unwrap();
println!("Verification test: (x^3 + 2x^2 - x + 5) / (x^2 + 1)");
println!("Quotient: {}, Remainder: {}", quot, rem);
assert!(
!quot.is_zero() || !rem.is_zero(),
"Expected non-trivial result"
);
}
#[test]
fn test_division_coefficients_extraction() {
let x = symbol!(x);
let poly = Expression::add(vec![
expr!(3 * (x ^ 2)),
expr!(5 * x),
Expression::integer(7),
]);
let (quot, rem) = polynomial_div(&poly, &Expression::integer(1), &x).unwrap();
println!("Coefficient test: (3x^2 + 5x + 7) / 1");
println!("Quotient: {}, Remainder: {}", quot, rem);
assert!(rem.is_zero(), "Division by 1 should have zero remainder");
}