use crate::int::algos::support::limbs::is_zero;
use crate::int::types::compute_limbs::{ComputeLimbs, Limbs};
fn div_small_radix(limbs: &mut [u64], radix: u64) -> u64 {
let mut rem: u64 = 0;
for limb in limbs.iter_mut().rev() {
let acc = ((rem as u128) << 64) | (*limb as u128);
*limb = (acc / (radix as u128)) as u64;
rem = (acc % (radix as u128)) as u64;
}
rem
}
const POW10_19: u64 = 10_000_000_000_000_000_000;
const POW10_19_DIGITS: usize = 19;
pub(crate) fn fmt_into<'a, const N: usize>(
limbs: &[u64],
radix: u64,
lower: bool,
buf: &'a mut [u8],
) -> &'a str
where
Limbs<N>: ComputeLimbs,
{
if is_zero(limbs) {
let last = buf.len() - 1;
buf[last] = b'0';
return core::str::from_utf8(&buf[last..]).unwrap();
}
let mut work_buf = Limbs::<N>::single_u64();
let work = work_buf.as_mut();
work[..limbs.len()].copy_from_slice(limbs);
let wl = limbs.len();
let mut pos = buf.len();
if radix == 10 {
loop {
let chunk = div_small_radix(&mut work[..wl], POW10_19);
if is_zero(&work[..wl]) {
let mut v = chunk;
loop {
pos -= 1;
buf[pos] = b'0' + (v % 10) as u8;
v /= 10;
if v == 0 {
break;
}
}
break;
}
let mut v = chunk;
for _ in 0..POW10_19_DIGITS {
pos -= 1;
buf[pos] = b'0' + (v % 10) as u8;
v /= 10;
}
}
return core::str::from_utf8(&buf[pos..]).unwrap();
}
let digits: &[u8] = if lower {
b"0123456789abcdef"
} else {
b"0123456789ABCDEF"
};
while !is_zero(&work[..wl]) {
let r = div_small_radix(&mut work[..wl], radix);
pos -= 1;
buf[pos] = digits[r as usize];
}
core::str::from_utf8(&buf[pos..]).unwrap()
}