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 mut total = 0usize;
let mut decided = 0usize;
let mut i = self.len as usize;
while i > 0 {
i -= 1;
let v = self.limbs[i];
let v_lz = v.leading_zeros() as usize;
let undecided = core::hint::black_box(!decided);
total += undecided & v_lz;
let v_nz_mask =
core::hint::black_box(((!super::is_zero(&v)) as usize).wrapping_neg());
decided |= v_nz_mask;
}
total
}
}
}
}
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()))
}
}