#![cfg(all(feature = "poly", feature = "rational"))]
use puremp::{Int, Poly, Rational};
fn pint(cs: &[i64]) -> Poly<Int> {
Poly::new(cs.iter().map(|&c| Int::from(c)).collect())
}
fn prat(cs: &[i64]) -> Poly<Rational> {
Poly::new(cs.iter().map(|&c| Rational::from(c)).collect())
}
#[test]
fn ring_operations() {
let a = pint(&[1, 1]);
let b = pint(&[-1, 1]);
assert_eq!(&a * &b, pint(&[-1, 0, 1]));
assert_eq!((&a + &b), pint(&[0, 2]));
assert_eq!(a.degree(), Some(1));
assert_eq!(Poly::<Int>::zero().degree(), None);
assert_eq!((&a * &b).eval(&Int::from(3)), Int::from(8));
assert_eq!(pint(&[1, 0, 2, 1]).derivative(), pint(&[0, 4, 3]));
assert_eq!(pint(&[-1, 0, 1]).to_string(), "1·x^2 + -1");
}
#[test]
fn field_division_and_gcd() {
let num = prat(&[-1, 0, 1]);
let den = prat(&[-1, 1]);
let (q, r) = num.div_rem(&den);
assert_eq!(q, prat(&[1, 1]));
assert!(r.is_zero());
let (q2, r2) = prat(&[1, 0, 1]).div_rem(&prat(&[-1, 1]));
assert_eq!(q2, prat(&[1, 1]));
assert_eq!(r2, prat(&[2]));
let g = prat(&[-1, 0, 1]).gcd(&prat(&[1, -2, 1]));
assert_eq!(g, prat(&[-1, 1])); assert!(g.leading().unwrap().is_one());
}
#[test]
fn real_root_isolation_and_approximation() {
use puremp::{Float, RoundingMode};
let n = RoundingMode::Nearest;
let p = prat(&[-6, 11, -6, 1]);
assert_eq!(p.real_root_count(), 3);
let roots = p.real_roots(53, n);
assert_eq!(roots.len(), 3);
let vals: Vec<f64> = roots.iter().map(Float::to_f64).collect();
assert_eq!(vals, vec![1.0, 2.0, 3.0]);
let p2 = prat(&[-2, 0, 1]);
assert_eq!(p2.real_root_count(), 2);
let r = p2.real_roots(60, n);
assert!((r[0].to_f64() + core::f64::consts::SQRT_2).abs() < 1e-15);
assert!((r[1].to_f64() - core::f64::consts::SQRT_2).abs() < 1e-15);
assert_eq!(prat(&[1, 0, 1]).real_root_count(), 0);
assert!(prat(&[1, 0, 1]).real_roots(30, n).is_empty());
assert_eq!(
p.count_real_roots_in(
&Rational::new(3.into(), 2.into()),
&Rational::new(7.into(), 2.into())
),
2
);
assert_eq!(prat(&[1, -2, 1]).real_root_count(), 1);
}