crypto_bigint/uint/boxed/
shl.rs1use crate::{BoxedUint, Choice, CtOption, Limb, Shl, ShlAssign, ShlVartime, WrappingShl};
4
5impl BoxedUint {
6 #[must_use]
11 #[track_caller]
12 pub fn shl(&self, shift: u32) -> BoxedUint {
13 let mut result = self.clone();
14 result.shl_assign(shift);
15 result
16 }
17
18 pub fn shl_assign(&mut self, shift: u32) {
23 self.as_mut_uint_ref().shl_assign(shift);
24 }
25
26 #[must_use]
31 pub fn overflowing_shl(&self, shift: u32) -> CtOption<Self> {
32 let mut result = self.clone();
33 let overflow = result.as_mut_uint_ref().overflowing_shl_assign(shift);
34 CtOption::new(result, overflow.not())
35 }
36
37 #[must_use]
41 pub fn overflowing_shl_vartime(&self, shift: u32) -> Option<Self> {
42 if shift < self.bits_precision() {
43 Some(self.unbounded_shl_vartime(shift))
44 } else {
45 None
46 }
47 }
48
49 #[must_use]
53 pub fn overflowing_shl_assign(&mut self, shift: u32) -> Choice {
54 self.as_mut_uint_ref().overflowing_shl_assign(shift)
55 }
56
57 #[must_use]
62 pub fn overflowing_shl_assign_vartime(&mut self, shift: u32) -> bool {
63 if shift < self.bits_precision() {
64 self.as_mut_uint_ref().unbounded_shl_assign_vartime(shift);
65 false
66 } else {
67 true
68 }
69 }
70
71 #[must_use]
73 pub fn unbounded_shl(&self, shift: u32) -> Self {
74 let mut result = self.clone();
75 result.unbounded_shl_assign(shift);
76 result
77 }
78
79 pub fn unbounded_shl_assign(&mut self, shift: u32) {
81 self.as_mut_uint_ref().unbounded_shl_assign(shift);
82 }
83
84 #[must_use]
87 pub fn unbounded_shl_vartime(&self, shift: u32) -> Self {
88 let mut result = Self::zero_with_precision(self.bits_precision());
89 self.as_uint_ref()
90 .unbounded_shl_vartime(shift, result.as_mut_uint_ref());
91 result
92 }
93
94 pub fn unbounded_shl_assign_vartime(&mut self, shift: u32) {
97 self.as_mut_uint_ref().unbounded_shl_assign_vartime(shift);
98 }
99
100 #[must_use]
103 pub fn wrapping_shl(&self, shift: u32) -> Self {
104 let mut result = self.clone();
105 result.wrapping_shl_assign(shift);
106 result
107 }
108
109 pub fn wrapping_shl_assign(&mut self, shift: u32) {
112 self.as_mut_uint_ref().wrapping_shl_assign(shift);
113 }
114
115 #[must_use]
118 #[allow(clippy::integer_division_remainder_used, reason = "vartime")]
119 pub fn wrapping_shl_vartime(&self, shift: u32) -> Self {
120 self.unbounded_shl_vartime(shift % self.bits_precision())
121 }
122
123 pub fn wrapping_shl_assign_vartime(&mut self, shift: u32) {
126 self.as_mut_uint_ref().wrapping_shl_assign_vartime(shift);
127 }
128
129 #[inline(always)]
136 #[must_use]
137 pub fn shl_vartime(&self, shift: u32) -> Option<Self> {
138 self.overflowing_shl_vartime(shift)
139 }
140
141 pub(crate) fn shl1(&self) -> (Self, Limb) {
143 let mut ret = self.clone();
144 let carry = ret.as_mut_uint_ref().shl1_assign();
145 (ret, carry)
146 }
147}
148
149macro_rules! impl_shl {
150 ($($shift:ty),+) => {
151 $(
152 impl Shl<$shift> for BoxedUint {
153 type Output = BoxedUint;
154
155 #[inline]
156 fn shl(self, shift: $shift) -> BoxedUint {
157 <&Self>::shl(&self, shift)
158 }
159 }
160
161 impl Shl<$shift> for &BoxedUint {
162 type Output = BoxedUint;
163
164 #[inline]
165 fn shl(self, shift: $shift) -> BoxedUint {
166 BoxedUint::shl(self, u32::try_from(shift).expect("invalid shift"))
167 }
168 }
169
170 impl ShlAssign<$shift> for BoxedUint {
171 fn shl_assign(&mut self, shift: $shift) {
172 BoxedUint::shl_assign(self, u32::try_from(shift).expect("invalid shift"))
173 }
174 }
175 )+
176 };
177}
178
179impl_shl!(i32, u32, usize);
180
181impl WrappingShl for BoxedUint {
182 fn wrapping_shl(&self, shift: u32) -> BoxedUint {
183 self.wrapping_shl(shift)
184 }
185}
186
187impl ShlVartime for BoxedUint {
188 fn overflowing_shl_vartime(&self, shift: u32) -> Option<Self> {
189 self.overflowing_shl_vartime(shift)
190 }
191
192 fn unbounded_shl_vartime(&self, shift: u32) -> Self {
193 self.unbounded_shl_vartime(shift)
194 }
195
196 fn wrapping_shl_vartime(&self, shift: u32) -> Self {
197 self.wrapping_shl_vartime(shift)
198 }
199}
200
201#[cfg(test)]
202mod tests {
203 use super::BoxedUint;
204 use crate::{ShlVartime, WrappingShl};
205
206 #[test]
207 fn shl() {
208 let one = BoxedUint::one_with_precision(128);
209
210 assert_eq!(BoxedUint::from(2u8), &one << 1);
211 assert_eq!(BoxedUint::from(4u8), &one << 2);
212 assert_eq!(
213 BoxedUint::from(0x80000000000000000u128),
214 one.shl_vartime(67).unwrap()
215 );
216 }
217
218 #[test]
219 fn shl1_assign() {
220 let n = BoxedUint::from(0x3c442b21f19185fe433f0a65af902b8fu128);
221 let n_shl1 = BoxedUint::from(0x78885643e3230bfc867e14cb5f20571eu128);
222 assert_eq!(n.shl1().0, n_shl1);
223 }
224
225 #[test]
226 fn shl_vartime() {
227 let one = BoxedUint::one_with_precision(128);
228
229 assert_eq!(BoxedUint::from(2u8), one.shl_vartime(1).unwrap());
230 assert_eq!(BoxedUint::from(4u8), one.shl_vartime(2).unwrap());
231 assert_eq!(
232 BoxedUint::from(0x80000000000000000u128),
233 one.shl_vartime(67).unwrap()
234 );
235 }
236
237 #[test]
238 fn overflowing_shl() {
239 assert_eq!(
240 BoxedUint::one().overflowing_shl(2).into_option(),
241 Some(BoxedUint::from(4u8))
242 );
243 assert_eq!(BoxedUint::max(192).overflowing_shl(192).into_option(), None);
244 assert_eq!(
245 ShlVartime::overflowing_shl_vartime(&BoxedUint::one(), 2),
246 Some(BoxedUint::from(4u8))
247 );
248 assert_eq!(
249 ShlVartime::overflowing_shl_vartime(&BoxedUint::max(192), 192),
250 None
251 );
252 let mut boxed = BoxedUint::one();
253 assert!(!boxed.overflowing_shl_assign_vartime(2));
254 assert_eq!(boxed, BoxedUint::from(4u8));
255 let mut boxed = BoxedUint::max(192);
256 assert!(boxed.overflowing_shl_assign_vartime(192));
257 }
258
259 #[test]
260 fn unbounded_shl() {
261 assert_eq!(BoxedUint::one().unbounded_shl(2), BoxedUint::from(4u8));
262 assert_eq!(BoxedUint::max(192).unbounded_shl(192), BoxedUint::zero());
263 assert_eq!(
264 ShlVartime::unbounded_shl_vartime(&BoxedUint::one(), 2),
265 BoxedUint::from(4u8)
266 );
267 assert_eq!(
268 ShlVartime::unbounded_shl_vartime(&BoxedUint::max(192), 192),
269 BoxedUint::zero()
270 );
271 }
272
273 #[test]
274 fn wrapping_shl() {
275 assert_eq!(
276 WrappingShl::wrapping_shl(&BoxedUint::one(), 2),
277 BoxedUint::from(4u8)
278 );
279 assert_eq!(
280 WrappingShl::wrapping_shl(&BoxedUint::one_with_precision(192), 192),
281 BoxedUint::one()
282 );
283 assert_eq!(
284 ShlVartime::wrapping_shl_vartime(&BoxedUint::one(), 2),
285 BoxedUint::from(4u8)
286 );
287 assert_eq!(
288 ShlVartime::wrapping_shl_vartime(&BoxedUint::one_with_precision(192), 192),
289 BoxedUint::one()
290 );
291 }
292}