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`. 
2934pub  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. 
4057pub  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`. 
59115pub ( 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