crypto_bigint/limb/
shr.rs1use crate::{Choice, CtOption, Limb, ShrVartime, WrappingShr};
4use core::ops::{Shr, ShrAssign};
5
6impl Limb {
7 #[inline(always)]
12 #[must_use]
13 #[track_caller]
14 pub const fn shr(self, shift: u32) -> Self {
15 Limb(self.0 >> shift)
16 }
17
18 #[inline(always)]
20 pub(crate) const fn shr1(self) -> (Self, Self) {
21 (Self(self.0 >> 1), Self(self.0 << Self::HI_BIT))
22 }
23
24 #[inline(always)]
26 #[must_use]
27 pub const fn overflowing_shr(self, shift: u32) -> CtOption<Self> {
28 CtOption::new(
29 self.wrapping_shr(shift),
30 Choice::from_u32_lt(shift, Limb::BITS),
31 )
32 }
33
34 #[inline(always)]
38 #[must_use]
39 pub const fn overflowing_shr_vartime(self, shift: u32) -> Option<Self> {
40 if shift < Limb::BITS {
41 Some(self.shr(shift))
42 } else {
43 None
44 }
45 }
46
47 #[inline(always)]
49 #[must_use]
50 pub const fn unbounded_shr(self, shift: u32) -> Self {
51 Limb::select(
52 Limb::ZERO,
53 self.wrapping_shr(shift),
54 Choice::from_u32_lt(shift, Limb::BITS),
55 )
56 }
57
58 #[inline(always)]
62 #[must_use]
63 pub const fn unbounded_shr_vartime(self, shift: u32) -> Self {
64 if shift < Limb::BITS {
65 self.shr(shift)
66 } else {
67 Self::ZERO
68 }
69 }
70
71 #[inline(always)]
74 #[must_use]
75 pub const fn wrapping_shr(self, shift: u32) -> Self {
76 Limb(self.0 >> (shift & (Limb::BITS - 1)))
77 }
78}
79
80macro_rules! impl_shr {
81 ($($shift:ty),+) => {
82 $(
83 impl Shr<$shift> for Limb {
84 type Output = Limb;
85
86 #[inline]
87 fn shr(self, shift: $shift) -> Limb {
88 Self::shr(self, u32::try_from(shift).expect("invalid shift"))
89 }
90 }
91
92 impl Shr<$shift> for &Limb {
93 type Output = Limb;
94
95 #[inline]
96 fn shr(self, shift: $shift) -> Limb {
97 *self >> shift
98 }
99 }
100
101 impl ShrAssign<$shift> for Limb {
102 #[inline]
103 fn shr_assign(&mut self, shift: $shift) {
104 *self = *self >> shift;
105 }
106 }
107 )+
108 };
109}
110
111impl_shr!(i32, u32, usize);
112
113impl ShrVartime for Limb {
114 #[inline]
115 fn overflowing_shr_vartime(&self, shift: u32) -> Option<Self> {
116 (*self).overflowing_shr_vartime(shift)
117 }
118
119 #[inline]
120 fn unbounded_shr_vartime(&self, shift: u32) -> Self {
121 (*self).unbounded_shr_vartime(shift)
122 }
123
124 #[inline]
125 fn wrapping_shr_vartime(&self, shift: u32) -> Self {
126 (*self).wrapping_shr(shift)
127 }
128}
129
130impl WrappingShr for Limb {
131 #[inline]
132 fn wrapping_shr(&self, shift: u32) -> Limb {
133 (*self).wrapping_shr(shift)
134 }
135}
136
137#[cfg(test)]
138mod 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}