crypto_bigint/uint/boxed/
div.rs1use crate::{
4 BoxedUint, CheckedDiv, CtAssign, CtOption, Div, DivAssign, DivRemLimb, DivVartime, Integer,
5 Limb, NonZero, Reciprocal, Rem, RemAssign, RemLimb, RemMixed, ToUnsigned, UintRef, Unsigned,
6 Wrapping, bitlen,
7};
8
9impl BoxedUint {
10 #[must_use]
13 pub fn div_rem_limb_with_reciprocal(&self, reciprocal: &Reciprocal) -> (Self, Limb) {
14 let mut quo = self.clone();
15 let rem = quo
16 .as_mut_uint_ref()
17 .div_rem_limb_with_reciprocal(reciprocal);
18 (quo, rem)
19 }
20
21 #[must_use]
23 pub fn div_rem_limb(&self, rhs: NonZero<Limb>) -> (Self, Limb) {
24 let mut quo = self.clone();
25 let rem = quo.as_mut_uint_ref().div_rem_limb(rhs);
26 (quo, rem)
27 }
28
29 #[inline(always)]
31 #[must_use]
32 pub fn rem_limb_with_reciprocal(&self, reciprocal: &Reciprocal) -> Limb {
33 self.as_uint_ref()
34 .rem_limb_with_reciprocal(reciprocal, Limb::ZERO)
35 }
36
37 #[inline(always)]
39 #[must_use]
40 pub fn rem_limb(&self, rhs: NonZero<Limb>) -> Limb {
41 self.as_uint_ref().rem_limb(rhs)
42 }
43
44 #[must_use]
46 pub fn div_rem<Rhs: ToUnsigned + ?Sized>(&self, rhs: &NonZero<Rhs>) -> (Self, Rhs::Unsigned) {
47 let mut quo = self.clone();
48 let rem = quo.div_rem_assign(rhs.to_unsigned());
49 (quo, rem)
50 }
51
52 #[must_use]
54 pub fn rem<Rhs: ToUnsigned + ?Sized>(&self, rhs: &NonZero<Rhs>) -> Rhs::Unsigned {
55 self.div_rem(rhs).1
56 }
57
58 #[must_use]
60 pub(crate) fn div_rem_assign<Rhs: AsMut<UintRef>>(&mut self, rhs: NonZero<Rhs>) -> Rhs {
61 let mut rem = rhs.get();
62 self.as_mut_uint_ref().div_rem(rem.as_mut());
63 rem
64 }
65
66 #[must_use]
68 pub fn div_exact<Rhs: ToUnsigned + ?Sized>(&self, rhs: &NonZero<Rhs>) -> CtOption<Self> {
69 let mut quo = self.clone();
70 let mut div = rhs.to_unsigned().get();
71 let exact = quo.as_mut_uint_ref().div_exact(div.as_mut_uint_ref());
72 CtOption::new(quo, exact)
73 }
74
75 #[must_use]
79 pub fn div_rem_vartime<Rhs: ToUnsigned + ?Sized>(
80 &self,
81 rhs: &NonZero<Rhs>,
82 ) -> (Self, Rhs::Unsigned) {
83 let mut quo = self.clone();
84 let rem = quo.div_rem_assign_vartime(rhs.to_unsigned());
85 (quo, rem)
86 }
87
88 #[must_use]
92 pub fn rem_vartime<Rhs: ToUnsigned + ?Sized>(&self, rhs: &NonZero<Rhs>) -> Rhs::Unsigned {
93 let xc = self.limbs.len();
94 let yc = bitlen::to_limbs(rhs.as_ref().as_ref().bits_vartime());
95
96 match yc {
97 0 => unreachable!("zero divisor"),
98 1 => {
99 let rem_limb = self.as_uint_ref().rem_limb(rhs.lower_limb());
101 let mut rem = rhs.as_ref().to_unsigned_zero();
102 rem.as_mut_limbs()[0] = rem_limb;
103 rem
104 }
105 _ if yc > xc => {
106 let mut rem = rhs.as_ref().to_unsigned_zero();
107 rem.as_mut_uint_ref()
108 .leading_mut(xc)
109 .copy_from_slice(&self.limbs);
110 rem
111 }
112 _ => {
113 let mut quo = self.clone();
114 let mut rem = rhs.as_ref().to_unsigned();
115 quo.as_mut_uint_ref()
116 .leading_mut(xc)
117 .div_rem_large_vartime(rem.as_mut_uint_ref().leading_mut(yc));
118 rem
119 }
120 }
121 }
122
123 #[must_use]
127 pub(crate) fn div_rem_assign_vartime<Rhs: AsMut<UintRef>>(&mut self, rhs: NonZero<Rhs>) -> Rhs {
128 let mut rem = rhs.get();
129 self.as_mut_uint_ref().div_rem_vartime(rem.as_mut());
130 rem
131 }
132
133 #[must_use]
135 pub fn div_exact_vartime<Rhs: ToUnsigned + ?Sized>(
136 &self,
137 rhs: &NonZero<Rhs>,
138 ) -> CtOption<Self> {
139 let mut quo = self.clone();
140 let mut div = rhs.to_unsigned().get();
141 let exact = quo
142 .as_mut_uint_ref()
143 .div_exact_vartime(div.as_mut_uint_ref());
144 CtOption::new(quo, exact)
145 }
146
147 #[must_use]
155 pub fn wrapping_div<Rhs: ToUnsigned + ?Sized>(&self, rhs: &NonZero<Rhs>) -> Self {
156 self.div_rem(rhs).0
157 }
158
159 #[must_use]
164 pub fn wrapping_div_vartime<Rhs: ToUnsigned + ?Sized>(&self, rhs: &NonZero<Rhs>) -> Self {
165 self.div_rem_vartime(rhs).0
166 }
167
168 #[must_use]
171 pub fn checked_div(&self, rhs: impl AsRef<UintRef>) -> CtOption<Self> {
172 let mut quo = self.clone();
173 let rhs = rhs.as_ref();
174 let is_nz = rhs.is_nonzero();
175 let mut rem = Self::one_with_precision(rhs.bits_precision());
176 rem.as_mut_uint_ref().ct_assign(rhs, is_nz);
177 quo.as_mut_uint_ref().div_rem(rem.as_mut_uint_ref());
178 CtOption::new(quo, is_nz)
179 }
180}
181
182impl<Rhs: AsRef<UintRef>> CheckedDiv<Rhs> for BoxedUint {
183 fn checked_div(&self, rhs: &Rhs) -> CtOption<Self> {
184 self.checked_div(rhs)
185 }
186}
187
188impl<Rhs: ToUnsigned + ?Sized> Div<&NonZero<Rhs>> for &BoxedUint {
189 type Output = BoxedUint;
190
191 fn div(self, rhs: &NonZero<Rhs>) -> Self::Output {
192 self.wrapping_div(rhs)
193 }
194}
195
196impl<Rhs: ToUnsigned + ?Sized> Div<&NonZero<Rhs>> for BoxedUint {
197 type Output = BoxedUint;
198
199 fn div(mut self, rhs: &NonZero<Rhs>) -> Self::Output {
200 let _rem = self.div_rem_assign(rhs.to_unsigned());
201 self
202 }
203}
204
205impl<Rhs: AsMut<UintRef>> Div<NonZero<Rhs>> for &BoxedUint {
206 type Output = BoxedUint;
207
208 fn div(self, rhs: NonZero<Rhs>) -> Self::Output {
209 let mut quo = self.clone();
210 let _rem = quo.div_rem_assign(rhs);
211 quo
212 }
213}
214
215impl<Rhs: AsMut<UintRef>> Div<NonZero<Rhs>> for BoxedUint {
216 type Output = BoxedUint;
217
218 fn div(mut self, rhs: NonZero<Rhs>) -> Self::Output {
219 let _rem = self.div_rem_assign(rhs);
220 self
221 }
222}
223
224impl<Rhs: ToUnsigned + ?Sized> DivAssign<&NonZero<Rhs>> for BoxedUint {
225 fn div_assign(&mut self, rhs: &NonZero<Rhs>) {
226 let _rem = self.div_rem_assign(rhs.to_unsigned());
227 }
228}
229
230impl<Rhs: AsMut<UintRef>> DivAssign<NonZero<Rhs>> for BoxedUint {
231 fn div_assign(&mut self, rhs: NonZero<Rhs>) {
232 let _rem = self.div_rem_assign(rhs);
233 }
234}
235
236impl DivVartime for BoxedUint {
237 fn div_vartime(&self, rhs: &NonZero<BoxedUint>) -> Self {
238 self.wrapping_div_vartime(rhs)
239 }
240}
241
242impl<Rhs: AsMut<UintRef>> Div<NonZero<Rhs>> for Wrapping<BoxedUint> {
243 type Output = Wrapping<BoxedUint>;
244
245 fn div(self, rhs: NonZero<Rhs>) -> Self::Output {
246 Wrapping(self.0 / rhs)
247 }
248}
249
250impl<Rhs: AsMut<UintRef>> Div<NonZero<Rhs>> for &Wrapping<BoxedUint> {
251 type Output = Wrapping<BoxedUint>;
252
253 fn div(self, rhs: NonZero<Rhs>) -> Self::Output {
254 Wrapping(&self.0 / rhs)
255 }
256}
257
258impl<Rhs: ToUnsigned + ?Sized> Div<&NonZero<Rhs>> for &Wrapping<BoxedUint> {
259 type Output = Wrapping<BoxedUint>;
260
261 fn div(self, rhs: &NonZero<Rhs>) -> Self::Output {
262 Wrapping(&self.0 / rhs)
263 }
264}
265
266impl<Rhs: ToUnsigned + ?Sized> Div<&NonZero<Rhs>> for Wrapping<BoxedUint> {
267 type Output = Wrapping<BoxedUint>;
268
269 fn div(self, rhs: &NonZero<Rhs>) -> Self::Output {
270 Wrapping(self.0 / rhs)
271 }
272}
273
274impl<Rhs: ToUnsigned + ?Sized> DivAssign<&NonZero<Rhs>> for Wrapping<BoxedUint> {
275 fn div_assign(&mut self, rhs: &NonZero<Rhs>) {
276 self.0 /= rhs;
277 }
278}
279
280impl<Rhs: AsMut<UintRef>> DivAssign<NonZero<Rhs>> for Wrapping<BoxedUint> {
281 fn div_assign(&mut self, rhs: NonZero<Rhs>) {
282 self.0 /= rhs;
283 }
284}
285
286impl<Rhs: ToUnsigned + ?Sized> Rem<&NonZero<Rhs>> for &BoxedUint {
287 type Output = Rhs::Unsigned;
288
289 #[inline]
290 fn rem(self, rhs: &NonZero<Rhs>) -> Self::Output {
291 self.rem(rhs)
292 }
293}
294
295impl<Rhs: ToUnsigned + ?Sized> Rem<&NonZero<Rhs>> for BoxedUint {
296 type Output = Rhs::Unsigned;
297
298 #[inline]
299 fn rem(self, rhs: &NonZero<Rhs>) -> Self::Output {
300 Self::rem(&self, rhs)
301 }
302}
303
304impl<Rhs: AsMut<UintRef>> Rem<NonZero<Rhs>> for &BoxedUint {
305 type Output = Rhs;
306
307 #[inline]
308 fn rem(self, rhs: NonZero<Rhs>) -> Self::Output {
309 self.clone().div_rem_assign(rhs)
310 }
311}
312
313impl<Rhs: AsMut<UintRef>> Rem<NonZero<Rhs>> for BoxedUint {
314 type Output = Rhs;
315
316 #[inline]
317 fn rem(mut self, rhs: NonZero<Rhs>) -> Self::Output {
318 self.div_rem_assign(rhs)
319 }
320}
321
322impl<Rhs: AsRef<UintRef> + ?Sized> RemAssign<&NonZero<Rhs>> for BoxedUint {
323 fn rem_assign(&mut self, rhs: &NonZero<Rhs>) {
324 *self = self.div_rem_assign(rhs.to_boxed());
325 }
326}
327
328impl<Rhs: AsRef<UintRef>> RemAssign<NonZero<Rhs>> for BoxedUint {
329 fn rem_assign(&mut self, rhs: NonZero<Rhs>) {
330 *self = self.div_rem_assign(rhs.to_boxed());
331 }
332}
333
334impl DivRemLimb for BoxedUint {
335 fn div_rem_limb_with_reciprocal(&self, reciprocal: &Reciprocal) -> (Self, Limb) {
336 Self::div_rem_limb_with_reciprocal(self, reciprocal)
337 }
338}
339
340impl RemLimb for BoxedUint {
341 fn rem_limb_with_reciprocal(&self, reciprocal: &Reciprocal) -> Limb {
342 Self::rem_limb_with_reciprocal(self, reciprocal)
343 }
344}
345
346impl<Rhs: Unsigned> RemMixed<Rhs> for BoxedUint {
347 fn rem_mixed(&self, reductor: &NonZero<Rhs>) -> Rhs {
348 Self::div_rem(self, reductor).1
349 }
350}
351
352#[cfg(test)]
353mod tests {
354 use super::{BoxedUint, Limb, NonZero};
355 use crate::{CtAssign, DivVartime, One, Resize, UintRef, Wrapping, Zero};
356
357 #[test]
358 fn div_trait() {
359 let n = BoxedUint::from(0xFFEECCBBAA99887766u128);
360 let p = NonZero::new(BoxedUint::from(997u128)).unwrap();
361 let res = BoxedUint::from(0x41b74857375c0f86u64);
362 assert_eq!(&n / &p, res);
363 assert_eq!(&n / p.clone(), res);
364 assert_eq!(n.clone() / &p, res);
365 assert_eq!(n / p, res);
366 }
367
368 #[test]
369 fn rem_trait() {
370 let n = BoxedUint::from(0xFFEECCBBAA99887766u128);
371 let p = NonZero::new(BoxedUint::from(997u128)).unwrap();
372 let res = BoxedUint::from(648u128);
373 assert_eq!(&n % &p, res);
374 assert_eq!(&n % p.clone(), res);
375 assert_eq!(n.clone() % &p, res);
376 assert_eq!(n % p, res);
377 }
378
379 #[test]
380 fn div_rem_larger_denominator() {
381 let x = BoxedUint::from_be_hex("8000000000000000", 64).unwrap();
383 let y = BoxedUint::from_be_hex("00000000000000010000000000000000", 128)
384 .unwrap()
385 .to_nz()
386 .unwrap();
387 let (quo, rem) = x.div_rem(&y);
388 assert_eq!(quo, BoxedUint::zero_with_precision(64));
389 assert_eq!(rem, x.resize_unchecked(128));
390
391 let x = BoxedUint::from_be_hex("8000000000000000", 64).unwrap();
393 let y = BoxedUint::from_be_hex("00000000000000000000000000001000", 128)
394 .unwrap()
395 .to_nz()
396 .unwrap();
397 let (quo, rem) = x.div_rem(&y);
398 assert_eq!(quo, BoxedUint::from_be_hex("0008000000000000", 64).unwrap());
399 assert_eq!(rem, BoxedUint::zero_with_precision(128));
400
401 let x = BoxedUint::from_be_hex("80000000000000008000000000000000", 128).unwrap();
403 let y = BoxedUint::from_be_hex(
404 "0000000000000001000000000000000000000000000000010000000000000000",
405 256,
406 )
407 .unwrap()
408 .to_nz()
409 .unwrap();
410 let (quo, rem) = x.div_rem(&y);
411 assert_eq!(quo, BoxedUint::zero_with_precision(128));
412 assert_eq!(rem, x.resize_unchecked(256));
413
414 let x = BoxedUint::from_be_hex("80000000000000008000000000000000", 128).unwrap();
416 let y = BoxedUint::from_be_hex(
417 "0000000000000000000000000000000000000000000000000000000000110000",
418 256,
419 )
420 .unwrap()
421 .to_nz()
422 .unwrap();
423 let (quo, rem) = x.div_rem(&y);
424 assert_eq!(
425 quo,
426 BoxedUint::from_be_hex("000007878787878787878f0f0f0f0f0f", 128).unwrap()
427 );
428 assert_eq!(
429 rem,
430 BoxedUint::from_be_hex(
431 "0000000000000000000000000000000000000000000000000000000000010000",
432 256
433 )
434 .unwrap()
435 );
436 }
437
438 #[test]
439 fn rem_vartime() {
440 let n = BoxedUint::from(0xFFEECCBBAA99887766u128);
441 let p = NonZero::new(BoxedUint::from(997u128)).unwrap();
442 assert_eq!(BoxedUint::from(648u128), n.rem_vartime(&p));
443 }
444
445 #[test]
446 fn rem_limb() {
447 let n = BoxedUint::from(0xFFEECCBBAA99887766u128);
448 let pl = NonZero::new(Limb(997)).unwrap();
449 let p = NonZero::new(BoxedUint::from(997u128)).unwrap();
450 assert_eq!(n.rem(&p).limbs[0], n.rem_limb(pl));
451 }
452
453 #[test]
454 fn div_vartime_through_trait() {
455 struct A<T> {
456 x: T,
457 y: T,
458 }
459 impl<T: DivVartime + Clone + Zero + One + CtAssign> A<T> {
460 fn divide_x_by_y(&self) -> T {
461 let rhs = &NonZero::new(self.y.clone()).unwrap();
462 self.x.div_vartime(rhs)
463 }
464 }
465
466 let a = A {
467 x: BoxedUint::from(1234567890u64),
468 y: BoxedUint::from(456u64),
469 };
470 assert_eq!(a.divide_x_by_y(), BoxedUint::from(2707385u64));
471 }
472
473 #[test]
474 fn div_uintref() {
475 let a = BoxedUint::from(1234567890u64);
476 let b = UintRef::new(&[Limb(456), Limb(0)])
477 .as_nz_vartime()
478 .expect("ensured non-zero");
479 assert_eq!(&a / b, BoxedUint::from(2707385u64));
480 assert_eq!(
481 a.checked_div(b.as_ref()).into_option(),
482 Some(BoxedUint::from(2707385u64))
483 );
484 }
485
486 #[test]
487 fn wrapping_div() {
488 let a = Wrapping(BoxedUint::from(1234567890u64));
489 let b = NonZero::new(BoxedUint::from(456u64)).expect("ensured non-zero");
490 let res = Wrapping(BoxedUint::from(2707385u64));
491 assert_eq!(&a / &b, res);
492 assert_eq!(&a / b.clone(), res);
493 assert_eq!(a.clone() / &b, res);
494 assert_eq!(a.clone() / b.clone(), res);
495
496 let mut c = a.clone();
497 c /= &b;
498 assert_eq!(c, res);
499 let mut c = a.clone();
500 c /= b;
501 assert_eq!(c, res);
502 }
503}