11//! Bit manipulation functions.
22
3- use crate :: { BoxedUint , Limb , Zero } ;
3+ use crate :: { BoxedUint , ConstChoice , Limb , Zero } ;
44use subtle:: { Choice , ConditionallySelectable , ConstantTimeEq } ;
55
66impl BoxedUint {
@@ -24,6 +24,11 @@ impl BoxedUint {
2424 Limb :: BITS * n - leading_zeros
2525 }
2626
27+ /// `floor(log2(self.bits_precision()))`.
28+ pub ( crate ) fn log2_bits ( & self ) -> u32 {
29+ u32:: BITS - self . bits_precision ( ) . leading_zeros ( ) - 1
30+ }
31+
2732 /// Calculate the number of bits needed to represent this number in variable-time with respect
2833 /// to `self`.
2934 pub fn bits_vartime ( & self ) -> u32 {
@@ -36,6 +41,18 @@ impl BoxedUint {
3641 Limb :: BITS * ( i as u32 + 1 ) - limb. leading_zeros ( )
3742 }
3843
44+ /// Returns `true` if the bit at position `index` is set, `false` otherwise.
45+ ///
46+ /// # Remarks
47+ /// This operation is variable time with respect to `index` only.
48+ pub fn bit_vartime ( & self , index : u32 ) -> bool {
49+ if index >= self . bits_precision ( ) {
50+ false
51+ } else {
52+ ( self . limbs [ ( index / Limb :: BITS ) as usize ] . 0 >> ( index % Limb :: BITS ) ) & 1 == 1
53+ }
54+ }
55+
3956 /// Get the precision of this [`BoxedUint`] in bits.
4057 pub fn bits_precision ( & self ) -> u32 {
4158 self . limbs . len ( ) as u32 * Limb :: BITS
@@ -55,6 +72,45 @@ impl BoxedUint {
5572 count
5673 }
5774
75+ /// Calculate the number of trailing ones in the binary representation of this number.
76+ pub fn trailing_ones ( & self ) -> u32 {
77+ let limbs = self . as_limbs ( ) ;
78+
79+ let mut count = 0 ;
80+ let mut i = 0 ;
81+ let mut nonmax_limb_not_encountered = ConstChoice :: TRUE ;
82+ while i < limbs. len ( ) {
83+ let l = limbs[ i] ;
84+ let z = l. trailing_ones ( ) ;
85+ count += nonmax_limb_not_encountered. if_true_u32 ( z) ;
86+ nonmax_limb_not_encountered =
87+ nonmax_limb_not_encountered. and ( ConstChoice :: from_word_eq ( l. 0 , Limb :: MAX . 0 ) ) ;
88+ i += 1 ;
89+ }
90+
91+ count
92+ }
93+
94+ /// Calculate the number of trailing ones in the binary representation of this number,
95+ /// variable time in `self`.
96+ pub fn trailing_ones_vartime ( & self ) -> u32 {
97+ let limbs = self . as_limbs ( ) ;
98+
99+ let mut count = 0 ;
100+ let mut i = 0 ;
101+ while i < limbs. len ( ) {
102+ let l = limbs[ i] ;
103+ let z = l. trailing_ones ( ) ;
104+ count += z;
105+ if z != Limb :: BITS {
106+ break ;
107+ }
108+ i += 1 ;
109+ }
110+
111+ count
112+ }
113+
58114 /// Sets the bit at `index` to 0 or 1 depending on the value of `bit_value`.
59115 pub ( crate ) fn set_bit ( & mut self , index : u32 , bit_value : Choice ) {
60116 let limb_num = ( index / Limb :: BITS ) as usize ;
@@ -89,6 +145,18 @@ mod tests {
89145 result
90146 }
91147
148+ #[ test]
149+ fn bit_vartime ( ) {
150+ let u = uint_with_bits_at ( & [ 16 , 48 , 112 , 127 , 255 ] ) ;
151+ assert ! ( !u. bit_vartime( 0 ) ) ;
152+ assert ! ( !u. bit_vartime( 1 ) ) ;
153+ assert ! ( u. bit_vartime( 16 ) ) ;
154+ assert ! ( u. bit_vartime( 127 ) ) ;
155+ assert ! ( u. bit_vartime( 255 ) ) ;
156+ assert ! ( !u. bit_vartime( 256 ) ) ;
157+ assert ! ( !u. bit_vartime( 260 ) ) ;
158+ }
159+
92160 #[ test]
93161 fn bits ( ) {
94162 assert_eq ! ( 0 , BoxedUint :: zero( ) . bits( ) ) ;
@@ -119,4 +187,40 @@ mod tests {
119187 u. set_bit ( 150 , Choice :: from ( 0 ) ) ;
120188 assert_eq ! ( u, uint_with_bits_at( & [ 16 , 79 ] ) ) ;
121189 }
190+
191+ #[ test]
192+ fn trailing_ones ( ) {
193+ let u = !uint_with_bits_at ( & [ 16 , 79 , 150 ] ) ;
194+ assert_eq ! ( u. trailing_ones( ) , 16 ) ;
195+
196+ let u = !uint_with_bits_at ( & [ 79 , 150 ] ) ;
197+ assert_eq ! ( u. trailing_ones( ) , 79 ) ;
198+
199+ let u = !uint_with_bits_at ( & [ 150 , 207 ] ) ;
200+ assert_eq ! ( u. trailing_ones( ) , 150 ) ;
201+
202+ let u = !uint_with_bits_at ( & [ 0 , 150 , 207 ] ) ;
203+ assert_eq ! ( u. trailing_ones( ) , 0 ) ;
204+
205+ let u = !BoxedUint :: zero_with_precision ( 256 ) ;
206+ assert_eq ! ( u. trailing_ones( ) , 256 ) ;
207+ }
208+
209+ #[ test]
210+ fn trailing_ones_vartime ( ) {
211+ let u = !uint_with_bits_at ( & [ 16 , 79 , 150 ] ) ;
212+ assert_eq ! ( u. trailing_ones_vartime( ) , 16 ) ;
213+
214+ let u = !uint_with_bits_at ( & [ 79 , 150 ] ) ;
215+ assert_eq ! ( u. trailing_ones_vartime( ) , 79 ) ;
216+
217+ let u = !uint_with_bits_at ( & [ 150 , 207 ] ) ;
218+ assert_eq ! ( u. trailing_ones_vartime( ) , 150 ) ;
219+
220+ let u = !uint_with_bits_at ( & [ 0 , 150 , 207 ] ) ;
221+ assert_eq ! ( u. trailing_ones_vartime( ) , 0 ) ;
222+
223+ let u = !BoxedUint :: zero_with_precision ( 256 ) ;
224+ assert_eq ! ( u. trailing_ones_vartime( ) , 256 ) ;
225+ }
122226}
0 commit comments