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, c) = div_two_digit_by_one(a1, a2, b1.clone(), level);
299 let (mut r, rsub) = (concat_biguint(&c, a3, level), &q * &b2);
300 if r < rsub {
302 let b = concat_biguint(&b1, b2, level);
303 q -= 1u32;
304 r += &b;
305 if r < rsub {
306 q -= 1u32;
307 r += &b;
308 }
309 }
310 (q, r - rsub)
311 }
312
313 let mut level = 1 << ilog2(u.data.len());
314 if d.data.len() > level {
315 level *= 2;
316 }
317 let (u1, u2) = divide_biguint(u.clone(), level);
318 if &u1 >= d {
319 div_two_digit_by_one(BigUint::ZERO, u.clone(), d.clone(), level * 2)
320 } else {
321 div_two_digit_by_one(u1, u2, d.clone(), level)
322 }
323}
324
325fn div_rem_core(a: Cow<'_, BigUint>, b: &BigUint) -> (BigUint, BigUint) {
328 if (a.data.len() > BURNIKEL_ZIEGLER_THRESHOLD * 2)
329 && (b.data.len() > BURNIKEL_ZIEGLER_THRESHOLD)
330 {
331 return div_rem_burnikel_ziegler(&a, b);
332 }
333
334 let mut a = a.into_owned();
335 let b = &*b.data;
336 debug_assert!(a.data.len() >= b.len() && b.len() > 1);
337 debug_assert!(b.last().unwrap().leading_zeros() == 0);
338
339 let mut a0 = 0;
358
359 let b0 = b[b.len() - 1];
361 let b1 = b[b.len() - 2];
362
363 let q_len = a.data.len() - b.len() + 1;
364 let mut q = BigUint {
365 data: BigDigits::from_vec(vec![0; q_len]),
366 };
367
368 for j in (0..q_len).rev() {
369 debug_assert!(a.data.len() == b.len() + j);
370
371 let a1 = *a.data.last().unwrap();
372 let a2 = a.data[a.data.len() - 2];
373
374 let (mut q0, mut r) = if a0 < b0 {
377 let (q0, r) = div_wide(a0, a1, b0);
378 (q0, r as DoubleBigDigit)
379 } else {
380 debug_assert!(a0 == b0);
381 (big_digit::MAX, a0 as DoubleBigDigit + a1 as DoubleBigDigit)
384 };
385
386 while r <= big_digit::MAX as DoubleBigDigit
395 && big_digit::to_doublebigdigit(r as BigDigit, a2)
396 < q0 as DoubleBigDigit * b1 as DoubleBigDigit
397 {
398 q0 -= 1;
399 r += b0 as DoubleBigDigit;
400 }
401
402 let mut borrow = sub_mul_digit_same_len(&mut a.data[j..], b, q0);
406 if borrow > a0 {
407 q0 -= 1;
409 borrow -= __add2(&mut a.data[j..], b);
410 }
411 debug_assert!(borrow == a0);
413
414 q.data[j] = q0;
415
416 a0 = a.data.pop().unwrap();
418 }
419
420 if a0 != 0 {
421 a.data.push(a0);
422 a.data.shrink();
423 } else {
424 a.data.normalize();
425 }
426
427 debug_assert_eq!(cmp_slice(&a.data, b), Less);
428
429 q.data.normalize();
430 (q, a)
431}
432
433forward_val_ref_binop!(impl Div for BigUint, div);
434forward_ref_val_binop!(impl Div for BigUint, div);
435forward_val_assign!(impl DivAssign for BigUint, div_assign);
436
437impl Div<BigUint> for BigUint {
438 type Output = BigUint;
439
440 #[inline]
441 fn div(self, other: BigUint) -> BigUint {
442 let (q, _) = div_rem(self, other);
443 q
444 }
445}
446
447impl Div<&BigUint> for &BigUint {
448 type Output = BigUint;
449
450 #[inline]
451 fn div(self, other: &BigUint) -> BigUint {
452 let (q, _) = self.div_rem(other);
453 q
454 }
455}
456impl DivAssign<&BigUint> for BigUint {
457 #[inline]
458 fn div_assign(&mut self, other: &BigUint) {
459 *self = &*self / other;
460 }
461}
462
463promote_unsigned_scalars!(impl Div for BigUint, div);
464promote_unsigned_scalars_assign!(impl DivAssign for BigUint, div_assign);
465forward_all_scalar_binop_to_val_val!(impl Div<u32> for BigUint, div);
466forward_all_scalar_binop_to_val_val!(impl Div<u64> for BigUint, div);
467forward_all_scalar_binop_to_val_val!(impl Div<u128> for BigUint, div);
468
469impl Div<u32> for BigUint {
470 type Output = BigUint;
471
472 #[inline]
473 fn div(self, other: u32) -> BigUint {
474 let (q, _) = div_rem_digit(self, other as BigDigit);
475 q
476 }
477}
478impl DivAssign<u32> for BigUint {
479 #[inline]
480 fn div_assign(&mut self, other: u32) {
481 *self = &*self / other;
482 }
483}
484
485impl Div<BigUint> for u32 {
486 type Output = BigUint;
487
488 #[inline]
489 fn div(self, other: BigUint) -> BigUint {
490 match *other.data {
491 [] => panic!("attempt to divide by zero"),
492 [x] => BigUint::from(self as BigDigit / x),
493 _ => BigUint::ZERO,
494 }
495 }
496}
497
498impl Div<u64> for BigUint {
499 type Output = BigUint;
500
501 #[inline]
502 fn div(self, other: u64) -> BigUint {
503 let (q, _) = div_rem(self, From::from(other));
504 q
505 }
506}
507impl DivAssign<u64> for BigUint {
508 #[inline]
509 fn div_assign(&mut self, other: u64) {
510 let temp = mem::replace(self, Self::ZERO);
512 *self = temp / other;
513 }
514}
515
516impl Div<BigUint> for u64 {
517 type Output = BigUint;
518
519 cfg_digit!(
520 #[inline]
521 fn div(self, other: BigUint) -> BigUint {
522 match *other.data {
523 [] => panic!("attempt to divide by zero"),
524 [x] => BigUint::from(self / u64::from(x)),
525 [x, y] => BigUint::from(self / big_digit::to_doublebigdigit(y, x)),
526 _ => BigUint::ZERO,
527 }
528 }
529
530 #[inline]
531 fn div(self, other: BigUint) -> BigUint {
532 match *other.data {
533 [] => panic!("attempt to divide by zero"),
534 [x] => BigUint::from(self / x),
535 _ => BigUint::ZERO,
536 }
537 }
538 );
539}
540
541impl Div<u128> for BigUint {
542 type Output = BigUint;
543
544 #[inline]
545 fn div(self, other: u128) -> BigUint {
546 let (q, _) = div_rem(self, From::from(other));
547 q
548 }
549}
550
551impl DivAssign<u128> for BigUint {
552 #[inline]
553 fn div_assign(&mut self, other: u128) {
554 *self = &*self / other;
555 }
556}
557
558impl Div<BigUint> for u128 {
559 type Output = BigUint;
560
561 cfg_digit!(
562 #[inline]
563 fn div(self, other: BigUint) -> BigUint {
564 use super::u32_to_u128;
565 match *other.data {
566 [] => panic!("attempt to divide by zero"),
567 [x] => BigUint::from(self / u128::from(x)),
568 [x, y] => BigUint::from(self / u128::from(big_digit::to_doublebigdigit(y, x))),
569 [x, y, z] => BigUint::from(self / u32_to_u128(0, z, y, x)),
570 [w, x, y, z] => BigUint::from(self / u32_to_u128(z, y, x, w)),
571 _ => BigUint::ZERO,
572 }
573 }
574
575 #[inline]
576 fn div(self, other: BigUint) -> BigUint {
577 match *other.data {
578 [] => panic!("attempt to divide by zero"),
579 [x] => BigUint::from(self / u128::from(x)),
580 [x, y] => BigUint::from(self / big_digit::to_doublebigdigit(y, x)),
581 _ => BigUint::ZERO,
582 }
583 }
584 );
585}
586
587forward_val_ref_binop!(impl Rem for BigUint, rem);
588forward_ref_val_binop!(impl Rem for BigUint, rem);
589forward_val_assign!(impl RemAssign for BigUint, rem_assign);
590
591impl Rem<BigUint> for BigUint {
592 type Output = BigUint;
593
594 #[inline]
595 fn rem(self, other: BigUint) -> BigUint {
596 if let Some(other) = other.to_u32() {
597 &self % other
598 } else {
599 let (_, r) = div_rem(self, other);
600 r
601 }
602 }
603}
604
605impl Rem<&BigUint> for &BigUint {
606 type Output = BigUint;
607
608 #[inline]
609 fn rem(self, other: &BigUint) -> BigUint {
610 if let Some(other) = other.to_u32() {
611 self % other
612 } else {
613 let (_, r) = self.div_rem(other);
614 r
615 }
616 }
617}
618impl RemAssign<&BigUint> for BigUint {
619 #[inline]
620 fn rem_assign(&mut self, other: &BigUint) {
621 *self = &*self % other;
622 }
623}
624
625promote_unsigned_scalars!(impl Rem for BigUint, rem);
626promote_unsigned_scalars_assign!(impl RemAssign for BigUint, rem_assign);
627forward_all_scalar_binop_to_ref_val!(impl Rem<u32> for BigUint, rem);
628forward_all_scalar_binop_to_val_val!(impl Rem<u64> for BigUint, rem);
629forward_all_scalar_binop_to_val_val!(impl Rem<u128> for BigUint, rem);
630
631impl Rem<u32> for &BigUint {
632 type Output = BigUint;
633
634 #[inline]
635 fn rem(self, other: u32) -> BigUint {
636 rem_digit(self, other as BigDigit).into()
637 }
638}
639impl RemAssign<u32> for BigUint {
640 #[inline]
641 fn rem_assign(&mut self, other: u32) {
642 *self = &*self % other;
643 }
644}
645
646impl Rem<&BigUint> for u32 {
647 type Output = BigUint;
648
649 #[inline]
650 fn rem(mut self, other: &BigUint) -> BigUint {
651 self %= other;
652 From::from(self)
653 }
654}
655
656macro_rules! impl_rem_assign_scalar {
657 ($scalar:ty, $to_scalar:ident) => {
658 forward_val_assign_scalar!(impl RemAssign for BigUint, $scalar, rem_assign);
659 impl RemAssign<&BigUint> for $scalar {
660 #[inline]
661 fn rem_assign(&mut self, other: &BigUint) {
662 *self = match other.$to_scalar() {
663 None => *self,
664 Some(0) => panic!("attempt to divide by zero"),
665 Some(v) => *self % v
666 };
667 }
668 }
669 }
670}
671
672impl_rem_assign_scalar!(u128, to_u128);
674impl_rem_assign_scalar!(usize, to_usize);
675impl_rem_assign_scalar!(u64, to_u64);
676impl_rem_assign_scalar!(u32, to_u32);
677impl_rem_assign_scalar!(u16, to_u16);
678impl_rem_assign_scalar!(u8, to_u8);
679impl_rem_assign_scalar!(i128, to_i128);
680impl_rem_assign_scalar!(isize, to_isize);
681impl_rem_assign_scalar!(i64, to_i64);
682impl_rem_assign_scalar!(i32, to_i32);
683impl_rem_assign_scalar!(i16, to_i16);
684impl_rem_assign_scalar!(i8, to_i8);
685
686impl Rem<u64> for BigUint {
687 type Output = BigUint;
688
689 #[inline]
690 fn rem(self, other: u64) -> BigUint {
691 let (_, r) = div_rem(self, From::from(other));
692 r
693 }
694}
695impl RemAssign<u64> for BigUint {
696 #[inline]
697 fn rem_assign(&mut self, other: u64) {
698 *self = &*self % other;
699 }
700}
701
702impl Rem<BigUint> for u64 {
703 type Output = BigUint;
704
705 #[inline]
706 fn rem(mut self, other: BigUint) -> BigUint {
707 self %= other;
708 From::from(self)
709 }
710}
711
712impl Rem<u128> for BigUint {
713 type Output = BigUint;
714
715 #[inline]
716 fn rem(self, other: u128) -> BigUint {
717 let (_, r) = div_rem(self, From::from(other));
718 r
719 }
720}
721
722impl RemAssign<u128> for BigUint {
723 #[inline]
724 fn rem_assign(&mut self, other: u128) {
725 *self = &*self % other;
726 }
727}
728
729impl Rem<BigUint> for u128 {
730 type Output = BigUint;
731
732 #[inline]
733 fn rem(mut self, other: BigUint) -> BigUint {
734 self %= other;
735 From::from(self)
736 }
737}
738
739impl CheckedDiv for BigUint {
740 #[inline]
741 fn checked_div(&self, v: &BigUint) -> Option<BigUint> {
742 if v.is_zero() {
743 return None;
744 }
745 Some(self.div(v))
746 }
747}
748
749impl CheckedEuclid for BigUint {
750 #[inline]
751 fn checked_div_euclid(&self, v: &BigUint) -> Option<BigUint> {
752 if v.is_zero() {
753 return None;
754 }
755 Some(self.div_euclid(v))
756 }
757
758 #[inline]
759 fn checked_rem_euclid(&self, v: &BigUint) -> Option<BigUint> {
760 if v.is_zero() {
761 return None;
762 }
763 Some(self.rem_euclid(v))
764 }
765
766 fn checked_div_rem_euclid(&self, v: &Self) -> Option<(Self, Self)> {
767 Some(self.div_rem_euclid(v))
768 }
769}
770
771impl Euclid for BigUint {
772 #[inline]
773 fn div_euclid(&self, v: &BigUint) -> BigUint {
774 self / v
776 }
777
778 #[inline]
779 fn rem_euclid(&self, v: &BigUint) -> BigUint {
780 self % v
782 }
783
784 fn div_rem_euclid(&self, v: &Self) -> (Self, Self) {
785 self.div_rem(v)
787 }
788}