crypto_bigint/uint/
bits.rs

1use crate::{Limb, UInt, Word};
2
3impl<const LIMBS: usize> UInt<LIMBS> {
4    /// Get the value of the bit at position `index`, as a 0- or 1-valued Word.
5    /// Returns 0 for indices out of range.
6    #[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    /// Calculate the number of bits needed to represent this number.
16    #[deprecated(note = "please use `bits_vartime` instead")]
17    #[inline(always)]
18    pub const fn bits(self) -> usize {
19        self.bits_vartime()
20    }
21
22    /// Calculate the number of bits needed to represent this number.
23    #[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}