use crate::{Limb, UInt, Word};
impl<const LIMBS: usize> UInt<LIMBS> {
#[inline(always)]
pub const fn bit_vartime(self, index: usize) -> Word {
if index >= LIMBS * Limb::BIT_SIZE {
0
} else {
(self.limbs[index / Limb::BIT_SIZE].0 >> (index % Limb::BIT_SIZE)) & 1
}
}
#[deprecated(note = "please use `bits_vartime` instead")]
#[inline(always)]
pub const fn bits(self) -> usize {
self.bits_vartime()
}
#[allow(trivial_numeric_casts)]
pub const fn bits_vartime(self) -> usize {
let mut i = LIMBS - 1;
while i > 0 && self.limbs[i].0 == 0 {
i -= 1;
}
let limb = self.limbs[i].0;
let bits = (Limb::BIT_SIZE * (i + 1)) as Word - limb.leading_zeros() as Word;
Limb::ct_select(
Limb(bits),
Limb::ZERO,
!self.limbs[0].is_nonzero() & !Limb(i as Word).is_nonzero(),
)
.0 as usize
}
}
#[cfg(test)]
mod tests {
use crate::U128;
#[test]
fn bit_vartime_ok() {
let u = U128::from_be_hex("f0010000000000000001000000010000");
assert_eq!(u.bit_vartime(0), 0);
assert_eq!(u.bit_vartime(1), 0);
assert_eq!(u.bit_vartime(16), 1);
assert_eq!(u.bit_vartime(127), 1);
assert_eq!(u.bit_vartime(130), 0);
}
}