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..50000 {
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::<8>::new(a).to_int().to_string()
} => |a, b| Some(a) }
with!(fn test_add = |a, b| {
(AP::<8>::new(a) + b).to_string()
} => |a, b| a.checked_add(b));
with!(fn test_sub = |a, b| {
(AP::<8>::new(a) - b).to_string()
} => |a, b| a.checked_sub(b));
with!(fn test_mul = |a, b| {
(AP::<8>::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::<8>::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));
// #[test]
// fn fibtest() {
// fn fib(n: usize) -> (AP, AP) {
// if n == 0 {
// return (AP::new(0), AP::new(1));
// };
// let (α, β) = fib(n >> 1);
// let γ = &α * &((&β.shl::<1>()) - &α);
// let δ = &(&α * &α) + &(&β * &β);
// if n & 1 == 0 {
// return (γ, δ);
// }
// let t = &γ + &δ;
// (δ, t)
// }
// 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);
// let x = fib(1_000_000).0;
// }