crypto_bigint/uint/
bits.rs
1use crate::{Limb, UInt, Word};
2
3impl<const LIMBS: usize> UInt<LIMBS> {
4 #[inline(always)]
7 pub const fn bit_vartime(self, index: usize) -> Word {
8 if index >= LIMBS * Limb::BIT_SIZE {
9 0
10 } else {
11 (self.limbs[index / Limb::BIT_SIZE].0 >> (index % Limb::BIT_SIZE)) & 1
12 }
13 }
14
15 #[deprecated(note = "please use `bits_vartime` instead")]
17 #[inline(always)]
18 pub const fn bits(self) -> usize {
19 self.bits_vartime()
20 }
21
22 #[allow(trivial_numeric_casts)]
24 pub const fn bits_vartime(self) -> usize {
25 let mut i = LIMBS - 1;
26 while i > 0 && self.limbs[i].0 == 0 {
27 i -= 1;
28 }
29
30 let limb = self.limbs[i].0;
31 let bits = (Limb::BIT_SIZE * (i + 1)) as Word - limb.leading_zeros() as Word;
32
33 Limb::ct_select(
34 Limb(bits),
35 Limb::ZERO,
36 !self.limbs[0].is_nonzero() & !Limb(i as Word).is_nonzero(),
37 )
38 .0 as usize
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use crate::U128;
45
46 #[test]
47 fn bit_vartime_ok() {
48 let u = U128::from_be_hex("f0010000000000000001000000010000");
49 assert_eq!(u.bit_vartime(0), 0);
50 assert_eq!(u.bit_vartime(1), 0);
51 assert_eq!(u.bit_vartime(16), 1);
52 assert_eq!(u.bit_vartime(127), 1);
53 assert_eq!(u.bit_vartime(130), 0);
54 }
55}