1use super::div_limb::{div_rem_limb_with_reciprocal, Reciprocal};
4use crate::{CtChoice, Limb, NonZero, Uint, Word, Wrapping};
5use core::ops::{Div, DivAssign, Rem, RemAssign};
6use subtle::CtOption;
7
8impl<const LIMBS: usize> Uint<LIMBS> {
9 #[inline(always)]
12 pub const fn ct_div_rem_limb_with_reciprocal(&self, reciprocal: &Reciprocal) -> (Self, Limb) {
13 div_rem_limb_with_reciprocal(self, reciprocal)
14 }
15
16 #[inline(always)]
19 pub fn div_rem_limb_with_reciprocal(
20 &self,
21 reciprocal: &CtOption<Reciprocal>,
22 ) -> CtOption<(Self, Limb)> {
23 reciprocal.map(|r| div_rem_limb_with_reciprocal(self, &r))
24 }
25
26 #[inline(always)]
30 pub(crate) const fn ct_div_rem_limb(&self, rhs: Limb) -> (Self, Limb, CtChoice) {
31 let (reciprocal, is_some) = Reciprocal::ct_new(rhs);
32 let (quo, rem) = div_rem_limb_with_reciprocal(self, &reciprocal);
33 (quo, rem, is_some)
34 }
35
36 #[inline(always)]
38 pub fn div_rem_limb(&self, rhs: NonZero<Limb>) -> (Self, Limb) {
39 let (quo, rem, _is_some) = self.ct_div_rem_limb(*rhs);
41 (quo, rem)
42 }
43
44 pub(crate) const fn ct_div_rem(&self, rhs: &Self) -> (Self, Self, CtChoice) {
55 let mb = rhs.bits_vartime();
56 let mut bd = Self::BITS - mb;
57 let mut rem = *self;
58 let mut quo = Self::ZERO;
59 let mut c = rhs.shl_vartime(bd);
60
61 loop {
62 let (mut r, borrow) = rem.sbb(&c, Limb::ZERO);
63 rem = Self::ct_select(&r, &rem, CtChoice::from_mask(borrow.0));
64 r = quo.bitor(&Self::ONE);
65 quo = Self::ct_select(&r, &quo, CtChoice::from_mask(borrow.0));
66 if bd == 0 {
67 break;
68 }
69 bd -= 1;
70 c = c.shr_vartime(1);
71 quo = quo.shl_vartime(1);
72 }
73
74 let is_some = Limb(mb as Word).ct_is_nonzero();
75 quo = Self::ct_select(&Self::ZERO, &quo, is_some);
76 (quo, rem, is_some)
77 }
78
79 pub const fn const_rem(&self, rhs: &Self) -> (Self, CtChoice) {
88 let mb = rhs.bits_vartime();
89 let mut bd = Self::BITS - mb;
90 let mut rem = *self;
91 let mut c = rhs.shl_vartime(bd);
92
93 loop {
94 let (r, borrow) = rem.sbb(&c, Limb::ZERO);
95 rem = Self::ct_select(&r, &rem, CtChoice::from_mask(borrow.0));
96 if bd == 0 {
97 break;
98 }
99 bd -= 1;
100 c = c.shr_vartime(1);
101 }
102
103 let is_some = Limb(mb as Word).ct_is_nonzero();
104 (rem, is_some)
105 }
106
107 pub const fn const_rem_wide(lower_upper: (Self, Self), rhs: &Self) -> (Self, CtChoice) {
115 let mb = rhs.bits_vartime();
116
117 let mut bd = (2 * Self::BITS) - mb;
119
120 let (mut lower, mut upper) = lower_upper;
122
123 let mut c = Self::shl_vartime_wide((*rhs, Uint::ZERO), bd);
125
126 loop {
127 let (lower_sub, borrow) = lower.sbb(&c.0, Limb::ZERO);
128 let (upper_sub, borrow) = upper.sbb(&c.1, borrow);
129
130 lower = Self::ct_select(&lower_sub, &lower, CtChoice::from_mask(borrow.0));
131 upper = Self::ct_select(&upper_sub, &upper, CtChoice::from_mask(borrow.0));
132 if bd == 0 {
133 break;
134 }
135 bd -= 1;
136 c = Self::shr_vartime_wide(c, 1);
137 }
138
139 let is_some = Limb(mb as Word).ct_is_nonzero();
140 (lower, is_some)
141 }
142
143 pub const fn rem2k(&self, k: usize) -> Self {
146 let highest = (LIMBS - 1) as u32;
147 let index = k as u32 / (Limb::BITS as u32);
148 let le = Limb::ct_le(Limb::from_u32(index), Limb::from_u32(highest));
149 let word = Limb::ct_select(Limb::from_u32(highest), Limb::from_u32(index), le).0 as usize;
150
151 let base = k % Limb::BITS;
152 let mask = (1 << base) - 1;
153 let mut out = *self;
154
155 let outmask = Limb(out.limbs[word].0 & mask);
156
157 out.limbs[word] = Limb::ct_select(out.limbs[word], outmask, le);
158
159 let mut i = word + 1;
160 while i < LIMBS {
161 out.limbs[i] = Limb::ZERO;
162 i += 1;
163 }
164
165 out
166 }
167
168 pub fn div_rem(&self, rhs: &NonZero<Self>) -> (Self, Self) {
170 let (q, r, _c) = self.ct_div_rem(rhs);
172 (q, r)
173 }
174
175 pub fn rem(&self, rhs: &NonZero<Self>) -> Self {
177 let (r, _c) = self.const_rem(rhs);
179 r
180 }
181
182 pub const fn wrapping_div(&self, rhs: &Self) -> Self {
188 let (q, _, c) = self.ct_div_rem(rhs);
189 assert!(c.is_true_vartime(), "divide by zero");
190 q
191 }
192
193 pub fn checked_div(&self, rhs: &Self) -> CtOption<Self> {
196 NonZero::new(*rhs).map(|rhs| {
197 let (q, _r) = self.div_rem(&rhs);
198 q
199 })
200 }
201
202 pub const fn wrapping_rem(&self, rhs: &Self) -> Self {
208 let (r, c) = self.const_rem(rhs);
209 assert!(c.is_true_vartime(), "modulo zero");
210 r
211 }
212
213 pub fn checked_rem(&self, rhs: &Self) -> CtOption<Self> {
216 NonZero::new(*rhs).map(|rhs| self.rem(&rhs))
217 }
218}
219
220impl<const LIMBS: usize> Div<&NonZero<Limb>> for &Uint<LIMBS> {
225 type Output = Uint<LIMBS>;
226
227 fn div(self, rhs: &NonZero<Limb>) -> Self::Output {
228 *self / *rhs
229 }
230}
231
232impl<const LIMBS: usize> Div<&NonZero<Limb>> for Uint<LIMBS> {
233 type Output = Uint<LIMBS>;
234
235 fn div(self, rhs: &NonZero<Limb>) -> Self::Output {
236 self / *rhs
237 }
238}
239
240impl<const LIMBS: usize> Div<NonZero<Limb>> for &Uint<LIMBS> {
241 type Output = Uint<LIMBS>;
242
243 fn div(self, rhs: NonZero<Limb>) -> Self::Output {
244 *self / rhs
245 }
246}
247
248impl<const LIMBS: usize> Div<NonZero<Limb>> for Uint<LIMBS> {
249 type Output = Uint<LIMBS>;
250
251 fn div(self, rhs: NonZero<Limb>) -> Self::Output {
252 let (q, _, _) = self.ct_div_rem_limb(*rhs);
253 q
254 }
255}
256
257impl<const LIMBS: usize> DivAssign<&NonZero<Limb>> for Uint<LIMBS> {
258 fn div_assign(&mut self, rhs: &NonZero<Limb>) {
259 *self /= *rhs;
260 }
261}
262
263impl<const LIMBS: usize> DivAssign<NonZero<Limb>> for Uint<LIMBS> {
264 fn div_assign(&mut self, rhs: NonZero<Limb>) {
265 *self = *self / rhs;
266 }
267}
268
269impl<const LIMBS: usize> Div<NonZero<Limb>> for Wrapping<Uint<LIMBS>> {
270 type Output = Wrapping<Uint<LIMBS>>;
271
272 fn div(self, rhs: NonZero<Limb>) -> Self::Output {
273 Wrapping(self.0 / rhs)
274 }
275}
276
277impl<const LIMBS: usize> Div<NonZero<Limb>> for &Wrapping<Uint<LIMBS>> {
278 type Output = Wrapping<Uint<LIMBS>>;
279
280 fn div(self, rhs: NonZero<Limb>) -> Self::Output {
281 *self / rhs
282 }
283}
284
285impl<const LIMBS: usize> Div<&NonZero<Limb>> for &Wrapping<Uint<LIMBS>> {
286 type Output = Wrapping<Uint<LIMBS>>;
287
288 fn div(self, rhs: &NonZero<Limb>) -> Self::Output {
289 *self / *rhs
290 }
291}
292
293impl<const LIMBS: usize> Div<&NonZero<Limb>> for Wrapping<Uint<LIMBS>> {
294 type Output = Wrapping<Uint<LIMBS>>;
295
296 fn div(self, rhs: &NonZero<Limb>) -> Self::Output {
297 self / *rhs
298 }
299}
300
301impl<const LIMBS: usize> DivAssign<&NonZero<Limb>> for Wrapping<Uint<LIMBS>> {
302 fn div_assign(&mut self, rhs: &NonZero<Limb>) {
303 *self = Wrapping(self.0 / rhs)
304 }
305}
306
307impl<const LIMBS: usize> DivAssign<NonZero<Limb>> for Wrapping<Uint<LIMBS>> {
308 fn div_assign(&mut self, rhs: NonZero<Limb>) {
309 *self /= &rhs;
310 }
311}
312
313impl<const LIMBS: usize> Rem<&NonZero<Limb>> for &Uint<LIMBS> {
314 type Output = Limb;
315
316 fn rem(self, rhs: &NonZero<Limb>) -> Self::Output {
317 *self % *rhs
318 }
319}
320
321impl<const LIMBS: usize> Rem<&NonZero<Limb>> for Uint<LIMBS> {
322 type Output = Limb;
323
324 fn rem(self, rhs: &NonZero<Limb>) -> Self::Output {
325 self % *rhs
326 }
327}
328
329impl<const LIMBS: usize> Rem<NonZero<Limb>> for &Uint<LIMBS> {
330 type Output = Limb;
331
332 fn rem(self, rhs: NonZero<Limb>) -> Self::Output {
333 *self % rhs
334 }
335}
336
337impl<const LIMBS: usize> Rem<NonZero<Limb>> for Uint<LIMBS> {
338 type Output = Limb;
339
340 fn rem(self, rhs: NonZero<Limb>) -> Self::Output {
341 let (_, r, _) = self.ct_div_rem_limb(*rhs);
342 r
343 }
344}
345
346impl<const LIMBS: usize> RemAssign<&NonZero<Limb>> for Uint<LIMBS> {
347 fn rem_assign(&mut self, rhs: &NonZero<Limb>) {
348 *self = (*self % rhs).into();
349 }
350}
351
352impl<const LIMBS: usize> RemAssign<NonZero<Limb>> for Uint<LIMBS> {
353 fn rem_assign(&mut self, rhs: NonZero<Limb>) {
354 *self %= &rhs;
355 }
356}
357
358impl<const LIMBS: usize> Rem<NonZero<Limb>> for Wrapping<Uint<LIMBS>> {
359 type Output = Wrapping<Limb>;
360
361 fn rem(self, rhs: NonZero<Limb>) -> Self::Output {
362 Wrapping(self.0 % rhs)
363 }
364}
365
366impl<const LIMBS: usize> Rem<NonZero<Limb>> for &Wrapping<Uint<LIMBS>> {
367 type Output = Wrapping<Limb>;
368
369 fn rem(self, rhs: NonZero<Limb>) -> Self::Output {
370 *self % rhs
371 }
372}
373
374impl<const LIMBS: usize> Rem<&NonZero<Limb>> for &Wrapping<Uint<LIMBS>> {
375 type Output = Wrapping<Limb>;
376
377 fn rem(self, rhs: &NonZero<Limb>) -> Self::Output {
378 *self % *rhs
379 }
380}
381
382impl<const LIMBS: usize> Rem<&NonZero<Limb>> for Wrapping<Uint<LIMBS>> {
383 type Output = Wrapping<Limb>;
384
385 fn rem(self, rhs: &NonZero<Limb>) -> Self::Output {
386 self % *rhs
387 }
388}
389
390impl<const LIMBS: usize> RemAssign<NonZero<Limb>> for Wrapping<Uint<LIMBS>> {
391 fn rem_assign(&mut self, rhs: NonZero<Limb>) {
392 *self %= &rhs;
393 }
394}
395
396impl<const LIMBS: usize> RemAssign<&NonZero<Limb>> for Wrapping<Uint<LIMBS>> {
397 fn rem_assign(&mut self, rhs: &NonZero<Limb>) {
398 *self = Wrapping((self.0 % rhs).into())
399 }
400}
401
402impl<const LIMBS: usize> Div<&NonZero<Uint<LIMBS>>> for &Uint<LIMBS> {
407 type Output = Uint<LIMBS>;
408
409 fn div(self, rhs: &NonZero<Uint<LIMBS>>) -> Self::Output {
410 *self / *rhs
411 }
412}
413
414impl<const LIMBS: usize> Div<&NonZero<Uint<LIMBS>>> for Uint<LIMBS> {
415 type Output = Uint<LIMBS>;
416
417 fn div(self, rhs: &NonZero<Uint<LIMBS>>) -> Self::Output {
418 self / *rhs
419 }
420}
421
422impl<const LIMBS: usize> Div<NonZero<Uint<LIMBS>>> for &Uint<LIMBS> {
423 type Output = Uint<LIMBS>;
424
425 fn div(self, rhs: NonZero<Uint<LIMBS>>) -> Self::Output {
426 *self / rhs
427 }
428}
429
430impl<const LIMBS: usize> Div<NonZero<Uint<LIMBS>>> for Uint<LIMBS> {
431 type Output = Uint<LIMBS>;
432
433 fn div(self, rhs: NonZero<Uint<LIMBS>>) -> Self::Output {
434 let (q, _) = self.div_rem(&rhs);
435 q
436 }
437}
438
439impl<const LIMBS: usize> DivAssign<&NonZero<Uint<LIMBS>>> for Uint<LIMBS> {
440 fn div_assign(&mut self, rhs: &NonZero<Uint<LIMBS>>) {
441 *self /= *rhs
442 }
443}
444
445impl<const LIMBS: usize> DivAssign<NonZero<Uint<LIMBS>>> for Uint<LIMBS> {
446 fn div_assign(&mut self, rhs: NonZero<Uint<LIMBS>>) {
447 *self = *self / rhs;
448 }
449}
450
451impl<const LIMBS: usize> Div<NonZero<Uint<LIMBS>>> for Wrapping<Uint<LIMBS>> {
452 type Output = Wrapping<Uint<LIMBS>>;
453
454 fn div(self, rhs: NonZero<Uint<LIMBS>>) -> Self::Output {
455 Wrapping(self.0 / rhs)
456 }
457}
458
459impl<const LIMBS: usize> Div<NonZero<Uint<LIMBS>>> for &Wrapping<Uint<LIMBS>> {
460 type Output = Wrapping<Uint<LIMBS>>;
461
462 fn div(self, rhs: NonZero<Uint<LIMBS>>) -> Self::Output {
463 *self / rhs
464 }
465}
466
467impl<const LIMBS: usize> Div<&NonZero<Uint<LIMBS>>> for &Wrapping<Uint<LIMBS>> {
468 type Output = Wrapping<Uint<LIMBS>>;
469
470 fn div(self, rhs: &NonZero<Uint<LIMBS>>) -> Self::Output {
471 *self / *rhs
472 }
473}
474
475impl<const LIMBS: usize> Div<&NonZero<Uint<LIMBS>>> for Wrapping<Uint<LIMBS>> {
476 type Output = Wrapping<Uint<LIMBS>>;
477
478 fn div(self, rhs: &NonZero<Uint<LIMBS>>) -> Self::Output {
479 self / *rhs
480 }
481}
482
483impl<const LIMBS: usize> DivAssign<&NonZero<Uint<LIMBS>>> for Wrapping<Uint<LIMBS>> {
484 fn div_assign(&mut self, rhs: &NonZero<Uint<LIMBS>>) {
485 *self = Wrapping(self.0 / rhs);
486 }
487}
488
489impl<const LIMBS: usize> DivAssign<NonZero<Uint<LIMBS>>> for Wrapping<Uint<LIMBS>> {
490 fn div_assign(&mut self, rhs: NonZero<Uint<LIMBS>>) {
491 *self /= &rhs;
492 }
493}
494
495impl<const LIMBS: usize> Rem<&NonZero<Uint<LIMBS>>> for &Uint<LIMBS> {
496 type Output = Uint<LIMBS>;
497
498 fn rem(self, rhs: &NonZero<Uint<LIMBS>>) -> Self::Output {
499 *self % *rhs
500 }
501}
502
503impl<const LIMBS: usize> Rem<&NonZero<Uint<LIMBS>>> for Uint<LIMBS> {
504 type Output = Uint<LIMBS>;
505
506 fn rem(self, rhs: &NonZero<Uint<LIMBS>>) -> Self::Output {
507 self % *rhs
508 }
509}
510
511impl<const LIMBS: usize> Rem<NonZero<Uint<LIMBS>>> for &Uint<LIMBS> {
512 type Output = Uint<LIMBS>;
513
514 fn rem(self, rhs: NonZero<Uint<LIMBS>>) -> Self::Output {
515 *self % rhs
516 }
517}
518
519impl<const LIMBS: usize> Rem<NonZero<Uint<LIMBS>>> for Uint<LIMBS> {
520 type Output = Uint<LIMBS>;
521
522 fn rem(self, rhs: NonZero<Uint<LIMBS>>) -> Self::Output {
523 Self::rem(&self, &rhs)
524 }
525}
526
527impl<const LIMBS: usize> RemAssign<&NonZero<Uint<LIMBS>>> for Uint<LIMBS> {
528 fn rem_assign(&mut self, rhs: &NonZero<Uint<LIMBS>>) {
529 *self %= *rhs
530 }
531}
532
533impl<const LIMBS: usize> RemAssign<NonZero<Uint<LIMBS>>> for Uint<LIMBS> {
534 fn rem_assign(&mut self, rhs: NonZero<Uint<LIMBS>>) {
535 *self = *self % rhs;
536 }
537}
538
539impl<const LIMBS: usize> Rem<NonZero<Uint<LIMBS>>> for Wrapping<Uint<LIMBS>> {
540 type Output = Wrapping<Uint<LIMBS>>;
541
542 fn rem(self, rhs: NonZero<Uint<LIMBS>>) -> Self::Output {
543 Wrapping(self.0 % rhs)
544 }
545}
546
547impl<const LIMBS: usize> Rem<NonZero<Uint<LIMBS>>> for &Wrapping<Uint<LIMBS>> {
548 type Output = Wrapping<Uint<LIMBS>>;
549
550 fn rem(self, rhs: NonZero<Uint<LIMBS>>) -> Self::Output {
551 *self % rhs
552 }
553}
554
555impl<const LIMBS: usize> Rem<&NonZero<Uint<LIMBS>>> for &Wrapping<Uint<LIMBS>> {
556 type Output = Wrapping<Uint<LIMBS>>;
557
558 fn rem(self, rhs: &NonZero<Uint<LIMBS>>) -> Self::Output {
559 *self % *rhs
560 }
561}
562
563impl<const LIMBS: usize> Rem<&NonZero<Uint<LIMBS>>> for Wrapping<Uint<LIMBS>> {
564 type Output = Wrapping<Uint<LIMBS>>;
565
566 fn rem(self, rhs: &NonZero<Uint<LIMBS>>) -> Self::Output {
567 self % *rhs
568 }
569}
570
571impl<const LIMBS: usize> RemAssign<NonZero<Uint<LIMBS>>> for Wrapping<Uint<LIMBS>> {
572 fn rem_assign(&mut self, rhs: NonZero<Uint<LIMBS>>) {
573 *self %= &rhs;
574 }
575}
576
577impl<const LIMBS: usize> RemAssign<&NonZero<Uint<LIMBS>>> for Wrapping<Uint<LIMBS>> {
578 fn rem_assign(&mut self, rhs: &NonZero<Uint<LIMBS>>) {
579 *self = Wrapping(self.0 % rhs)
580 }
581}
582
583#[cfg(test)]
584mod tests {
585 use super::*;
586 use crate::{limb::HI_BIT, Limb, U256};
587
588 #[cfg(feature = "rand")]
589 use {
590 crate::{CheckedMul, Random},
591 rand_chacha::ChaChaRng,
592 rand_core::RngCore,
593 rand_core::SeedableRng,
594 };
595
596 #[test]
597 fn div_word() {
598 for (n, d, e, ee) in &[
599 (200u64, 2u64, 100u64, 0),
600 (100u64, 25u64, 4u64, 0),
601 (100u64, 10u64, 10u64, 0),
602 (1024u64, 8u64, 128u64, 0),
603 (27u64, 13u64, 2u64, 1u64),
604 (26u64, 13u64, 2u64, 0u64),
605 (14u64, 13u64, 1u64, 1u64),
606 (13u64, 13u64, 1u64, 0u64),
607 (12u64, 13u64, 0u64, 12u64),
608 (1u64, 13u64, 0u64, 1u64),
609 ] {
610 let lhs = U256::from(*n);
611 let rhs = U256::from(*d);
612 let (q, r, is_some) = lhs.ct_div_rem(&rhs);
613 assert!(is_some.is_true_vartime());
614 assert_eq!(U256::from(*e), q);
615 assert_eq!(U256::from(*ee), r);
616 }
617 }
618
619 #[cfg(feature = "rand")]
620 #[test]
621 fn div() {
622 let mut rng = ChaChaRng::from_seed([7u8; 32]);
623 for _ in 0..25 {
624 let num = U256::random(&mut rng).shr_vartime(128);
625 let den = U256::random(&mut rng).shr_vartime(128);
626 let n = num.checked_mul(&den);
627 if n.is_some().into() {
628 let (q, _, is_some) = n.unwrap().ct_div_rem(&den);
629 assert!(is_some.is_true_vartime());
630 assert_eq!(q, num);
631 }
632 }
633 }
634
635 #[test]
636 fn div_max() {
637 let mut a = U256::ZERO;
638 let mut b = U256::ZERO;
639 b.limbs[b.limbs.len() - 1] = Limb(Word::MAX);
640 let q = a.wrapping_div(&b);
641 assert_eq!(q, Uint::ZERO);
642 a.limbs[a.limbs.len() - 1] = Limb(1 << (HI_BIT - 7));
643 b.limbs[b.limbs.len() - 1] = Limb(0x82 << (HI_BIT - 7));
644 let q = a.wrapping_div(&b);
645 assert_eq!(q, Uint::ZERO);
646 }
647
648 #[test]
649 fn div_zero() {
650 let (q, r, is_some) = U256::ONE.ct_div_rem(&U256::ZERO);
651 assert!(!is_some.is_true_vartime());
652 assert_eq!(q, U256::ZERO);
653 assert_eq!(r, U256::ONE);
654 }
655
656 #[test]
657 fn div_one() {
658 let (q, r, is_some) = U256::from(10u8).ct_div_rem(&U256::ONE);
659 assert!(is_some.is_true_vartime());
660 assert_eq!(q, U256::from(10u8));
661 assert_eq!(r, U256::ZERO);
662 }
663
664 #[test]
665 fn reduce_one() {
666 let (r, is_some) = U256::from(10u8).const_rem(&U256::ONE);
667 assert!(is_some.is_true_vartime());
668 assert_eq!(r, U256::ZERO);
669 }
670
671 #[test]
672 fn reduce_zero() {
673 let u = U256::from(10u8);
674 let (r, is_some) = u.const_rem(&U256::ZERO);
675 assert!(!is_some.is_true_vartime());
676 assert_eq!(r, u);
677 }
678
679 #[test]
680 fn reduce_tests() {
681 let (r, is_some) = U256::from(10u8).const_rem(&U256::from(2u8));
682 assert!(is_some.is_true_vartime());
683 assert_eq!(r, U256::ZERO);
684 let (r, is_some) = U256::from(10u8).const_rem(&U256::from(3u8));
685 assert!(is_some.is_true_vartime());
686 assert_eq!(r, U256::ONE);
687 let (r, is_some) = U256::from(10u8).const_rem(&U256::from(7u8));
688 assert!(is_some.is_true_vartime());
689 assert_eq!(r, U256::from(3u8));
690 }
691
692 #[test]
693 fn reduce_tests_wide_zero_padded() {
694 let (r, is_some) = U256::const_rem_wide((U256::from(10u8), U256::ZERO), &U256::from(2u8));
695 assert!(is_some.is_true_vartime());
696 assert_eq!(r, U256::ZERO);
697 let (r, is_some) = U256::const_rem_wide((U256::from(10u8), U256::ZERO), &U256::from(3u8));
698 assert!(is_some.is_true_vartime());
699 assert_eq!(r, U256::ONE);
700 let (r, is_some) = U256::const_rem_wide((U256::from(10u8), U256::ZERO), &U256::from(7u8));
701 assert!(is_some.is_true_vartime());
702 assert_eq!(r, U256::from(3u8));
703 }
704
705 #[test]
706 fn reduce_max() {
707 let mut a = U256::ZERO;
708 let mut b = U256::ZERO;
709 b.limbs[b.limbs.len() - 1] = Limb(Word::MAX);
710 let r = a.wrapping_rem(&b);
711 assert_eq!(r, Uint::ZERO);
712 a.limbs[a.limbs.len() - 1] = Limb(1 << (HI_BIT - 7));
713 b.limbs[b.limbs.len() - 1] = Limb(0x82 << (HI_BIT - 7));
714 let r = a.wrapping_rem(&b);
715 assert_eq!(r, a);
716 }
717
718 #[cfg(feature = "rand")]
719 #[test]
720 fn rem2krand() {
721 let mut rng = ChaChaRng::from_seed([7u8; 32]);
722 for _ in 0..25 {
723 let num = U256::random(&mut rng);
724 let k = (rng.next_u32() % 256) as usize;
725 let den = U256::ONE.shl_vartime(k);
726
727 let a = num.rem2k(k);
728 let e = num.wrapping_rem(&den);
729 assert_eq!(a, e);
730 }
731 }
732
733 #[allow(clippy::op_ref)]
734 #[test]
735 fn rem_trait() {
736 let a = U256::from(10u64);
737 let b = NonZero::new(U256::from(3u64)).unwrap();
738 let c = U256::from(1u64);
739
740 assert_eq!(a % b, c);
741 assert_eq!(a % &b, c);
742 assert_eq!(&a % b, c);
743 assert_eq!(&a % &b, c);
744 }
745}