use std::io::Write; use rand::Rng; use super::*; fn coerce(f: impl FnMut(T, T) -> U) -> impl FnMut(T, T) -> U { f } macro_rules! with { (fn $ident:ident = $f:expr => $f2:expr) => { #[test] fn $ident() { let mut r = rand::rng(); for n in 0..5000 { let a_ = r.next_u64() as i64 as _; let b_ = r.next_u64() as i64 as _; let Some(ought) = coerce::>($f2)(a_, b_) else { continue; }; let mut o = coerce::($f)(a_, b_); // let x = to_int(63, &o);s assert_eq!( o, ought.to_string(), "should be {ought}, instead was {o}" ); } } }; } with! {fn roundtrip = |a, b| { AP::new(a).to_int().to_string() } => |a, b| Some(a) } with!(fn test_add = |a, b| { (AP::new(a) + b).to_string() } => |a, b| a.checked_add(b)); with!(fn test_sub = |a, b| { (AP::new(a) - b).to_string() } => |a, b| a.checked_sub(b)); with!(fn test_mul = |a, b| { (AP::new(a) * b).to_string() } => |a, b| a.checked_mul(b)); // with!(fn test_div = |a, b|{ // (AP::new(a) / b).to_string() // }=>|a, b| a.checked_div(b)); with!(fn test_shl = |a, b| { (&AP::new(a) << b as u8 as u32 / 4).to_string() }=>|a, b| a.checked_shl(dbg!(b as u8 as u32 /4))); with!(fn test_shr = |a, b| { (&AP::new(a.abs()) >> (b as u8 as u32 / 2)).to_string() }=>|a, b| a.abs().checked_shr(b as u8 as u32 / 2)); with!(fn test_cmp = |a, b| (AP::new(a).cmp(&AP::new(b)) as i128).to_string() =>|a, b| Some((a.cmp(&b)) as i128)); const fn fib(n: usize) -> (AP, AP) { if n == 0 { return (AP::new(0), AP::new(1)); }; let (α, β) = fib(n >> 1); let γ = &α * ((&β << 1) - &α); let δ = &α * &α + &β * &β; if n & 1 == 0 { return (γ, δ); } let t = γ + &δ; (δ, t) } // #[allow(long_running_const_eval)] const X: AP = fib(5000).0.globalize(); #[test] #[cfg(not(miri))] fn fibtest() { fn naive(n: usize) -> AP { let mut α = AP::new(1); let mut β = AP::new(1); for _ in 2..n { let temp = β.clone(); β += &α; α = temp; } β } assert_eq!(naive(5000), fib(5000).0); }