1use super::div_limb::Reciprocal;
4use crate::{
5 CheckedDiv, CtOption, Div, DivAssign, DivRemLimb, DivVartime, Limb, NonZero, Rem, RemAssign,
6 RemLimb, RemMixed, ToUnsigned, Uint, UintRef, Unsigned, Wrapping,
7};
8
9impl<const LIMBS: usize> Uint<LIMBS> {
10 #[must_use]
13 pub const fn div_rem_limb_with_reciprocal(&self, reciprocal: &Reciprocal) -> (Self, Limb) {
14 let mut quo = *self;
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 const fn div_rem_limb(&self, rhs: NonZero<Limb>) -> (Self, Limb) {
24 let mut quo = *self;
25 let rem = quo.as_mut_uint_ref().div_rem_limb(rhs);
26 (quo, rem)
27 }
28
29 #[must_use]
31 pub const fn rem_limb_with_reciprocal(&self, reciprocal: &Reciprocal) -> Limb {
32 self.as_uint_ref()
33 .rem_limb_with_reciprocal(reciprocal, Limb::ZERO)
34 }
35
36 #[must_use]
38 pub const fn rem_limb(&self, rhs: NonZero<Limb>) -> Limb {
39 self.as_uint_ref().rem_limb(rhs)
40 }
41
42 #[must_use]
46 pub const fn div_rem<const RHS_LIMBS: usize>(
47 &self,
48 rhs: &NonZero<Uint<RHS_LIMBS>>,
49 ) -> (Self, Uint<RHS_LIMBS>) {
50 let (mut x, mut y) = (*self, *rhs.as_ref());
51 UintRef::div_rem(x.as_mut_uint_ref(), y.as_mut_uint_ref());
52 (x, y)
53 }
54
55 #[inline]
62 #[must_use]
63 pub const fn div_rem_vartime<const RHS_LIMBS: usize>(
64 &self,
65 rhs: &NonZero<Uint<RHS_LIMBS>>,
66 ) -> (Self, Uint<RHS_LIMBS>) {
67 let (mut x, mut y) = (*self, *rhs.as_ref());
68 UintRef::div_rem_vartime(x.as_mut_uint_ref(), y.as_mut_uint_ref());
69 (x, y)
70 }
71
72 #[must_use]
74 pub const fn div_exact<const RHS_LIMBS: usize>(
75 &self,
76 rhs: &NonZero<Uint<RHS_LIMBS>>,
77 ) -> CtOption<Self> {
78 let mut quo = *self;
79 let mut div = rhs.get_copy();
80 let exact = quo.as_mut_uint_ref().div_exact(div.as_mut_uint_ref());
81 CtOption::new(quo, exact)
82 }
83
84 #[must_use]
90 pub const fn div_exact_vartime<const RHS_LIMBS: usize>(
91 &self,
92 rhs: &NonZero<Uint<RHS_LIMBS>>,
93 ) -> CtOption<Self> {
94 let mut quo = *self;
95 let mut div = rhs.get_copy();
96 let exact = quo
97 .as_mut_uint_ref()
98 .div_exact_vartime(div.as_mut_uint_ref());
99 CtOption::new(quo, exact)
100 }
101
102 #[must_use]
104 pub(crate) fn div_rem_assign<Rhs: Unsigned>(&mut self, rhs: NonZero<Rhs>) -> Rhs {
105 let mut rem = rhs.get();
106 self.as_mut_uint_ref().div_rem(rem.as_mut_uint_ref());
107 rem
108 }
109
110 #[must_use]
112 pub const fn rem<const RHS_LIMBS: usize>(
113 &self,
114 rhs: &NonZero<Uint<RHS_LIMBS>>,
115 ) -> Uint<RHS_LIMBS> {
116 let (mut x, mut y) = (*self, *rhs.as_ref());
117 UintRef::div_rem(x.as_mut_uint_ref(), y.as_mut_uint_ref());
118 y
119 }
120
121 #[inline]
126 #[must_use]
127 pub const fn rem_vartime<const RHS_LIMBS: usize>(
128 &self,
129 rhs: &NonZero<Uint<RHS_LIMBS>>,
130 ) -> Uint<RHS_LIMBS> {
131 let (mut x, mut y) = (*self, *rhs.as_ref());
132 UintRef::div_rem_vartime(x.as_mut_uint_ref(), y.as_mut_uint_ref());
133 y
134 }
135
136 #[inline]
138 #[must_use]
139 pub const fn rem_wide(mut lower_upper: (Self, Self), rhs: &NonZero<Self>) -> Self {
140 let mut y = *rhs.as_ref();
141 UintRef::rem_wide(
142 (
143 lower_upper.0.as_mut_uint_ref(),
144 lower_upper.1.as_mut_uint_ref(),
145 ),
146 y.as_mut_uint_ref(),
147 );
148 y
149 }
150
151 #[inline]
158 #[must_use]
159 pub const fn rem_wide_vartime(mut lower_upper: (Self, Self), rhs: &NonZero<Self>) -> Self {
160 let mut y = *rhs.as_ref();
161 UintRef::rem_wide_vartime(
162 (
163 lower_upper.0.as_mut_uint_ref(),
164 lower_upper.1.as_mut_uint_ref(),
165 ),
166 y.as_mut_uint_ref(),
167 );
168 y
169 }
170
171 #[must_use]
186 pub const fn rem2k_vartime(&self, k: u32) -> Self {
187 self.restrict_bits(k)
188 }
189
190 #[must_use]
195 pub const fn wrapping_div(&self, rhs: &NonZero<Self>) -> Self {
196 self.div_rem(rhs).0
197 }
198
199 #[must_use]
204 pub const fn wrapping_div_vartime<const RHS: usize>(&self, rhs: &NonZero<Uint<RHS>>) -> Self {
205 self.div_rem_vartime(rhs).0
206 }
207
208 #[must_use]
227 pub fn checked_div<const RHS_LIMBS: usize>(&self, rhs: &Uint<RHS_LIMBS>) -> CtOption<Self> {
228 NonZero::new(*rhs).map(|rhs| self.div_rem(&rhs).0)
229 }
230
231 #[must_use]
247 pub const fn wrapping_rem_vartime(&self, rhs: &Self) -> Self {
248 let nz_rhs = rhs.to_nz().expect_copied("non-zero divisor");
249 self.rem_vartime(&nz_rhs)
250 }
251
252 #[must_use]
271 pub fn checked_rem<const RHS_LIMBS: usize>(
272 &self,
273 rhs: &Uint<RHS_LIMBS>,
274 ) -> CtOption<Uint<RHS_LIMBS>> {
275 NonZero::new(*rhs).map(|rhs| self.rem(&rhs))
276 }
277}
278
279impl<const LIMBS: usize, const RHS_LIMBS: usize> CheckedDiv<Uint<RHS_LIMBS>> for Uint<LIMBS> {
280 fn checked_div(&self, rhs: &Uint<RHS_LIMBS>) -> CtOption<Self> {
281 self.checked_div(rhs)
282 }
283}
284
285impl<const LIMBS: usize, Rhs: Unsigned> Div<Rhs> for &Uint<LIMBS> {
286 type Output = Uint<LIMBS>;
287
288 #[inline]
289 fn div(self, rhs: Rhs) -> Self::Output {
290 *self / rhs
291 }
292}
293
294impl<const LIMBS: usize, Rhs: Unsigned> Div<Rhs> for Uint<LIMBS> {
295 type Output = Uint<LIMBS>;
296
297 #[inline]
298 fn div(self, rhs: Rhs) -> Self::Output {
299 self / NonZero::new(rhs).expect("attempt to divide with a divisor of zero")
300 }
301}
302
303impl<const LIMBS: usize, Rhs: ToUnsigned + ?Sized> Div<&NonZero<Rhs>> for &Uint<LIMBS> {
304 type Output = Uint<LIMBS>;
305
306 fn div(self, rhs: &NonZero<Rhs>) -> Self::Output {
307 let mut quo = *self;
308 let _rem = quo.div_rem_assign(rhs.to_unsigned());
309 quo
310 }
311}
312
313impl<const LIMBS: usize, Rhs: ToUnsigned + ?Sized> Div<&NonZero<Rhs>> for Uint<LIMBS> {
314 type Output = Self;
315
316 fn div(mut self, rhs: &NonZero<Rhs>) -> Self::Output {
317 let _rem = self.div_rem_assign(rhs.to_unsigned());
318 self
319 }
320}
321
322impl<const LIMBS: usize, Rhs: Unsigned> Div<NonZero<Rhs>> for &Uint<LIMBS> {
323 type Output = Uint<LIMBS>;
324
325 fn div(self, rhs: NonZero<Rhs>) -> Self::Output {
326 let mut quo = *self;
327 let _rem = quo.div_rem_assign(rhs);
328 quo
329 }
330}
331
332impl<const LIMBS: usize, Rhs: Unsigned> Div<NonZero<Rhs>> for Uint<LIMBS> {
333 type Output = Self;
334
335 fn div(mut self, rhs: NonZero<Rhs>) -> Self::Output {
336 let _rem = self.div_rem_assign(rhs);
337 self
338 }
339}
340
341impl<const LIMBS: usize, Rhs: ToUnsigned + ?Sized> DivAssign<&NonZero<Rhs>> for Uint<LIMBS> {
342 fn div_assign(&mut self, rhs: &NonZero<Rhs>) {
343 let _rem = self.div_rem_assign(rhs.to_unsigned());
344 }
345}
346
347impl<const LIMBS: usize, Rhs: Unsigned> DivAssign<NonZero<Rhs>> for Uint<LIMBS> {
348 fn div_assign(&mut self, rhs: NonZero<Rhs>) {
349 let _rem = self.div_rem_assign(rhs);
350 }
351}
352
353impl<const LIMBS: usize, Rhs: Unsigned> Div<NonZero<Rhs>> for Wrapping<Uint<LIMBS>> {
354 type Output = Self;
355
356 fn div(self, rhs: NonZero<Rhs>) -> Self::Output {
357 Wrapping(self.0 / rhs)
358 }
359}
360
361impl<const LIMBS: usize, Rhs: Unsigned> Div<NonZero<Rhs>> for &Wrapping<Uint<LIMBS>> {
362 type Output = Wrapping<Uint<LIMBS>>;
363
364 fn div(self, rhs: NonZero<Rhs>) -> Self::Output {
365 Wrapping(self.0 / rhs)
366 }
367}
368
369impl<const LIMBS: usize, Rhs: ToUnsigned + ?Sized> Div<&NonZero<Rhs>> for &Wrapping<Uint<LIMBS>> {
370 type Output = Wrapping<Uint<LIMBS>>;
371
372 fn div(self, rhs: &NonZero<Rhs>) -> Self::Output {
373 Wrapping(self.0 / rhs)
374 }
375}
376
377impl<const LIMBS: usize, Rhs: ToUnsigned + ?Sized> Div<&NonZero<Rhs>> for Wrapping<Uint<LIMBS>> {
378 type Output = Self;
379
380 fn div(self, rhs: &NonZero<Rhs>) -> Self::Output {
381 Wrapping(self.0 / rhs)
382 }
383}
384
385impl<const LIMBS: usize, Rhs: ToUnsigned + ?Sized> DivAssign<&NonZero<Rhs>>
386 for Wrapping<Uint<LIMBS>>
387{
388 fn div_assign(&mut self, rhs: &NonZero<Rhs>) {
389 self.0 /= rhs;
390 }
391}
392
393impl<const LIMBS: usize, Rhs: Unsigned> DivAssign<NonZero<Rhs>> for Wrapping<Uint<LIMBS>> {
394 fn div_assign(&mut self, rhs: NonZero<Rhs>) {
395 self.0 /= rhs;
396 }
397}
398
399impl<const LIMBS: usize> DivVartime for Uint<LIMBS> {
400 fn div_vartime(&self, rhs: &NonZero<Uint<LIMBS>>) -> Self {
401 self.div_rem_vartime(rhs).0
402 }
403}
404
405impl<const LIMBS: usize, Rhs: Unsigned> Rem<Rhs> for &Uint<LIMBS> {
406 type Output = Rhs;
407
408 #[inline]
409 fn rem(self, rhs: Rhs) -> Self::Output {
410 *self % rhs
411 }
412}
413
414impl<const LIMBS: usize, Rhs: Unsigned> Rem<Rhs> for Uint<LIMBS> {
415 type Output = Rhs;
416
417 #[inline]
418 fn rem(self, rhs: Rhs) -> Self::Output {
419 self % NonZero::new(rhs).expect("attempt to calculate the remainder with a divisor of zero")
420 }
421}
422
423impl<const LIMBS: usize, Rhs: ToUnsigned + ?Sized> Rem<&NonZero<Rhs>> for &Uint<LIMBS> {
424 type Output = Rhs::Unsigned;
425
426 #[inline]
427 fn rem(self, rhs: &NonZero<Rhs>) -> Self::Output {
428 (*self).rem(rhs)
429 }
430}
431
432impl<const LIMBS: usize, Rhs: ToUnsigned + ?Sized> Rem<&NonZero<Rhs>> for Uint<LIMBS> {
433 type Output = Rhs::Unsigned;
434
435 #[inline]
436 fn rem(mut self, rhs: &NonZero<Rhs>) -> Self::Output {
437 self.div_rem_assign(rhs.to_unsigned())
438 }
439}
440
441impl<const LIMBS: usize, Rhs: Unsigned> Rem<NonZero<Rhs>> for &Uint<LIMBS> {
442 type Output = Rhs;
443
444 #[inline]
445 fn rem(self, rhs: NonZero<Rhs>) -> Self::Output {
446 (*self).rem(rhs)
447 }
448}
449
450impl<const LIMBS: usize, Rhs: Unsigned> Rem<NonZero<Rhs>> for Uint<LIMBS> {
451 type Output = Rhs;
452
453 #[inline]
454 fn rem(mut self, rhs: NonZero<Rhs>) -> Self::Output {
455 self.div_rem_assign(rhs)
456 }
457}
458
459impl<const LIMBS: usize, Rhs: Unsigned> Rem<NonZero<Rhs>> for Wrapping<Uint<LIMBS>> {
460 type Output = Wrapping<Rhs>;
461
462 fn rem(self, rhs: NonZero<Rhs>) -> Self::Output {
463 Wrapping(self.0 % rhs)
464 }
465}
466
467impl<const LIMBS: usize, Rhs: Unsigned> Rem<NonZero<Rhs>> for &Wrapping<Uint<LIMBS>> {
468 type Output = Wrapping<Rhs>;
469
470 fn rem(self, rhs: NonZero<Rhs>) -> Self::Output {
471 *self % rhs
472 }
473}
474
475impl<const LIMBS: usize, Rhs: ToUnsigned + ?Sized> Rem<&NonZero<Rhs>> for &Wrapping<Uint<LIMBS>> {
476 type Output = Wrapping<Rhs::Unsigned>;
477
478 fn rem(self, rhs: &NonZero<Rhs>) -> Self::Output {
479 *self % rhs.to_unsigned()
480 }
481}
482
483impl<const LIMBS: usize, Rhs: ToUnsigned + ?Sized> Rem<&NonZero<Rhs>> for Wrapping<Uint<LIMBS>> {
484 type Output = Wrapping<Rhs::Unsigned>;
485
486 fn rem(self, rhs: &NonZero<Rhs>) -> Self::Output {
487 self % rhs.to_unsigned()
488 }
489}
490
491impl<const LIMBS: usize, Rhs: Unsigned> RemAssign<NonZero<Rhs>> for Uint<LIMBS> {
492 fn rem_assign(&mut self, rhs: NonZero<Rhs>) {
493 let rem = *self % rhs;
494 *self = rem.as_uint_ref().to_uint_resize();
495 }
496}
497
498impl<const LIMBS: usize, Rhs: ToUnsigned + ?Sized> RemAssign<&NonZero<Rhs>> for Uint<LIMBS> {
499 fn rem_assign(&mut self, rhs: &NonZero<Rhs>) {
500 *self %= rhs.to_unsigned();
501 }
502}
503
504impl<const LIMBS: usize, Rhs: Unsigned> RemAssign<NonZero<Rhs>> for Wrapping<Uint<LIMBS>> {
505 fn rem_assign(&mut self, rhs: NonZero<Rhs>) {
506 *self %= &rhs;
507 }
508}
509
510impl<const LIMBS: usize, Rhs: ToUnsigned + ?Sized> RemAssign<&NonZero<Rhs>>
511 for Wrapping<Uint<LIMBS>>
512{
513 fn rem_assign(&mut self, rhs: &NonZero<Rhs>) {
514 self.0 %= rhs;
515 }
516}
517
518impl<const LIMBS: usize> DivRemLimb for Uint<LIMBS> {
519 fn div_rem_limb_with_reciprocal(&self, reciprocal: &Reciprocal) -> (Self, Limb) {
520 Self::div_rem_limb_with_reciprocal(self, reciprocal)
521 }
522}
523
524impl<const LIMBS: usize> RemLimb for Uint<LIMBS> {
525 fn rem_limb_with_reciprocal(&self, reciprocal: &Reciprocal) -> Limb {
526 Self::rem_limb_with_reciprocal(self, reciprocal)
527 }
528}
529
530impl<const LIMBS: usize, Rhs: Unsigned> RemMixed<Rhs> for Uint<LIMBS> {
531 fn rem_mixed(&self, reductor: &NonZero<Rhs>) -> Rhs {
532 let (mut quo, mut rem) = (*self, reductor.as_ref().clone());
533 quo.as_mut_uint_ref().div_rem(rem.as_mut_uint_ref());
534 rem
535 }
536}
537
538#[cfg(test)]
539#[allow(clippy::integer_division_remainder_used, reason = "test")]
540mod tests {
541 use crate::{
542 CtAssign, DivVartime, Limb, NonZero, One, RemMixed, U64, U128, U256, U512, U896, U1024,
543 Uint, Word, Wrapping, Zero,
544 };
545
546 #[cfg(feature = "rand_core")]
547 use {crate::Random, chacha20::ChaCha8Rng, rand_core::Rng, rand_core::SeedableRng};
548
549 #[test]
550 fn div_word() {
551 for (n, d, e, ee) in &[
552 (200u64, 2u64, 100u64, 0),
553 (100u64, 25u64, 4u64, 0),
554 (100u64, 10u64, 10u64, 0),
555 (1024u64, 8u64, 128u64, 0),
556 (27u64, 13u64, 2u64, 1u64),
557 (26u64, 13u64, 2u64, 0u64),
558 (14u64, 13u64, 1u64, 1u64),
559 (13u64, 13u64, 1u64, 0u64),
560 (12u64, 13u64, 0u64, 12u64),
561 (1u64, 13u64, 0u64, 1u64),
562 ] {
563 let lhs = U256::from(*n);
564 let rhs = NonZero::new(U256::from(*d)).unwrap();
565 let (q, r) = lhs.div_rem(&rhs);
566 assert_eq!(U256::from(*e), q);
567 assert_eq!(U256::from(*ee), r);
568 let (q, r) = lhs.div_rem_vartime(&rhs);
569 assert_eq!(U256::from(*e), q);
570 assert_eq!(U256::from(*ee), r);
571 let q = lhs.div_exact(&rhs).into_option();
572 assert_eq!(if *ee == 0 { Some(U256::from(*e)) } else { None }, q);
573 let q = lhs.div_exact_vartime(&rhs).into_option();
574 assert_eq!(if *ee == 0 { Some(U256::from(*e)) } else { None }, q);
575 }
576 }
577
578 #[cfg(feature = "rand_core")]
579 #[test]
580 fn div() {
581 let mut rng = ChaCha8Rng::from_seed([7u8; 32]);
582 for _ in 0..25 {
583 let num = U256::random_from_rng(&mut rng)
584 .overflowing_shr_vartime(128)
585 .unwrap();
586 let den = NonZero::new(
587 U256::random_from_rng(&mut rng)
588 .overflowing_shr_vartime(128)
589 .unwrap(),
590 )
591 .unwrap();
592 let n = num.checked_mul(den.as_ref());
593 if n.is_some().into() {
594 let n = n.unwrap();
595 let (q, _) = n.div_rem(&den);
596 assert_eq!(q, num);
597 let (q, _) = n.div_rem_vartime(&den);
598 assert_eq!(q, num);
599 let q = n.div_exact(&den).into_option();
600 assert_eq!(q, Some(num));
601 let q = n.div_exact_vartime(&den).into_option();
602 assert_eq!(q, Some(num));
603 }
604 }
605 }
606
607 #[test]
608 fn div_max() {
609 let mut a = U256::ZERO;
610 let mut b = U256::ZERO;
611 b.limbs[b.limbs.len() - 1] = Limb(Word::MAX);
612 let q = a.wrapping_div(&NonZero::new(b).unwrap());
613 assert_eq!(q, Uint::ZERO);
614 a.limbs[a.limbs.len() - 1] = Limb(1 << (Limb::HI_BIT - 7));
615 b.limbs[b.limbs.len() - 1] = Limb(0x82 << (Limb::HI_BIT - 7));
616 let b = NonZero::new(b).unwrap();
617 let q = a.wrapping_div(&b);
618 assert_eq!(q, Uint::ZERO);
619 }
620
621 #[test]
622 fn div_one() {
623 let (q, r) = U256::from(10u8).div_rem(&NonZero::new(U256::ONE).unwrap());
624 assert_eq!(q, U256::from(10u8));
625 assert_eq!(r, U256::ZERO);
626 let (q, r) = U256::from(10u8).div_rem_vartime(&NonZero::new(U256::ONE).unwrap());
627 assert_eq!(q, U256::from(10u8));
628 assert_eq!(r, U256::ZERO);
629 }
630
631 #[test]
632 fn div_edge() {
633 let lo = U128::from_be_hex("00000000000000000000000000000001");
634 let hi = U128::from_be_hex("00000000000000000000000000000001");
635 let y = U128::from_be_hex("00000000000000010000000000000001");
636 let x = U256::from((lo, hi));
637 let expect = (U64::MAX.resize::<{ U256::LIMBS }>(), U256::from(2u64));
638
639 let (q1, r1) = Uint::div_rem(&x, &NonZero::new(y.resize()).unwrap());
640 assert_eq!((q1, r1), expect);
641 let (q2, r2) = Uint::div_rem_vartime(&x, &NonZero::new(y).unwrap());
642 assert_eq!((q2, r2.resize()), expect);
643 let r3 = Uint::rem(&x, &NonZero::new(y.resize()).unwrap());
644 assert_eq!(r3, expect.1);
645 let r4 = Uint::rem_vartime(&x, &NonZero::new(y.resize()).unwrap());
646 assert_eq!(r4, expect.1);
647 let r5 = Uint::rem_wide((lo, hi), &NonZero::new(y).unwrap());
648 assert_eq!(r5.resize(), expect.1);
649 let r6 = Uint::rem_wide_vartime((lo, hi), &NonZero::new(y).unwrap());
650 assert_eq!(r6.resize(), expect.1);
651 }
652
653 #[test]
654 fn div_rem_larger_denominator() {
655 let x = U64::from_be_hex("8000000000000000");
657 let y = U128::from_be_hex("00000000000000010000000000000000")
658 .to_nz()
659 .unwrap();
660 let (quo, rem) = x.div_rem(&y);
661 assert_eq!(quo, Uint::ZERO);
662 assert_eq!(rem, x.resize());
663
664 let x = U64::from_be_hex("8000000000000000");
666 let y = U128::from_be_hex("00000000000000000000000000001000")
667 .to_nz()
668 .unwrap();
669 let (quo, rem) = x.div_rem(&y);
670 assert_eq!(quo, U64::from_be_hex("0008000000000000"));
671 assert_eq!(rem, U128::ZERO);
672
673 let x = U128::from_be_hex("80000000000000008000000000000000");
675 let y =
676 U256::from_be_hex("0000000000000001000000000000000000000000000000010000000000000000")
677 .to_nz()
678 .unwrap();
679 let (quo, rem) = x.div_rem(&y);
680 assert_eq!(quo, U128::ZERO);
681 assert_eq!(rem, x.resize());
682
683 let x = U128::from_be_hex("80000000000000008000000000000000");
685 let y =
686 U256::from_be_hex("0000000000000000000000000000000000000000000000000000000000110000")
687 .to_nz()
688 .unwrap();
689 let (quo, rem) = x.div_rem(&y);
690 assert_eq!(quo, U128::from_be_hex("000007878787878787878f0f0f0f0f0f"));
691 assert_eq!(
692 rem,
693 U256::from_be_hex("0000000000000000000000000000000000000000000000000000000000010000",)
694 );
695 }
696
697 #[test]
698 fn div_rem_larger_numerator() {
699 let denom = U128::from_be_hex("AAAA0000FFFF11117777333344449999");
700 let (full_q, full_r) =
701 U1024::MAX.div_rem(&denom.resize::<{ U1024::LIMBS }>().to_nz().unwrap());
702
703 let (q, r) = U1024::MAX.div_rem(&denom.to_nz().unwrap());
704 assert_eq!(full_q, q);
705 assert_eq!(full_r.resize(), r);
706 }
707
708 #[allow(clippy::op_ref)]
709 #[test]
710 fn div_trait() {
711 let a = U256::from(10u64);
712 let b = NonZero::new(U256::from(2u64)).unwrap();
713 let c = U256::from(5u64);
714
715 assert_eq!(a / b, c);
716 assert_eq!(a / &b, c);
717 assert_eq!(&a / b, c);
718 assert_eq!(&a / &b, c);
719 assert_eq!(Wrapping(a) / b, Wrapping(c));
720 assert_eq!(Wrapping(a) / &b, Wrapping(c));
721 assert_eq!(&Wrapping(a) / b, Wrapping(c));
722 assert_eq!(&Wrapping(a) / &b, Wrapping(c));
723 }
724
725 #[allow(clippy::op_ref)]
726 #[test]
727 fn div_assign_trait() {
728 let a = U256::from(10u64);
729 let b = NonZero::new(U256::from(2u64)).unwrap();
730 let c = U256::from(5u64);
731
732 let mut res = a;
733 res /= b;
734 assert_eq!(res, c);
735 let mut res = a;
736 res /= &b;
737 assert_eq!(res, c);
738
739 let mut res = Wrapping(a);
740 res /= b;
741 assert_eq!(res, Wrapping(c));
742 let mut res = Wrapping(a);
743 res /= &b;
744 assert_eq!(res, Wrapping(c));
745 }
746
747 #[should_panic]
748 #[test]
749 fn div_zero() {
750 let _ = U256::ONE / U256::ZERO;
751 }
752
753 #[should_panic]
754 #[test]
755 #[allow(clippy::op_ref)]
756 fn div_ref_zero() {
757 let _ = &U256::ONE / U256::ZERO;
758 }
759
760 #[test]
761 fn reduce_one() {
762 let r = U256::from(10u8).rem_vartime(&NonZero::new(U256::ONE).unwrap());
763 assert_eq!(r, U256::ZERO);
764 }
765
766 #[test]
767 fn reduce_tests() {
768 let tests = [
769 (U256::from(2u8), 0u8),
770 (U256::from(3u8), 1u8),
771 (U256::from(7u8), 3u8),
772 (U256::MAX, 10u8),
773 ];
774 for (divisor, expect) in tests {
775 let r1 = U256::from(10u8).rem(&NonZero::new(divisor).unwrap());
776 let r2 = U256::from(10u8).rem_vartime(&NonZero::new(divisor).unwrap());
777 assert_eq!(r1, U256::from(expect));
778 assert_eq!(r1, r2);
779 }
780 }
781
782 #[test]
783 fn reduce_tests_wide_zero_padded() {
784 let tests = [
785 (U256::from(2u8), 0u8),
786 (U256::from(3u8), 1u8),
787 (U256::from(7u8), 3u8),
788 (U256::MAX, 10u8),
789 ];
790 for (divisor, expect) in tests {
791 let r1 = U256::rem_wide(
792 (U256::from(10u8), U256::ZERO),
793 &NonZero::new(divisor).unwrap(),
794 );
795 let r2 = U256::rem_wide_vartime(
796 (U256::from(10u8), U256::ZERO),
797 &NonZero::new(divisor).unwrap(),
798 );
799 assert_eq!(r1, U256::from(expect));
800 assert_eq!(r1, r2);
801 }
802 }
803
804 #[test]
805 fn rem_wide_corner_case() {
806 let modulus = "0000000000000000000000000000000081000000000000000000000000000001";
807 let modulus = NonZero::new(U256::from_be_hex(modulus)).expect("it's odd and not zero");
808 let lo_hi = (
809 U256::from_be_hex("1000000000000000000000000000000000000000000000000000000000000001"),
810 U256::ZERO,
811 );
812 let rem = U256::rem_wide(lo_hi, &modulus);
813 assert_eq!(
815 &rem.to_be_bytes().as_ref()[0..16],
816 U128::ZERO.to_be_bytes().as_ref()
817 );
818 let expected = U128::from_be_hex("203F80FE03F80FE03F80FE03F80FE041");
820 assert_eq!(
821 &rem.to_be_bytes().as_ref()[16..],
822 expected.to_be_bytes().as_ref()
823 );
824
825 let remv = U256::rem_wide_vartime(lo_hi, &modulus);
826 assert_eq!(rem, remv);
827 }
828
829 #[test]
830 fn reduce_max() {
831 let mut a = U256::ZERO;
832 let mut b = U256::ZERO;
833 b.limbs[b.limbs.len() - 1] = Limb(Word::MAX);
834 let r = a.wrapping_rem_vartime(&b);
835 assert_eq!(r, Uint::ZERO);
836 a.limbs[a.limbs.len() - 1] = Limb(1 << (Limb::HI_BIT - 7));
837 b.limbs[b.limbs.len() - 1] = Limb(0x82 << (Limb::HI_BIT - 7));
838 let r = a.wrapping_rem_vartime(&b);
839 assert_eq!(r, a);
840 }
841
842 #[cfg(feature = "rand_core")]
843 #[test]
844 fn rem2krand() {
845 let mut rng = ChaCha8Rng::from_seed([7u8; 32]);
846 for _ in 0..25 {
847 let num = U256::random_from_rng(&mut rng);
848 let k = rng.next_u32() % 256;
849 let den = U256::ONE.overflowing_shl_vartime(k).unwrap();
850
851 let a = num.rem2k_vartime(k);
852 let e = num.wrapping_rem_vartime(&den);
853 assert_eq!(a, e);
854 }
855 }
856
857 #[allow(clippy::op_ref)]
858 #[test]
859 fn rem_trait() {
860 let a = U256::from(10u64);
861 let b = NonZero::new(U256::from(3u64)).unwrap();
862 let c = U256::from(1u64);
863
864 assert_eq!(a % b, c);
865 assert_eq!(a % &b, c);
866 assert_eq!(&a % b, c);
867 assert_eq!(&a % &b, c);
868 assert_eq!(Wrapping(a) % b, Wrapping(c));
869 assert_eq!(Wrapping(a) % &b, Wrapping(c));
870 assert_eq!(&Wrapping(a) % b, Wrapping(c));
871 assert_eq!(&Wrapping(a) % &b, Wrapping(c));
872 }
873
874 #[allow(clippy::op_ref)]
875 #[test]
876 fn rem_assign_trait() {
877 let a = U256::from(10u64);
878 let b = NonZero::new(U256::from(3u64)).unwrap();
879 let c = U256::from(1u64);
880
881 let mut res = a;
882 res %= b;
883 assert_eq!(res, c);
884 let mut res = a;
885 res %= &b;
886 assert_eq!(res, c);
887
888 let mut res = Wrapping(a);
889 res %= b;
890 assert_eq!(res, Wrapping(c));
891 let mut res = Wrapping(a);
892 res %= &b;
893 assert_eq!(res, Wrapping(c));
894 }
895
896 #[should_panic]
897 #[test]
898 fn rem_zero() {
899 let _ = U256::ONE % U256::ZERO;
900 }
901
902 #[should_panic]
903 #[test]
904 #[allow(clippy::op_ref)]
905 fn rem_ref_zero() {
906 let _ = &U256::ONE % U256::ZERO;
907 }
908
909 #[test]
910 fn rem_mixed() {
911 let x = U1024::from_be_hex(concat![
912 "3740C11DB8F260753BC6B97DD2B8746D3E2694412772AC6ABD975119EE0A6190",
913 "F27F6F0969BCA069D8D151031AF83EE2283CC2E3E4FADBBDB9EEDBF0B8F4C1FD",
914 "51912C0D329FDC37D49176DB0A1A2D17E5E6D4F9F6B217FE9412EAA2F881F702",
915 "7A831C1B06D31D3618D218D6E667DBD85BFC7B6B6B93422D52516989376AA29A",
916 ]);
917 let y = U128::from_u64(1234567890987654321);
918 let rem = x.rem_mixed(&y.to_nz().unwrap());
919
920 let y2: U1024 = U128::concat_mixed(&y, &U896::ZERO);
921 let rem_control = x.rem(&NonZero::new(y2).unwrap());
922
923 assert_eq!(rem.bits(), rem_control.bits());
924 assert_eq!(rem.as_words(), &rem_control.as_words()[0..U128::LIMBS]);
925 assert!(
926 rem_control.as_words()[U128::LIMBS..]
927 .iter()
928 .all(|w| *w == 0)
929 );
930 }
931
932 #[test]
933 fn rem_mixed_even() {
934 let x = U1024::from_be_hex(concat![
935 "3740C11DB8F260753BC6B97DD2B8746D3E2694412772AC6ABD975119EE0A6190",
936 "F27F6F0969BCA069D8D151031AF83EE2283CC2E3E4FADBBDB9EEDBF0B8F4C1FD",
937 "51912C0D329FDC37D49176DB0A1A2D17E5E6D4F9F6B217FE9412EAA2F881F702",
938 "7A831C1B06D31D3618D218D6E667DBD85BFC7B6B6B93422D52516989376AA29A",
939 ]);
940 let y = U512::from_u64(1234567890987654321);
941 let rem: U512 = x.rem_mixed(&y.to_nz().unwrap());
942
943 let y_wide = U512::concat_mixed(&y, &U512::ZERO);
944 let rem_control: U1024 = x.rem(&NonZero::new(y_wide).unwrap());
945
946 assert_eq!(rem.bits(), rem_control.bits());
947 assert_eq!(rem.as_words(), &rem_control.as_words()[0..U512::LIMBS]);
948 assert!(
949 rem_control.as_words()[U512::LIMBS..]
950 .iter()
951 .all(|w| *w == 0)
952 );
953 }
954
955 #[test]
956 fn rem_mixed_through_traits() {
957 struct A<T, U> {
958 t: T,
959 u: U,
960 }
961 impl<T, U> A<T, U>
962 where
963 T: RemMixed<U>,
964 U: Clone + Zero + One + CtAssign,
965 {
966 fn reduce_t_by_u(&self) -> U {
967 let rhs = &NonZero::new(self.u.clone()).unwrap();
968 self.t.rem_mixed(rhs)
969 }
970 }
971
972 let a = A {
973 t: U1024::from(1234567890u64),
974 u: U128::from(456u64),
975 };
976 assert_eq!(a.reduce_t_by_u(), U128::from(330u64));
977 }
978
979 #[test]
980 fn div_vartime_through_traits() {
981 struct A<T> {
982 x: T,
983 y: T,
984 }
985 impl<T> A<T>
986 where
987 T: DivVartime + Clone + Zero + One + CtAssign,
988 {
989 fn divide_x_by_y(&self) -> T {
990 let rhs = &NonZero::new(self.y.clone()).unwrap();
991 self.x.div_vartime(rhs)
992 }
993 }
994
995 let a = A {
996 x: U1024::from(1234567890u64),
997 y: U1024::from(456u64),
998 };
999 assert_eq!(a.divide_x_by_y(), U1024::from(2707385u64));
1000 }
1001}