Coverage Report

Created: 2026-11-12 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/crypto-bigint-0.7.10/src/limb/shr.rs
Line
Count
Source
1
//! Limb right bitshift
2
3
use crate::{Choice, CtOption, Limb, ShrVartime, WrappingShr};
4
use core::ops::{Shr, ShrAssign};
5
6
impl Limb {
7
    /// Computes `self >> shift`.
8
    ///
9
    /// # Panics
10
    /// - if `shift` overflows `Limb::BITS`.
11
    #[inline(always)]
12
    #[must_use]
13
    #[track_caller]
14
2.09M
    pub const fn shr(self, shift: u32) -> Self {
15
2.09M
        Limb(self.0 >> shift)
16
2.09M
    }
17
18
    /// Computes `self >> 1` and return the result and the carry (0 or `1 << HI_BIT`).
19
    #[inline(always)]
20
0
    pub(crate) const fn shr1(self) -> (Self, Self) {
21
0
        (Self(self.0 >> 1), Self(self.0 << Self::HI_BIT))
22
0
    }
23
24
    /// Computes `self >> shift`, returning `CtOption::none()` if the shift exceeds the capacity.
25
    #[inline(always)]
26
    #[must_use]
27
0
    pub const fn overflowing_shr(self, shift: u32) -> CtOption<Self> {
28
0
        CtOption::new(
29
0
            self.wrapping_shr(shift),
30
0
            Choice::from_u32_lt(shift, Limb::BITS),
31
        )
32
0
    }
33
34
    /// Computes `self >> shift`, returning `None` if the shift exceeds the capacity.
35
    ///
36
    /// This method is variable time in `shift` only.
37
    #[inline(always)]
38
    #[must_use]
39
0
    pub const fn overflowing_shr_vartime(self, shift: u32) -> Option<Self> {
40
0
        if shift < Limb::BITS {
41
0
            Some(self.shr(shift))
42
        } else {
43
0
            None
44
        }
45
0
    }
46
47
    /// Computes `self >> shift`, returning `Limb::ZERO` if the shift exceeds the capacity.
48
    #[inline(always)]
49
    #[must_use]
50
0
    pub const fn unbounded_shr(self, shift: u32) -> Self {
51
0
        Limb::select(
52
            Limb::ZERO,
53
0
            self.wrapping_shr(shift),
54
0
            Choice::from_u32_lt(shift, Limb::BITS),
55
        )
56
0
    }
57
58
    /// Computes `self >> shift`, returning `Limb::ZERO` if the shift exceeds the capacity.
59
    ///
60
    /// This method is variable time in `shift` only.
61
    #[inline(always)]
62
    #[must_use]
63
0
    pub const fn unbounded_shr_vartime(self, shift: u32) -> Self {
64
0
        if shift < Limb::BITS {
65
0
            self.shr(shift)
66
        } else {
67
0
            Self::ZERO
68
        }
69
0
    }
70
71
    /// Computes `self >> shift` in a panic-free manner, masking off bits of `shift`
72
    /// which would cause the shift to exceed the type's width.
73
    #[inline(always)]
74
    #[must_use]
75
0
    pub const fn wrapping_shr(self, shift: u32) -> Self {
76
0
        Limb(self.0 >> (shift & (Limb::BITS - 1)))
77
0
    }
78
}
79
80
macro_rules! impl_shr {
81
    ($($shift:ty),+) => {
82
        $(
83
            impl Shr<$shift> for Limb {
84
                type Output = Limb;
85
86
                #[inline]
87
0
                fn shr(self, shift: $shift) -> Limb {
88
0
                     Self::shr(self, u32::try_from(shift).expect("invalid shift"))
89
0
                }
Unexecuted instantiation: <crypto_bigint::limb::Limb as core::ops::bit::Shr<i32>>::shr
Unexecuted instantiation: <crypto_bigint::limb::Limb as core::ops::bit::Shr<u32>>::shr
Unexecuted instantiation: <crypto_bigint::limb::Limb as core::ops::bit::Shr<usize>>::shr
90
            }
91
92
            impl Shr<$shift> for &Limb {
93
                type Output = Limb;
94
95
                #[inline]
96
0
                fn shr(self, shift: $shift) -> Limb {
97
0
                   *self >> shift
98
0
                }
Unexecuted instantiation: <&crypto_bigint::limb::Limb as core::ops::bit::Shr<i32>>::shr
Unexecuted instantiation: <&crypto_bigint::limb::Limb as core::ops::bit::Shr<u32>>::shr
Unexecuted instantiation: <&crypto_bigint::limb::Limb as core::ops::bit::Shr<usize>>::shr
99
            }
100
101
            impl ShrAssign<$shift> for Limb {
102
                #[inline]
103
0
                fn shr_assign(&mut self, shift: $shift) {
104
0
                    *self = *self >> shift;
105
0
                }
Unexecuted instantiation: <crypto_bigint::limb::Limb as core::ops::bit::ShrAssign<i32>>::shr_assign
Unexecuted instantiation: <crypto_bigint::limb::Limb as core::ops::bit::ShrAssign<u32>>::shr_assign
Unexecuted instantiation: <crypto_bigint::limb::Limb as core::ops::bit::ShrAssign<usize>>::shr_assign
106
            }
107
        )+
108
    };
109
}
110
111
impl_shr!(i32, u32, usize);
112
113
impl ShrVartime for Limb {
114
    #[inline]
115
0
    fn overflowing_shr_vartime(&self, shift: u32) -> Option<Self> {
116
0
        (*self).overflowing_shr_vartime(shift)
117
0
    }
118
119
    #[inline]
120
0
    fn unbounded_shr_vartime(&self, shift: u32) -> Self {
121
0
        (*self).unbounded_shr_vartime(shift)
122
0
    }
123
124
    #[inline]
125
0
    fn wrapping_shr_vartime(&self, shift: u32) -> Self {
126
0
        (*self).wrapping_shr(shift)
127
0
    }
128
}
129
130
impl WrappingShr for Limb {
131
    #[inline]
132
0
    fn wrapping_shr(&self, shift: u32) -> Limb {
133
0
        (*self).wrapping_shr(shift)
134
0
    }
135
}
136
137
#[cfg(test)]
138
mod tests {
139
    use crate::{Limb, ShrVartime, WrappingShr};
140
141
    #[test]
142
    fn shr1() {
143
        assert_eq!(Limb(2) >> 1, Limb(1));
144
    }
145
146
    #[test]
147
    fn shr2() {
148
        assert_eq!(Limb(16) >> 2, Limb(4));
149
    }
150
151
    #[test]
152
    fn shr_assign1() {
153
        let mut l = Limb::ONE;
154
        l >>= 1;
155
        assert_eq!(l, Limb::ZERO);
156
    }
157
158
    #[test]
159
    fn shr_assign2() {
160
        let mut l = Limb(32);
161
        l >>= 2;
162
        assert_eq!(l, Limb(8));
163
    }
164
165
    #[test]
166
    fn overflowing_shr() {
167
        assert_eq!(
168
            Limb::from(16u8).overflowing_shr(2).into_option(),
169
            Some(Limb(4))
170
        );
171
        assert_eq!(Limb::ONE.overflowing_shr(Limb::BITS).into_option(), None);
172
        assert_eq!(
173
            ShrVartime::overflowing_shr_vartime(&Limb::from(16u8), 2),
174
            Some(Limb(4))
175
        );
176
        assert_eq!(
177
            ShrVartime::overflowing_shr_vartime(&Limb::ONE, Limb::BITS),
178
            None
179
        );
180
    }
181
182
    #[test]
183
    fn unbounded_shr() {
184
        assert_eq!(Limb::from(16u8).unbounded_shr(2), Limb(4));
185
        assert_eq!(Limb::ONE.unbounded_shr(Limb::BITS), Limb::ZERO);
186
        assert_eq!(
187
            ShrVartime::unbounded_shr_vartime(&Limb::from(16u8), 2),
188
            Limb(4)
189
        );
190
        assert_eq!(
191
            ShrVartime::unbounded_shr_vartime(&Limb::ONE, Limb::BITS),
192
            Limb::ZERO
193
        );
194
    }
195
196
    #[test]
197
    fn wrapping_shr() {
198
        assert_eq!(WrappingShr::wrapping_shr(&Limb::from(16u8), 2), Limb(4));
199
        assert_eq!(WrappingShr::wrapping_shr(&Limb::ONE, Limb::BITS), Limb::ONE);
200
        assert_eq!(
201
            ShrVartime::wrapping_shr_vartime(&Limb::from(16u8), 2),
202
            Limb(4)
203
        );
204
        assert_eq!(
205
            ShrVartime::wrapping_shr_vartime(&Limb::ONE, Limb::BITS),
206
            Limb::ONE
207
        );
208
    }
209
}