1use subtle::Choice;
2
3use crate::{BitOps, ConstChoice, Limb, Uint, Word};
4
5#[inline(always)]
6pub(crate) const fn bit(limbs: &[Limb], index: u32) -> ConstChoice {
7 let limb_num = index / Limb::BITS;
8 let index_in_limb = index % Limb::BITS;
9 let index_mask = 1 << index_in_limb;
10
11 let mut result = 0;
12 let mut i = 0;
13 while i < limbs.len() {
14 let bit = limbs[i].0 & index_mask;
15 let is_right_limb = ConstChoice::from_u32_eq(i as u32, limb_num);
16 result |= is_right_limb.if_true_word(bit);
17 i += 1;
18 }
19
20 ConstChoice::from_word_lsb(result >> index_in_limb)
21}
22
23pub(crate) const fn leading_zeros(limbs: &[Limb]) -> u32 {
25 let mut count = 0;
26 let mut i = limbs.len();
27 let mut nonzero_limb_not_encountered = ConstChoice::TRUE;
28 while i > 0 {
29 i -= 1;
30 let l = limbs[i];
31 let z = l.leading_zeros();
32 count += nonzero_limb_not_encountered.if_true_u32(z);
33 nonzero_limb_not_encountered =
34 nonzero_limb_not_encountered.and(ConstChoice::from_word_nonzero(l.0).not());
35 }
36
37 count
38}
39
40#[inline(always)]
41pub(crate) const fn bit_vartime(limbs: &[Limb], index: u32) -> bool {
42 let limb_num = (index / Limb::BITS) as usize;
43 let index_in_limb = (index % Limb::BITS) as usize;
44 if limb_num >= limbs.len() {
45 false
46 } else {
47 (limbs[limb_num].0 >> index_in_limb) & 1 == 1
48 }
49}
50
51#[inline(always)]
52pub(crate) const fn bits_vartime(limbs: &[Limb]) -> u32 {
53 let mut i = limbs.len() - 1;
54 while i > 0 && limbs[i].0 == 0 {
55 i -= 1;
56 }
57
58 let limb = limbs[i];
59 Limb::BITS * (i as u32 + 1) - limb.leading_zeros()
60}
61
62#[inline(always)]
63pub(crate) const fn trailing_zeros(limbs: &[Limb]) -> u32 {
64 let mut count = 0;
65 let mut i = 0;
66 let mut nonzero_limb_not_encountered = ConstChoice::TRUE;
67 while i < limbs.len() {
68 let l = limbs[i];
69 let z = l.trailing_zeros();
70 count += nonzero_limb_not_encountered.if_true_u32(z);
71 nonzero_limb_not_encountered =
72 nonzero_limb_not_encountered.and(ConstChoice::from_word_nonzero(l.0).not());
73 i += 1;
74 }
75
76 count
77}
78
79#[inline(always)]
80pub(crate) const fn trailing_zeros_vartime(limbs: &[Limb]) -> u32 {
81 let mut count = 0;
82 let mut i = 0;
83 while i < limbs.len() {
84 let l = limbs[i];
85 let z = l.trailing_zeros();
86 count += z;
87 if z != Limb::BITS {
88 break;
89 }
90 i += 1;
91 }
92
93 count
94}
95
96#[inline(always)]
97pub(crate) const fn trailing_ones(limbs: &[Limb]) -> u32 {
98 let mut count = 0;
99 let mut i = 0;
100 let mut nonmax_limb_not_encountered = ConstChoice::TRUE;
101 while i < limbs.len() {
102 let l = limbs[i];
103 let z = l.trailing_ones();
104 count += nonmax_limb_not_encountered.if_true_u32(z);
105 nonmax_limb_not_encountered =
106 nonmax_limb_not_encountered.and(ConstChoice::from_word_eq(l.0, Limb::MAX.0));
107 i += 1;
108 }
109
110 count
111}
112
113#[inline(always)]
114pub(crate) const fn trailing_ones_vartime(limbs: &[Limb]) -> u32 {
115 let mut count = 0;
116 let mut i = 0;
117 while i < limbs.len() {
118 let l = limbs[i];
119 let z = l.trailing_ones();
120 count += z;
121 if z != Limb::BITS {
122 break;
123 }
124 i += 1;
125 }
126
127 count
128}
129
130impl<const LIMBS: usize> Uint<LIMBS> {
131 pub const fn bit(&self, index: u32) -> ConstChoice {
134 bit(&self.limbs, index)
135 }
136
137 #[inline(always)]
142 pub const fn bit_vartime(&self, index: u32) -> bool {
143 bit_vartime(&self.limbs, index)
144 }
145
146 #[inline]
148 pub const fn bits(&self) -> u32 {
149 Self::BITS - self.leading_zeros()
150 }
151
152 pub const fn bits_vartime(&self) -> u32 {
155 bits_vartime(&self.limbs)
156 }
157
158 pub const fn leading_zeros(&self) -> u32 {
160 leading_zeros(&self.limbs)
161 }
162
163 pub const fn leading_zeros_vartime(&self) -> u32 {
166 Self::BITS - self.bits_vartime()
167 }
168
169 pub const fn trailing_zeros(&self) -> u32 {
171 trailing_zeros(&self.limbs)
172 }
173
174 pub const fn trailing_zeros_vartime(&self) -> u32 {
177 trailing_zeros_vartime(&self.limbs)
178 }
179
180 pub const fn trailing_ones(&self) -> u32 {
182 trailing_ones(&self.limbs)
183 }
184
185 pub const fn trailing_ones_vartime(&self) -> u32 {
188 trailing_ones_vartime(&self.limbs)
189 }
190
191 pub(crate) const fn set_bit(self, index: u32, bit_value: ConstChoice) -> Self {
193 let mut result = self;
194 let limb_num = index / Limb::BITS;
195 let index_in_limb = index % Limb::BITS;
196 let index_mask = 1 << index_in_limb;
197
198 let mut i = 0;
199 while i < LIMBS {
200 let is_right_limb = ConstChoice::from_u32_eq(i as u32, limb_num);
201 let old_limb = result.limbs[i].0;
202 let new_limb = bit_value.select_word(old_limb & !index_mask, old_limb | index_mask);
203 result.limbs[i] = Limb(is_right_limb.select_word(old_limb, new_limb));
204 i += 1;
205 }
206 result
207 }
208
209 pub(crate) const fn set_bit_vartime(self, index: u32, bit_value: bool) -> Self {
212 let mut result = self;
213 let limb_num = (index / Limb::BITS) as usize;
214 let index_in_limb = index % Limb::BITS;
215 if bit_value {
216 result.limbs[limb_num].0 |= 1 << index_in_limb;
217 } else {
218 #[allow(trivial_numeric_casts)]
219 {
220 result.limbs[limb_num].0 &= !((1 as Word) << index_in_limb);
221 }
222 }
223 result
224 }
225}
226
227impl<const LIMBS: usize> BitOps for Uint<LIMBS> {
228 fn bits_precision(&self) -> u32 {
229 Self::BITS
230 }
231
232 fn bytes_precision(&self) -> usize {
233 Self::BYTES
234 }
235
236 fn leading_zeros(&self) -> u32 {
237 self.leading_zeros()
238 }
239
240 fn bit(&self, index: u32) -> Choice {
241 self.bit(index).into()
242 }
243
244 fn set_bit(&mut self, index: u32, bit_value: Choice) {
245 *self = Self::set_bit(*self, index, bit_value.into());
246 }
247
248 fn trailing_zeros(&self) -> u32 {
249 self.trailing_zeros()
250 }
251
252 fn trailing_ones(&self) -> u32 {
253 self.trailing_ones()
254 }
255
256 fn bit_vartime(&self, index: u32) -> bool {
257 self.bit_vartime(index)
258 }
259
260 fn bits_vartime(&self) -> u32 {
261 self.bits_vartime()
262 }
263
264 fn set_bit_vartime(&mut self, index: u32, bit_value: bool) {
265 *self = Self::set_bit_vartime(*self, index, bit_value);
266 }
267
268 fn trailing_zeros_vartime(&self) -> u32 {
269 self.trailing_zeros_vartime()
270 }
271
272 fn trailing_ones_vartime(&self) -> u32 {
273 self.trailing_ones_vartime()
274 }
275}
276
277#[cfg(test)]
278mod tests {
279 use crate::{ConstChoice, U256};
280
281 fn uint_with_bits_at(positions: &[u32]) -> U256 {
282 let mut result = U256::ZERO;
283 for pos in positions {
284 result |= U256::ONE << *pos;
285 }
286 result
287 }
288
289 #[test]
290 fn bit_vartime() {
291 let u = uint_with_bits_at(&[16, 48, 112, 127, 255]);
292 assert!(!u.bit_vartime(0));
293 assert!(!u.bit_vartime(1));
294 assert!(u.bit_vartime(16));
295 assert!(u.bit_vartime(127));
296 assert!(u.bit_vartime(255));
297 assert!(!u.bit_vartime(256));
298 assert!(!u.bit_vartime(260));
299 }
300
301 #[test]
302 fn bit() {
303 let u = uint_with_bits_at(&[16, 48, 112, 127, 255]);
304 assert!(!u.bit(0).is_true_vartime());
305 assert!(!u.bit(1).is_true_vartime());
306 assert!(u.bit(16).is_true_vartime());
307 assert!(u.bit(127).is_true_vartime());
308 assert!(u.bit(255).is_true_vartime());
309 assert!(!u.bit(256).is_true_vartime());
310 assert!(!u.bit(260).is_true_vartime());
311 }
312
313 #[test]
314 fn leading_zeros() {
315 let u = uint_with_bits_at(&[256 - 16, 256 - 79, 256 - 207]);
316 assert_eq!(u.leading_zeros(), 15);
317
318 let u = uint_with_bits_at(&[256 - 79, 256 - 207]);
319 assert_eq!(u.leading_zeros(), 78);
320
321 let u = uint_with_bits_at(&[256 - 207]);
322 assert_eq!(u.leading_zeros(), 206);
323
324 let u = uint_with_bits_at(&[256 - 1, 256 - 75, 256 - 150]);
325 assert_eq!(u.leading_zeros(), 0);
326
327 let u = U256::ZERO;
328 assert_eq!(u.leading_zeros(), 256);
329 }
330
331 #[test]
332 fn leading_zeros_vartime() {
333 let u = uint_with_bits_at(&[256 - 16, 256 - 79, 256 - 207]);
334 assert_eq!(u.leading_zeros_vartime(), 15);
335
336 let u = uint_with_bits_at(&[256 - 79, 256 - 207]);
337 assert_eq!(u.leading_zeros_vartime(), 78);
338
339 let u = uint_with_bits_at(&[256 - 207]);
340 assert_eq!(u.leading_zeros_vartime(), 206);
341
342 let u = uint_with_bits_at(&[256 - 1, 256 - 75, 256 - 150]);
343 assert_eq!(u.leading_zeros_vartime(), 0);
344
345 let u = U256::ZERO;
346 assert_eq!(u.leading_zeros_vartime(), 256);
347 }
348
349 #[test]
350 fn trailing_zeros() {
351 let u = uint_with_bits_at(&[16, 79, 150]);
352 assert_eq!(u.trailing_zeros(), 16);
353
354 let u = uint_with_bits_at(&[79, 150]);
355 assert_eq!(u.trailing_zeros(), 79);
356
357 let u = uint_with_bits_at(&[150, 207]);
358 assert_eq!(u.trailing_zeros(), 150);
359
360 let u = uint_with_bits_at(&[0, 150, 207]);
361 assert_eq!(u.trailing_zeros(), 0);
362
363 let u = U256::ZERO;
364 assert_eq!(u.trailing_zeros(), 256);
365 }
366
367 #[test]
368 fn trailing_zeros_vartime() {
369 let u = uint_with_bits_at(&[16, 79, 150]);
370 assert_eq!(u.trailing_zeros_vartime(), 16);
371
372 let u = uint_with_bits_at(&[79, 150]);
373 assert_eq!(u.trailing_zeros_vartime(), 79);
374
375 let u = uint_with_bits_at(&[150, 207]);
376 assert_eq!(u.trailing_zeros_vartime(), 150);
377
378 let u = uint_with_bits_at(&[0, 150, 207]);
379 assert_eq!(u.trailing_zeros_vartime(), 0);
380
381 let u = U256::ZERO;
382 assert_eq!(u.trailing_zeros_vartime(), 256);
383 }
384
385 #[test]
386 fn trailing_ones() {
387 let u = !uint_with_bits_at(&[16, 79, 150]);
388 assert_eq!(u.trailing_ones(), 16);
389
390 let u = !uint_with_bits_at(&[79, 150]);
391 assert_eq!(u.trailing_ones(), 79);
392
393 let u = !uint_with_bits_at(&[150, 207]);
394 assert_eq!(u.trailing_ones(), 150);
395
396 let u = !uint_with_bits_at(&[0, 150, 207]);
397 assert_eq!(u.trailing_ones(), 0);
398
399 let u = U256::MAX;
400 assert_eq!(u.trailing_ones(), 256);
401 }
402
403 #[test]
404 fn trailing_ones_vartime() {
405 let u = !uint_with_bits_at(&[16, 79, 150]);
406 assert_eq!(u.trailing_ones_vartime(), 16);
407
408 let u = !uint_with_bits_at(&[79, 150]);
409 assert_eq!(u.trailing_ones_vartime(), 79);
410
411 let u = !uint_with_bits_at(&[150, 207]);
412 assert_eq!(u.trailing_ones_vartime(), 150);
413
414 let u = !uint_with_bits_at(&[0, 150, 207]);
415 assert_eq!(u.trailing_ones_vartime(), 0);
416
417 let u = U256::MAX;
418 assert_eq!(u.trailing_ones_vartime(), 256);
419 }
420
421 #[test]
422 fn set_bit() {
423 let u = uint_with_bits_at(&[16, 79, 150]);
424 assert_eq!(
425 u.set_bit(127, ConstChoice::TRUE),
426 uint_with_bits_at(&[16, 79, 127, 150])
427 );
428
429 let u = uint_with_bits_at(&[16, 79, 150]);
430 assert_eq!(
431 u.set_bit(150, ConstChoice::TRUE),
432 uint_with_bits_at(&[16, 79, 150])
433 );
434
435 let u = uint_with_bits_at(&[16, 79, 150]);
436 assert_eq!(
437 u.set_bit(127, ConstChoice::FALSE),
438 uint_with_bits_at(&[16, 79, 150])
439 );
440
441 let u = uint_with_bits_at(&[16, 79, 150]);
442 assert_eq!(
443 u.set_bit(150, ConstChoice::FALSE),
444 uint_with_bits_at(&[16, 79])
445 );
446 }
447}