crypto_bigint/uint/
shr.rs

1//! [`UInt`] bitwise right shift operations.
2
3use super::UInt;
4use crate::Limb;
5use core::ops::{Shr, ShrAssign};
6
7impl<const LIMBS: usize> UInt<LIMBS> {
8    /// Computes `self >> n`.
9    ///
10    /// NOTE: this operation is variable time with respect to `n` *ONLY*.
11    ///
12    /// When used with a fixed `n`, this function is constant-time with respect
13    /// to `self`.
14    #[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    /// NOTE: this operation is variable time with respect to `rhs` *ONLY*.
53    ///
54    /// When used with a fixed `rhs`, this function is constant-time with respect
55    /// to `self`.
56    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    /// NOTE: this operation is variable time with respect to `rhs` *ONLY*.
65    ///
66    /// When used with a fixed `rhs`, this function is constant-time with respect
67    /// to `self`.
68    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}