use super::HeaplessBigInt;
use crate::MachineWord;
use const_num_traits::{Personality, PersonalityTag};
impl<T: MachineWord, const CAP: usize, P: Personality> HeaplessBigInt<T, CAP, P> {
pub fn bit_length(&self) -> usize {
let width = self.len as usize * core::mem::size_of::<T>() * 8;
width - self.leading_zeros()
}
pub fn leading_zeros(&self) -> usize {
let word_bits = core::mem::size_of::<T>() * 8;
match P::TAG {
PersonalityTag::Nct => {
let len = self.len as usize;
let mut i = len;
while i > 0 {
i -= 1;
let limb = self.limbs[i];
if !super::is_zero(&limb) {
return (len - 1 - i) * word_bits + limb.leading_zeros() as usize;
}
}
len * word_bits
}
PersonalityTag::Ct => {
let n = self.len as usize;
let s = self.limbs.get(..n).unwrap_or(&self.limbs);
crate::fixeduint::const_leading_zeros_ct(s) as usize
}
}
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> const_num_traits::BitWidth
for HeaplessBigInt<T, CAP, P>
{
fn bit_width(self) -> u32 {
self.bit_length() as u32
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> const_num_traits::BitWidth
for &HeaplessBigInt<T, CAP, P>
{
fn bit_width(self) -> u32 {
self.bit_length() as u32
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> const_num_traits::BitsPrecision
for HeaplessBigInt<T, CAP, P>
{
fn bits_precision(&self) -> u32 {
self.len as u32 * (core::mem::size_of::<T>() as u32 * 8)
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> const_num_traits::BitsPrecision
for &HeaplessBigInt<T, CAP, P>
{
fn bits_precision(&self) -> u32 {
self.len as u32 * (core::mem::size_of::<T>() as u32 * 8)
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> const_num_traits::WithPrecision
for HeaplessBigInt<T, CAP, P>
{
fn widen_to_precision(self, bits_precision: u32) -> Self {
let word_bits = core::mem::size_of::<T>() as u32 * 8;
let target_len = bits_precision.div_ceil(word_bits) as u16;
self.widened(target_len.max(self.len()))
}
}