crypto_bigint/uint/boxed/
shr.rs1use crate::{BoxedUint, Choice, CtOption, Shr, ShrAssign, ShrVartime, WrappingShr};
4
5impl BoxedUint {
6 #[must_use]
11 pub fn shr(&self, shift: u32) -> BoxedUint {
12 let mut result = self.clone();
13 result.shr_assign(shift);
14 result
15 }
16
17 pub fn shr_assign(&mut self, shift: u32) {
22 self.as_mut_uint_ref().shr_assign(shift);
23 }
24
25 #[must_use]
30 pub fn overflowing_shr(&self, shift: u32) -> CtOption<Self> {
31 let mut result = self.clone();
32 let overflow = result.overflowing_shr_assign(shift);
33 CtOption::new(result, overflow.not())
34 }
35
36 #[must_use]
40 pub fn overflowing_shr_vartime(&self, shift: u32) -> Option<Self> {
41 if shift < self.bits_precision() {
42 Some(self.unbounded_shr_vartime(shift))
43 } else {
44 None
45 }
46 }
47
48 pub fn overflowing_shr_assign(&mut self, shift: u32) -> Choice {
52 self.as_mut_uint_ref().overflowing_shr_assign(shift)
53 }
54
55 pub fn overflowing_shr_assign_vartime(&mut self, shift: u32) -> bool {
64 if shift < self.bits_precision() {
65 self.as_mut_uint_ref().unbounded_shr_assign_vartime(shift);
66 false
67 } else {
68 true
69 }
70 }
71
72 #[must_use]
74 pub fn unbounded_shr(&self, shift: u32) -> Self {
75 let mut result = self.clone();
76 result.unbounded_shr_assign(shift);
77 result
78 }
79
80 pub fn unbounded_shr_assign(&mut self, shift: u32) {
82 self.as_mut_uint_ref().unbounded_shr_assign(shift);
83 }
84
85 #[must_use]
92 pub fn unbounded_shr_vartime(&self, shift: u32) -> Self {
93 let mut result = Self::zero_with_precision(self.bits_precision());
94 self.as_uint_ref()
95 .unbounded_shr_vartime(shift, result.as_mut_uint_ref());
96 result
97 }
98
99 pub fn unbounded_shr_assign_vartime(&mut self, shift: u32) {
105 self.as_mut_uint_ref().unbounded_shr_assign_vartime(shift);
106 }
107
108 #[must_use]
110 pub fn wrapping_shr(&self, shift: u32) -> Self {
111 let mut result = self.clone();
112 result.wrapping_shr_assign(shift);
113 result
114 }
115
116 pub fn wrapping_shr_assign(&mut self, shift: u32) {
118 self.as_mut_uint_ref().wrapping_shr_assign(shift);
119 }
120
121 #[must_use]
128 #[allow(clippy::integer_division_remainder_used, reason = "vartime")]
129 pub fn wrapping_shr_vartime(&self, shift: u32) -> Self {
130 self.unbounded_shr_vartime(shift % self.bits_precision())
131 }
132
133 pub fn wrapping_shr_assign_vartime(&mut self, shift: u32) {
140 self.as_mut_uint_ref().wrapping_shr_assign_vartime(shift);
141 }
142
143 #[inline(always)]
150 #[must_use]
151 pub fn shr_vartime(&self, shift: u32) -> Option<Self> {
152 self.overflowing_shr_vartime(shift)
153 }
154
155 pub(crate) fn shr1_assign(&mut self) -> Choice {
157 self.as_mut_uint_ref().shr1_assign().lsb_to_choice()
158 }
159}
160
161macro_rules! impl_shr {
162 ($($shift:ty),+) => {
163 $(
164 impl Shr<$shift> for BoxedUint {
165 type Output = BoxedUint;
166
167 #[inline]
168 fn shr(self, shift: $shift) -> BoxedUint {
169 <&Self>::shr(&self, shift)
170 }
171 }
172
173 impl Shr<$shift> for &BoxedUint {
174 type Output = BoxedUint;
175
176 #[inline]
177 fn shr(self, shift: $shift) -> BoxedUint {
178 BoxedUint::shr(self, u32::try_from(shift).expect("invalid shift"))
179 }
180 }
181
182 impl ShrAssign<$shift> for BoxedUint {
183 fn shr_assign(&mut self, shift: $shift) {
184 BoxedUint::shr_assign(self, u32::try_from(shift).expect("invalid shift"))
185 }
186 }
187 )+
188 };
189}
190
191impl_shr!(i32, u32, usize);
192
193impl WrappingShr for BoxedUint {
194 fn wrapping_shr(&self, shift: u32) -> BoxedUint {
195 self.wrapping_shr(shift)
196 }
197}
198
199impl ShrVartime for BoxedUint {
200 fn overflowing_shr_vartime(&self, shift: u32) -> Option<Self> {
201 self.overflowing_shr_vartime(shift)
202 }
203
204 fn unbounded_shr_vartime(&self, shift: u32) -> Self {
205 self.unbounded_shr_vartime(shift)
206 }
207
208 fn wrapping_shr_vartime(&self, shift: u32) -> Self {
209 self.wrapping_shr_vartime(shift)
210 }
211}
212
213#[cfg(test)]
214mod tests {
215 use super::BoxedUint;
216 use crate::{ShrVartime, WrappingShr};
217
218 #[test]
219 fn shr1_assign() {
220 let mut n = BoxedUint::from(0x3c442b21f19185fe433f0a65af902b8fu128);
221 let n_shr1 = BoxedUint::from(0x1e221590f8c8c2ff219f8532d7c815c7u128);
222 n.shr1_assign();
223 assert_eq!(n, n_shr1);
224 }
225
226 #[test]
227 fn shr() {
228 let n = BoxedUint::from(0x80000000000000000u128);
229 assert_eq!(BoxedUint::zero(), &n >> 68);
230 assert_eq!(BoxedUint::one(), &n >> 67);
231 assert_eq!(BoxedUint::from(2u8), &n >> 66);
232 assert_eq!(BoxedUint::from(4u8), &n >> 65);
233 }
234
235 #[test]
236 fn shr_vartime() {
237 let n = BoxedUint::from(0x80000000000000000u128);
238 assert_eq!(BoxedUint::zero(), n.shr_vartime(68).unwrap());
239 assert_eq!(BoxedUint::one(), n.shr_vartime(67).unwrap());
240 assert_eq!(BoxedUint::from(2u8), n.shr_vartime(66).unwrap());
241 assert_eq!(BoxedUint::from(4u8), n.shr_vartime(65).unwrap());
242 }
243
244 #[test]
245 fn overflowing_shr() {
246 assert_eq!(
247 BoxedUint::from(16u8).overflowing_shr(2).into_option(),
248 Some(BoxedUint::from(4u8))
249 );
250 assert_eq!(
251 BoxedUint::one_with_precision(192)
252 .overflowing_shr(192)
253 .into_option(),
254 None
255 );
256 assert_eq!(
257 ShrVartime::overflowing_shr_vartime(&BoxedUint::from(16u8), 2),
258 Some(BoxedUint::from(4u8))
259 );
260 assert_eq!(
261 ShrVartime::overflowing_shr_vartime(&BoxedUint::one_with_precision(192), 192),
262 None
263 );
264 let mut boxed = BoxedUint::from(16u8);
265 assert!(!boxed.overflowing_shr_assign_vartime(2));
266 assert_eq!(boxed, BoxedUint::from(4u8));
267 let mut boxed = BoxedUint::one_with_precision(192);
268 assert!(boxed.overflowing_shr_assign_vartime(192));
269 }
270
271 #[test]
272 fn unbounded_shr() {
273 assert_eq!(BoxedUint::from(16u8).unbounded_shr(2), BoxedUint::from(4u8));
274 assert_eq!(BoxedUint::max(192).unbounded_shr(192), BoxedUint::zero());
275 assert_eq!(
276 ShrVartime::unbounded_shr_vartime(&BoxedUint::from(16u8), 2),
277 BoxedUint::from(4u8)
278 );
279 assert_eq!(
280 ShrVartime::unbounded_shr_vartime(&BoxedUint::max(192), 192),
281 BoxedUint::zero()
282 );
283 }
284
285 #[test]
286 fn wrapping_shr() {
287 assert_eq!(
288 WrappingShr::wrapping_shr(&BoxedUint::from(16u8), 2),
289 BoxedUint::from(4u8)
290 );
291 assert_eq!(
292 WrappingShr::wrapping_shr(&BoxedUint::one_with_precision(192), 192),
293 BoxedUint::one()
294 );
295 assert_eq!(
296 ShrVartime::wrapping_shr_vartime(&BoxedUint::from(16u8), 2),
297 BoxedUint::from(4u8)
298 );
299 assert_eq!(
300 ShrVartime::wrapping_shr_vartime(&BoxedUint::one_with_precision(192), 192),
301 BoxedUint::one()
302 );
303 }
304}