use oxinum_complex::CBig;
use proptest::prelude::*;
const PREC: usize = 40;
const NEAR_ZERO: f64 = 1e-6;
const HEAVY_CASES: u32 = 16;
proptest! {
#[test]
fn conj_conj_is_identity(a in -5.0f64..5.0, b in -5.0f64..5.0) {
let z = CBig::from_f64(a, b).expect("finite parts");
prop_assert!(z.conj().conj() == z);
}
#[test]
fn add_negation_is_zero(a in -5.0f64..5.0, b in -5.0f64..5.0) {
let z = CBig::from_f64(a, b).expect("finite parts");
let sum = &z + &(-&z);
prop_assert!(sum == CBig::zero());
prop_assert!(sum.is_zero());
}
#[test]
fn mul_one_is_identity(a in -5.0f64..5.0, b in -5.0f64..5.0) {
let z = CBig::from_f64(a, b).expect("finite parts");
prop_assert!(&z * &CBig::one() == z);
}
}
proptest! {
#![proptest_config(ProptestConfig { cases: HEAVY_CASES, ..ProptestConfig::default() })]
#[test]
fn exp_ln_round_trip(a in -5.0f64..5.0, b in -5.0f64..5.0) {
let mag = a.hypot(b);
prop_assume!(mag > NEAR_ZERO);
let z = CBig::from_f64(a, b).expect("finite parts");
let back = z.ln(PREC).expect("ln").exp(PREC).expect("exp");
let (re, im) = back.to_f64_parts();
let tol = 1e-12 * mag.max(1.0);
prop_assert!((re - a).abs() < tol, "re: {re} vs {a} (tol {tol})");
prop_assert!((im - b).abs() < tol, "im: {im} vs {b} (tol {tol})");
}
#[test]
fn abs_squared_matches_norm_sqr(a in -5.0f64..5.0, b in -5.0f64..5.0) {
let mag = a.hypot(b);
prop_assume!(mag > NEAR_ZERO);
let z = CBig::from_f64(a, b).expect("finite parts");
let abs = z.abs(PREC).expect("abs").to_f64().value();
let ns = z.norm_sqr().to_f64().value();
let lhs = abs * abs;
let tol = 1e-9 * ns.max(1.0);
prop_assert!((lhs - ns).abs() < tol, "abs² = {lhs}, norm_sqr = {ns} (tol {tol})");
}
}