|
1 | 1 | //! Bit manipulation functions. |
2 | 2 |
|
3 | | -use crate::{BoxedUint, Limb, Zero}; |
| 3 | +use crate::{BoxedUint, ConstChoice, Limb, Zero}; |
4 | 4 | use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; |
5 | 5 |
|
6 | 6 | impl BoxedUint { |
@@ -68,6 +68,25 @@ impl BoxedUint { |
68 | 68 | count |
69 | 69 | } |
70 | 70 |
|
| 71 | + /// Calculate the number of trailing ones in the binary representation of this number. |
| 72 | + pub fn trailing_ones(&self) -> u32 { |
| 73 | + let limbs = self.as_limbs(); |
| 74 | + |
| 75 | + let mut count = 0; |
| 76 | + let mut i = 0; |
| 77 | + let mut nonmax_limb_not_encountered = ConstChoice::TRUE; |
| 78 | + while i < limbs.len() { |
| 79 | + let l = limbs[i]; |
| 80 | + let z = l.trailing_ones(); |
| 81 | + count += nonmax_limb_not_encountered.if_true_u32(z); |
| 82 | + nonmax_limb_not_encountered = |
| 83 | + nonmax_limb_not_encountered.and(ConstChoice::from_word_eq(l.0, Limb::MAX.0)); |
| 84 | + i += 1; |
| 85 | + } |
| 86 | + |
| 87 | + count |
| 88 | + } |
| 89 | + |
71 | 90 | /// Sets the bit at `index` to 0 or 1 depending on the value of `bit_value`. |
72 | 91 | pub(crate) fn set_bit(&mut self, index: u32, bit_value: Choice) { |
73 | 92 | let limb_num = (index / Limb::BITS) as usize; |
@@ -144,4 +163,22 @@ mod tests { |
144 | 163 | assert!(!u.bit_vartime(256)); |
145 | 164 | assert!(!u.bit_vartime(260)); |
146 | 165 | } |
| 166 | + |
| 167 | + #[test] |
| 168 | + fn trailing_ones() { |
| 169 | + let u = !uint_with_bits_at(&[16, 79, 150]); |
| 170 | + assert_eq!(u.trailing_ones(), 16); |
| 171 | + |
| 172 | + let u = !uint_with_bits_at(&[79, 150]); |
| 173 | + assert_eq!(u.trailing_ones(), 79); |
| 174 | + |
| 175 | + let u = !uint_with_bits_at(&[150, 207]); |
| 176 | + assert_eq!(u.trailing_ones(), 150); |
| 177 | + |
| 178 | + let u = !uint_with_bits_at(&[0, 150, 207]); |
| 179 | + assert_eq!(u.trailing_ones(), 0); |
| 180 | + |
| 181 | + let u = !BoxedUint::zero_with_precision(256); |
| 182 | + assert_eq!(u.trailing_ones(), 256); |
| 183 | + } |
147 | 184 | } |
0 commit comments