use std::io::Write;
use rand::Rng;
use super::*;
fn coerce<T, U>(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::<i128, Option<i128>>($f2)(a_, b_)
else {
continue;
};
let mut o = coerce::<i128, String>($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);
}