crypto_bigint/uint/
shr.rs
1use super::UInt;
4use crate::Limb;
5use core::ops::{Shr, ShrAssign};
6
7impl<const LIMBS: usize> UInt<LIMBS> {
8 #[inline(always)]
15 pub const fn shr_vartime(&self, shift: usize) -> Self {
16 let full_shifts = shift / Limb::BIT_SIZE;
17 let small_shift = shift & (Limb::BIT_SIZE - 1);
18 let mut limbs = [Limb::ZERO; LIMBS];
19
20 if shift > Limb::BIT_SIZE * LIMBS {
21 return Self { limbs };
22 }
23
24 let n = LIMBS - full_shifts;
25 let mut i = 0;
26
27 if small_shift == 0 {
28 while i < n {
29 limbs[i] = Limb(self.limbs[i + full_shifts].0);
30 i += 1;
31 }
32 } else {
33 while i < n {
34 let mut lo = self.limbs[i + full_shifts].0 >> small_shift;
35
36 if i < (LIMBS - 1) - full_shifts {
37 lo |= self.limbs[i + full_shifts + 1].0 << (Limb::BIT_SIZE - small_shift);
38 }
39
40 limbs[i] = Limb(lo);
41 i += 1;
42 }
43 }
44
45 Self { limbs }
46 }
47}
48
49impl<const LIMBS: usize> Shr<usize> for UInt<LIMBS> {
50 type Output = UInt<LIMBS>;
51
52 fn shr(self, rhs: usize) -> UInt<LIMBS> {
57 self.shr_vartime(rhs)
58 }
59}
60
61impl<const LIMBS: usize> Shr<usize> for &UInt<LIMBS> {
62 type Output = UInt<LIMBS>;
63
64 fn shr(self, rhs: usize) -> UInt<LIMBS> {
69 self.shr_vartime(rhs)
70 }
71}
72
73impl<const LIMBS: usize> ShrAssign<usize> for UInt<LIMBS> {
74 fn shr_assign(&mut self, rhs: usize) {
75 *self = self.shr_vartime(rhs);
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use crate::U256;
82
83 const N: U256 =
84 U256::from_be_hex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
85
86 const N_2: U256 =
87 U256::from_be_hex("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0");
88
89 #[test]
90 fn shr1() {
91 assert_eq!(N >> 1, N_2);
92 }
93}