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 {
@@ -24,6 +24,11 @@ impl BoxedUint {
24
24
Limb :: BITS * n - leading_zeros
25
25
}
26
26
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
+
27
32
/// Calculate the number of bits needed to represent this number in variable-time with respect
28
33
/// to `self`.
29
34
pub fn bits_vartime ( & self ) -> u32 {
@@ -36,6 +41,18 @@ impl BoxedUint {
36
41
Limb :: BITS * ( i as u32 + 1 ) - limb. leading_zeros ( )
37
42
}
38
43
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
+
39
56
/// Get the precision of this [`BoxedUint`] in bits.
40
57
pub fn bits_precision ( & self ) -> u32 {
41
58
self . limbs . len ( ) as u32 * Limb :: BITS
@@ -55,6 +72,45 @@ impl BoxedUint {
55
72
count
56
73
}
57
74
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
+
58
114
/// Sets the bit at `index` to 0 or 1 depending on the value of `bit_value`.
59
115
pub ( crate ) fn set_bit ( & mut self , index : u32 , bit_value : Choice ) {
60
116
let limb_num = ( index / Limb :: BITS ) as usize ;
@@ -89,6 +145,18 @@ mod tests {
89
145
result
90
146
}
91
147
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
+
92
160
#[ test]
93
161
fn bits ( ) {
94
162
assert_eq ! ( 0 , BoxedUint :: zero( ) . bits( ) ) ;
@@ -119,4 +187,40 @@ mod tests {
119
187
u. set_bit ( 150 , Choice :: from ( 0 ) ) ;
120
188
assert_eq ! ( u, uint_with_bits_at( & [ 16 , 79 ] ) ) ;
121
189
}
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
+ }
122
226
}
0 commit comments