1use super::addition::__add2;
2use super::shift::biguint_shl;
3use super::{cmp_slice, ilog2, BigUint};
4
5use crate::big_digit::{self, BigDigit, BigDigits, DoubleBigDigit, BITS};
6use crate::UsizePromotion;
7
8use alloc::borrow::Cow;
9use core::cmp::Ordering::{Equal, Greater, Less};
10use core::mem;
11use core::ops::{Div, DivAssign, Rem, RemAssign};
12use num_integer::Integer;
13use num_traits::{CheckedDiv, CheckedEuclid, Euclid, ToPrimitive, Zero};
14
15pub(super) const FAST_DIV_WIDE: bool = cfg!(any(target_arch = "x86", target_arch = "x86_64"));
16
17#[cfg(any(miri, not(any(target_arch = "x86", target_arch = "x86_64"))))]
24#[inline]
25fn div_wide(hi: BigDigit, lo: BigDigit, divisor: BigDigit) -> (BigDigit, BigDigit) {
26 debug_assert!(hi < divisor);
27
28 let lhs = big_digit::to_doublebigdigit(hi, lo);
29 let rhs = DoubleBigDigit::from(divisor);
30 ((lhs / rhs) as BigDigit, (lhs % rhs) as BigDigit)
31}
32
33#[cfg(all(not(miri), any(target_arch = "x86", target_arch = "x86_64")))]
35#[inline]
36fn div_wide(hi: BigDigit, lo: BigDigit, divisor: BigDigit) -> (BigDigit, BigDigit) {
37 debug_assert!(hi < divisor);
41
42 unsafe {
47 let (div, rem);
48
49 cfg_digit!(
50 macro_rules! div {
51 () => {
52 "div {0:e}"
53 };
54 }
55 macro_rules! div {
56 () => {
57 "div {0:r}"
58 };
59 }
60 );
61
62 core::arch::asm!(
63 div!(),
64 in(reg) divisor,
65 inout("dx") hi => rem,
66 inout("ax") lo => div,
67 options(pure, nomem, nostack),
68 );
69
70 (div, rem)
71 }
72}
73
74#[inline]
77fn div_half(rem: BigDigit, digit: BigDigit, divisor: BigDigit) -> (BigDigit, BigDigit) {
78 use crate::big_digit::{HALF, HALF_BITS};
79
80 debug_assert!(rem < divisor && divisor <= HALF);
81 let (hi, rem) = ((rem << HALF_BITS) | (digit >> HALF_BITS)).div_rem(&divisor);
82 let (lo, rem) = ((rem << HALF_BITS) | (digit & HALF)).div_rem(&divisor);
83 ((hi << HALF_BITS) | lo, rem)
84}
85
86#[inline]
87pub(super) fn div_rem_digit(mut a: BigUint, b: BigDigit) -> (BigUint, BigDigit) {
88 if b == 0 {
89 panic!("attempt to divide by zero")
90 }
91
92 let mut rem = 0;
93
94 if !FAST_DIV_WIDE && b <= big_digit::HALF {
95 for d in a.data.iter_mut().rev() {
96 let (q, r) = div_half(rem, *d, b);
97 *d = q;
98 rem = r;
99 }
100 } else {
101 for d in a.data.iter_mut().rev() {
102 let (q, r) = div_wide(rem, *d, b);
103 *d = q;
104 rem = r;
105 }
106 }
107
108 a.data.normalize();
109 (a, rem)
110}
111
112#[inline]
113fn rem_digit(a: &BigUint, b: BigDigit) -> BigDigit {
114 if b == 0 {
115 panic!("attempt to divide by zero")
116 }
117
118 let mut rem = 0;
119
120 if !FAST_DIV_WIDE && b <= big_digit::HALF {
121 for &digit in a.data.iter().rev() {
122 let (_, r) = div_half(rem, digit, b);
123 rem = r;
124 }
125 } else {
126 for &digit in a.data.iter().rev() {
127 let (_, r) = div_wide(rem, digit, b);
128 rem = r;
129 }
130 }
131
132 rem
133}
134
135fn sub_mul_digit_same_len(a: &mut [BigDigit], b: &[BigDigit], c: BigDigit) -> BigDigit {
139 debug_assert!(a.len() == b.len());
140
141 let mut offset_carry = big_digit::MAX;
144
145 for (x, y) in a.iter_mut().zip(b) {
146 let offset_sum = big_digit::to_doublebigdigit(big_digit::MAX, *x)
151 - big_digit::MAX as DoubleBigDigit
152 + offset_carry as DoubleBigDigit
153 - *y as DoubleBigDigit * c as DoubleBigDigit;
154
155 let (new_offset_carry, new_x) = big_digit::from_doublebigdigit(offset_sum);
156 offset_carry = new_offset_carry;
157 *x = new_x;
158 }
159
160 big_digit::MAX - offset_carry
162}
163
164fn div_rem(u: BigUint, d: BigUint) -> (BigUint, BigUint) {
165 div_rem_cow(Cow::Owned(u), Cow::Owned(d))
166}
167
168pub(super) fn div_rem_ref(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) {
169 div_rem_cow(Cow::Borrowed(u), Cow::Borrowed(d))
170}
171
172fn div_rem_cow(u: Cow<'_, BigUint>, d: Cow<'_, BigUint>) -> (BigUint, BigUint) {
173 if d.is_zero() {
174 panic!("attempt to divide by zero")
175 }
176 if u.is_zero() {
177 return (BigUint::ZERO, BigUint::ZERO);
178 }
179
180 if let [digit] = *d.data {
181 let u = u.into_owned();
182 if digit == 1 {
183 return (u, BigUint::ZERO);
184 }
185 let (div, rem) = div_rem_digit(u, digit);
186 return (div, rem.into());
187 }
188
189 match u.cmp(&d) {
191 Less => return (BigUint::ZERO, u.into_owned()),
192 Equal => return (BigUint::ONE, BigUint::ZERO),
193 Greater => {} }
195
196 let shift = d.data.last().unwrap().leading_zeros();
203
204 if shift == 0 {
205 div_rem_core(u, &d)
207 } else {
208 let u = biguint_shl(u, shift);
209 let d = biguint_shl(d, shift);
210 let (q, r) = div_rem_core(Cow::Owned(u), &d);
211 (q, r >> shift)
213 }
214}
215
216const BURNIKEL_ZIEGLER_THRESHOLD: usize = 64;
217
218fn div_rem_burnikel_ziegler(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) {
228 fn divide_biguint(mut b: BigUint, level: usize) -> (BigUint, BigUint) {
229 if b.data.len() <= level {
230 return (BigUint::ZERO, b);
231 }
232 let mut b1_data = BigDigits::from_slice(&b.data[level..]);
233 b1_data.normalize();
234 b.data.truncate(level);
235 b.data.normalize();
236 (BigUint { data: b1_data }, b)
237 }
238
239 fn normalizing_shift_amount(b: &BigUint, level: usize) -> u64 {
240 (level as u64) * u64::from(BITS) - b.bits()
241 }
242
243 fn concat_biguint(b1: &BigUint, b2: BigUint, level: usize) -> BigUint {
244 let mut data = b2.data;
245 data.reserve(level + b1.data.len() - data.len());
246 data.resize(level, 0);
247 data.extend_from_slice(&b1.data);
248 data.normalize();
249 BigUint { data }
250 }
251
252 fn div_two_digit_by_one(
253 ah: BigUint,
254 al: BigUint,
255 b: BigUint,
256 level: usize,
257 ) -> (BigUint, BigUint) {
258 debug_assert!(ah < b);
260 if level <= BURNIKEL_ZIEGLER_THRESHOLD {
261 return div_rem(concat_biguint(&ah, al, level), b);
262 }
263 let shift = normalizing_shift_amount(&b, level);
264 if shift != 0 {
265 let b = b << shift;
266 let (ah, al) = divide_biguint(concat_biguint(&ah, al, level) << shift, level);
267 let (q, r) = div_two_digit_by_one_normalized(ah, al, b, level);
268 (q, r >> shift)
269 } else {
270 div_two_digit_by_one_normalized(ah, al, b, level)
271 }
272 }
273
274 fn div_two_digit_by_one_normalized(
275 ah: BigUint,
276 al: BigUint,
277 b: BigUint,
278 level: usize,
279 ) -> (BigUint, BigUint) {
280 let level = level / 2;
281 let (a1, a2) = divide_biguint(ah, level);
282 let (a3, a4) = divide_biguint(al, level);
283 let (b1, b2) = divide_biguint(b, level);
284 let (q1, r) = div_three_halves_by_two(a1, a2, a3, b1.clone(), b2.clone(), level);
285 let (r1, r2) = divide_biguint(r, level);
286 let (q2, s) = div_three_halves_by_two(r1, r2, a4, b1, b2, level);
287 (concat_biguint(&q1, q2, level), s)
288 }
289
290 fn div_three_halves_by_two(
291 a1: BigUint,
292 a2: BigUint,
293 a3: BigUint,
294 b1: BigUint,
295 b2: BigUint,
296 level: usize,
297 ) -> (BigUint, BigUint) {
298 let (mut q, r1, d);
301 if a1 < b1 {
302 (q, r1) = div_two_digit_by_one(a1, a2, b1.clone(), level);
303 d = &q * &b2;
304 } else {
305 q = BigUint {
308 data: BigDigits::from_vec(vec![BigDigit::MAX; level]),
309 };
310 r1 = concat_biguint(&(a1 - &b1), a2, level) + &b1;
311 d = (&b2 << (level * usize::from(BITS))) - &b2;
313 };
314 let mut r = concat_biguint(&r1, a3, level);
316 if r < d {
317 let b = concat_biguint(&b1, b2, level);
318 q -= 1u32;
319 r += &b;
320 if r < d {
321 q -= 1u32;
322 r += &b;
323 }
324 }
325 (q, r - d)
326 }
327
328 let mut level = 1 << ilog2(u.data.len());
329 if d.data.len() > level {
330 level *= 2;
331 }
332 let (u1, u2) = divide_biguint(u.clone(), level);
333 if &u1 >= d {
334 div_two_digit_by_one(BigUint::ZERO, u.clone(), d.clone(), level * 2)
335 } else {
336 div_two_digit_by_one(u1, u2, d.clone(), level)
337 }
338}
339
340fn div_rem_core(a: Cow<'_, BigUint>, b: &BigUint) -> (BigUint, BigUint) {
343 if (a.data.len() > BURNIKEL_ZIEGLER_THRESHOLD * 2)
344 && (b.data.len() > BURNIKEL_ZIEGLER_THRESHOLD)
345 {
346 return div_rem_burnikel_ziegler(&a, b);
347 }
348
349 let mut a = a.into_owned();
350 let b = &*b.data;
351 debug_assert!(a.data.len() >= b.len() && b.len() > 1);
352 debug_assert!(b.last().unwrap().leading_zeros() == 0);
353
354 let mut a0 = 0;
373
374 let b0 = b[b.len() - 1];
376 let b1 = b[b.len() - 2];
377
378 let q_len = a.data.len() - b.len() + 1;
379 let mut q = BigUint {
380 data: BigDigits::from_vec(vec![0; q_len]),
381 };
382
383 for j in (0..q_len).rev() {
384 debug_assert!(a.data.len() == b.len() + j);
385
386 let a1 = *a.data.last().unwrap();
387 let a2 = a.data[a.data.len() - 2];
388
389 let (mut q0, mut r) = if a0 < b0 {
392 let (q0, r) = div_wide(a0, a1, b0);
393 (q0, r as DoubleBigDigit)
394 } else {
395 debug_assert!(a0 == b0);
396 (big_digit::MAX, a0 as DoubleBigDigit + a1 as DoubleBigDigit)
399 };
400
401 while r <= big_digit::MAX as DoubleBigDigit
410 && big_digit::to_doublebigdigit(r as BigDigit, a2)
411 < q0 as DoubleBigDigit * b1 as DoubleBigDigit
412 {
413 q0 -= 1;
414 r += b0 as DoubleBigDigit;
415 }
416
417 let mut borrow = sub_mul_digit_same_len(&mut a.data[j..], b, q0);
421 if borrow > a0 {
422 q0 -= 1;
424 borrow -= __add2(&mut a.data[j..], b);
425 }
426 debug_assert!(borrow == a0);
428
429 q.data[j] = q0;
430
431 a0 = a.data.pop().unwrap();
433 }
434
435 if a0 != 0 {
436 a.data.push(a0);
437 a.data.shrink();
438 } else {
439 a.data.normalize();
440 }
441
442 debug_assert_eq!(cmp_slice(&a.data, b), Less);
443
444 q.data.normalize();
445 (q, a)
446}
447
448forward_val_ref_binop!(impl Div for BigUint, div);
449forward_ref_val_binop!(impl Div for BigUint, div);
450forward_val_assign!(impl DivAssign for BigUint, div_assign);
451
452impl Div<BigUint> for BigUint {
453 type Output = BigUint;
454
455 #[inline]
456 fn div(self, other: BigUint) -> BigUint {
457 let (q, _) = div_rem(self, other);
458 q
459 }
460}
461
462impl Div<&BigUint> for &BigUint {
463 type Output = BigUint;
464
465 #[inline]
466 fn div(self, other: &BigUint) -> BigUint {
467 let (q, _) = self.div_rem(other);
468 q
469 }
470}
471impl DivAssign<&BigUint> for BigUint {
472 #[inline]
473 fn div_assign(&mut self, other: &BigUint) {
474 *self = &*self / other;
475 }
476}
477
478promote_unsigned_scalars!(impl Div for BigUint, div);
479promote_unsigned_scalars_assign!(impl DivAssign for BigUint, div_assign);
480forward_all_scalar_binop_to_val_val!(impl Div<u32> for BigUint, div);
481forward_all_scalar_binop_to_val_val!(impl Div<u64> for BigUint, div);
482forward_all_scalar_binop_to_val_val!(impl Div<u128> for BigUint, div);
483
484impl Div<u32> for BigUint {
485 type Output = BigUint;
486
487 #[inline]
488 fn div(self, other: u32) -> BigUint {
489 let (q, _) = div_rem_digit(self, other as BigDigit);
490 q
491 }
492}
493impl DivAssign<u32> for BigUint {
494 #[inline]
495 fn div_assign(&mut self, other: u32) {
496 *self = &*self / other;
497 }
498}
499
500impl Div<BigUint> for u32 {
501 type Output = BigUint;
502
503 #[inline]
504 fn div(self, other: BigUint) -> BigUint {
505 match *other.data {
506 [] => panic!("attempt to divide by zero"),
507 [x] => BigUint::from(self as BigDigit / x),
508 _ => BigUint::ZERO,
509 }
510 }
511}
512
513impl Div<u64> for BigUint {
514 type Output = BigUint;
515
516 #[inline]
517 fn div(self, other: u64) -> BigUint {
518 let (q, _) = div_rem(self, From::from(other));
519 q
520 }
521}
522impl DivAssign<u64> for BigUint {
523 #[inline]
524 fn div_assign(&mut self, other: u64) {
525 let temp = mem::replace(self, Self::ZERO);
527 *self = temp / other;
528 }
529}
530
531impl Div<BigUint> for u64 {
532 type Output = BigUint;
533
534 cfg_digit!(
535 #[inline]
536 fn div(self, other: BigUint) -> BigUint {
537 match *other.data {
538 [] => panic!("attempt to divide by zero"),
539 [x] => BigUint::from(self / u64::from(x)),
540 [x, y] => BigUint::from(self / big_digit::to_doublebigdigit(y, x)),
541 _ => BigUint::ZERO,
542 }
543 }
544
545 #[inline]
546 fn div(self, other: BigUint) -> BigUint {
547 match *other.data {
548 [] => panic!("attempt to divide by zero"),
549 [x] => BigUint::from(self / x),
550 _ => BigUint::ZERO,
551 }
552 }
553 );
554}
555
556impl Div<u128> for BigUint {
557 type Output = BigUint;
558
559 #[inline]
560 fn div(self, other: u128) -> BigUint {
561 let (q, _) = div_rem(self, From::from(other));
562 q
563 }
564}
565
566impl DivAssign<u128> for BigUint {
567 #[inline]
568 fn div_assign(&mut self, other: u128) {
569 *self = &*self / other;
570 }
571}
572
573impl Div<BigUint> for u128 {
574 type Output = BigUint;
575
576 cfg_digit!(
577 #[inline]
578 fn div(self, other: BigUint) -> BigUint {
579 use super::u32_to_u128;
580 match *other.data {
581 [] => panic!("attempt to divide by zero"),
582 [x] => BigUint::from(self / u128::from(x)),
583 [x, y] => BigUint::from(self / u128::from(big_digit::to_doublebigdigit(y, x))),
584 [x, y, z] => BigUint::from(self / u32_to_u128(0, z, y, x)),
585 [w, x, y, z] => BigUint::from(self / u32_to_u128(z, y, x, w)),
586 _ => BigUint::ZERO,
587 }
588 }
589
590 #[inline]
591 fn div(self, other: BigUint) -> BigUint {
592 match *other.data {
593 [] => panic!("attempt to divide by zero"),
594 [x] => BigUint::from(self / u128::from(x)),
595 [x, y] => BigUint::from(self / big_digit::to_doublebigdigit(y, x)),
596 _ => BigUint::ZERO,
597 }
598 }
599 );
600}
601
602forward_val_ref_binop!(impl Rem for BigUint, rem);
603forward_ref_val_binop!(impl Rem for BigUint, rem);
604forward_val_assign!(impl RemAssign for BigUint, rem_assign);
605
606impl Rem<BigUint> for BigUint {
607 type Output = BigUint;
608
609 #[inline]
610 fn rem(self, other: BigUint) -> BigUint {
611 if let Some(other) = other.to_u32() {
612 &self % other
613 } else {
614 let (_, r) = div_rem(self, other);
615 r
616 }
617 }
618}
619
620impl Rem<&BigUint> for &BigUint {
621 type Output = BigUint;
622
623 #[inline]
624 fn rem(self, other: &BigUint) -> BigUint {
625 if let Some(other) = other.to_u32() {
626 self % other
627 } else {
628 let (_, r) = self.div_rem(other);
629 r
630 }
631 }
632}
633impl RemAssign<&BigUint> for BigUint {
634 #[inline]
635 fn rem_assign(&mut self, other: &BigUint) {
636 *self = &*self % other;
637 }
638}
639
640promote_unsigned_scalars!(impl Rem for BigUint, rem);
641promote_unsigned_scalars_assign!(impl RemAssign for BigUint, rem_assign);
642forward_all_scalar_binop_to_ref_val!(impl Rem<u32> for BigUint, rem);
643forward_all_scalar_binop_to_val_val!(impl Rem<u64> for BigUint, rem);
644forward_all_scalar_binop_to_val_val!(impl Rem<u128> for BigUint, rem);
645
646impl Rem<u32> for &BigUint {
647 type Output = BigUint;
648
649 #[inline]
650 fn rem(self, other: u32) -> BigUint {
651 rem_digit(self, other as BigDigit).into()
652 }
653}
654impl RemAssign<u32> for BigUint {
655 #[inline]
656 fn rem_assign(&mut self, other: u32) {
657 *self = &*self % other;
658 }
659}
660
661impl Rem<&BigUint> for u32 {
662 type Output = BigUint;
663
664 #[inline]
665 fn rem(mut self, other: &BigUint) -> BigUint {
666 self %= other;
667 From::from(self)
668 }
669}
670
671macro_rules! impl_rem_assign_scalar {
672 ($scalar:ty, $to_scalar:ident) => {
673 forward_val_assign_scalar!(impl RemAssign for BigUint, $scalar, rem_assign);
674 impl RemAssign<&BigUint> for $scalar {
675 #[inline]
676 fn rem_assign(&mut self, other: &BigUint) {
677 *self = match other.$to_scalar() {
678 None => *self,
679 Some(0) => panic!("attempt to divide by zero"),
680 Some(v) => *self % v
681 };
682 }
683 }
684 }
685}
686
687impl_rem_assign_scalar!(u128, to_u128);
689impl_rem_assign_scalar!(usize, to_usize);
690impl_rem_assign_scalar!(u64, to_u64);
691impl_rem_assign_scalar!(u32, to_u32);
692impl_rem_assign_scalar!(u16, to_u16);
693impl_rem_assign_scalar!(u8, to_u8);
694impl_rem_assign_scalar!(i128, to_i128);
695impl_rem_assign_scalar!(isize, to_isize);
696impl_rem_assign_scalar!(i64, to_i64);
697impl_rem_assign_scalar!(i32, to_i32);
698impl_rem_assign_scalar!(i16, to_i16);
699impl_rem_assign_scalar!(i8, to_i8);
700
701impl Rem<u64> for BigUint {
702 type Output = BigUint;
703
704 #[inline]
705 fn rem(self, other: u64) -> BigUint {
706 let (_, r) = div_rem(self, From::from(other));
707 r
708 }
709}
710impl RemAssign<u64> for BigUint {
711 #[inline]
712 fn rem_assign(&mut self, other: u64) {
713 *self = &*self % other;
714 }
715}
716
717impl Rem<BigUint> for u64 {
718 type Output = BigUint;
719
720 #[inline]
721 fn rem(mut self, other: BigUint) -> BigUint {
722 self %= other;
723 From::from(self)
724 }
725}
726
727impl Rem<u128> for BigUint {
728 type Output = BigUint;
729
730 #[inline]
731 fn rem(self, other: u128) -> BigUint {
732 let (_, r) = div_rem(self, From::from(other));
733 r
734 }
735}
736
737impl RemAssign<u128> for BigUint {
738 #[inline]
739 fn rem_assign(&mut self, other: u128) {
740 *self = &*self % other;
741 }
742}
743
744impl Rem<BigUint> for u128 {
745 type Output = BigUint;
746
747 #[inline]
748 fn rem(mut self, other: BigUint) -> BigUint {
749 self %= other;
750 From::from(self)
751 }
752}
753
754impl CheckedDiv for BigUint {
755 #[inline]
756 fn checked_div(&self, v: &BigUint) -> Option<BigUint> {
757 if v.is_zero() {
758 return None;
759 }
760 Some(self.div(v))
761 }
762}
763
764impl CheckedEuclid for BigUint {
765 #[inline]
766 fn checked_div_euclid(&self, v: &BigUint) -> Option<BigUint> {
767 if v.is_zero() {
768 return None;
769 }
770 Some(self.div_euclid(v))
771 }
772
773 #[inline]
774 fn checked_rem_euclid(&self, v: &BigUint) -> Option<BigUint> {
775 if v.is_zero() {
776 return None;
777 }
778 Some(self.rem_euclid(v))
779 }
780
781 fn checked_div_rem_euclid(&self, v: &Self) -> Option<(Self, Self)> {
782 Some(self.div_rem_euclid(v))
783 }
784}
785
786impl Euclid for BigUint {
787 #[inline]
788 fn div_euclid(&self, v: &BigUint) -> BigUint {
789 self / v
791 }
792
793 #[inline]
794 fn rem_euclid(&self, v: &BigUint) -> BigUint {
795 self % v
797 }
798
799 fn div_rem_euclid(&self, v: &Self) -> (Self, Self) {
800 self.div_rem(v)
802 }
803}