1use super::addition::__add2;
2use super::{cmp_slice, BigUint};
3
4use crate::big_digit::{self, BigDigit, DoubleBigDigit};
5use crate::UsizePromotion;
6
7use core::cmp::Ordering::{Equal, Greater, Less};
8use core::mem;
9use core::ops::{Div, DivAssign, Rem, RemAssign};
10use num_integer::Integer;
11use num_traits::{CheckedDiv, CheckedEuclid, Euclid, One, ToPrimitive, Zero};
12
13pub(super) const FAST_DIV_WIDE: bool = cfg!(any(target_arch = "x86", target_arch = "x86_64"));
14
15#[cfg(any(miri, not(any(target_arch = "x86", target_arch = "x86_64"))))]
22#[inline]
23fn div_wide(hi: BigDigit, lo: BigDigit, divisor: BigDigit) -> (BigDigit, BigDigit) {
24 debug_assert!(hi < divisor);
25
26 let lhs = big_digit::to_doublebigdigit(hi, lo);
27 let rhs = DoubleBigDigit::from(divisor);
28 ((lhs / rhs) as BigDigit, (lhs % rhs) as BigDigit)
29}
30
31#[cfg(all(not(miri), any(target_arch = "x86", target_arch = "x86_64")))]
33#[inline]
34fn div_wide(hi: BigDigit, lo: BigDigit, divisor: BigDigit) -> (BigDigit, BigDigit) {
35 debug_assert!(hi < divisor);
39
40 unsafe {
45 let (div, rem);
46
47 cfg_digit!(
48 macro_rules! div {
49 () => {
50 "div {0:e}"
51 };
52 }
53 macro_rules! div {
54 () => {
55 "div {0:r}"
56 };
57 }
58 );
59
60 core::arch::asm!(
61 div!(),
62 in(reg) divisor,
63 inout("dx") hi => rem,
64 inout("ax") lo => div,
65 options(pure, nomem, nostack),
66 );
67
68 (div, rem)
69 }
70}
71
72#[inline]
75fn div_half(rem: BigDigit, digit: BigDigit, divisor: BigDigit) -> (BigDigit, BigDigit) {
76 use crate::big_digit::{HALF, HALF_BITS};
77
78 debug_assert!(rem < divisor && divisor <= HALF);
79 let (hi, rem) = ((rem << HALF_BITS) | (digit >> HALF_BITS)).div_rem(&divisor);
80 let (lo, rem) = ((rem << HALF_BITS) | (digit & HALF)).div_rem(&divisor);
81 ((hi << HALF_BITS) | lo, rem)
82}
83
84#[inline]
85pub(super) fn div_rem_digit(mut a: BigUint, b: BigDigit) -> (BigUint, BigDigit) {
86 if b == 0 {
87 panic!("attempt to divide by zero")
88 }
89
90 let mut rem = 0;
91
92 if !FAST_DIV_WIDE && b <= big_digit::HALF {
93 for d in a.data.iter_mut().rev() {
94 let (q, r) = div_half(rem, *d, b);
95 *d = q;
96 rem = r;
97 }
98 } else {
99 for d in a.data.iter_mut().rev() {
100 let (q, r) = div_wide(rem, *d, b);
101 *d = q;
102 rem = r;
103 }
104 }
105
106 (a.normalized(), rem)
107}
108
109#[inline]
110fn rem_digit(a: &BigUint, b: BigDigit) -> BigDigit {
111 if b == 0 {
112 panic!("attempt to divide by zero")
113 }
114
115 let mut rem = 0;
116
117 if !FAST_DIV_WIDE && b <= big_digit::HALF {
118 for &digit in a.data.iter().rev() {
119 let (_, r) = div_half(rem, digit, b);
120 rem = r;
121 }
122 } else {
123 for &digit in a.data.iter().rev() {
124 let (_, r) = div_wide(rem, digit, b);
125 rem = r;
126 }
127 }
128
129 rem
130}
131
132fn sub_mul_digit_same_len(a: &mut [BigDigit], b: &[BigDigit], c: BigDigit) -> BigDigit {
136 debug_assert!(a.len() == b.len());
137
138 let mut offset_carry = big_digit::MAX;
141
142 for (x, y) in a.iter_mut().zip(b) {
143 let offset_sum = big_digit::to_doublebigdigit(big_digit::MAX, *x)
148 - big_digit::MAX as DoubleBigDigit
149 + offset_carry as DoubleBigDigit
150 - *y as DoubleBigDigit * c as DoubleBigDigit;
151
152 let (new_offset_carry, new_x) = big_digit::from_doublebigdigit(offset_sum);
153 offset_carry = new_offset_carry;
154 *x = new_x;
155 }
156
157 big_digit::MAX - offset_carry
159}
160
161fn div_rem(mut u: BigUint, mut d: BigUint) -> (BigUint, BigUint) {
162 if d.is_zero() {
163 panic!("attempt to divide by zero")
164 }
165 if u.is_zero() {
166 return (BigUint::ZERO, BigUint::ZERO);
167 }
168
169 if d.data.len() == 1 {
170 if d.data == [1] {
171 return (u, BigUint::ZERO);
172 }
173 let (div, rem) = div_rem_digit(u, d.data[0]);
174 d.data.clear();
176 d += rem;
177 return (div, d);
178 }
179
180 match u.cmp(&d) {
182 Less => return (BigUint::ZERO, u),
183 Equal => {
184 u.set_one();
185 return (u, BigUint::ZERO);
186 }
187 Greater => {} }
189
190 let shift = d.data.last().unwrap().leading_zeros() as usize;
197
198 if shift == 0 {
199 div_rem_core(u, &d.data)
201 } else {
202 let (q, r) = div_rem_core(u << shift, &(d << shift).data);
203 (q, r >> shift)
205 }
206}
207
208pub(super) fn div_rem_ref(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) {
209 if d.is_zero() {
210 panic!("attempt to divide by zero")
211 }
212 if u.is_zero() {
213 return (BigUint::ZERO, BigUint::ZERO);
214 }
215
216 if d.data.len() == 1 {
217 if d.data == [1] {
218 return (u.clone(), BigUint::ZERO);
219 }
220
221 let (div, rem) = div_rem_digit(u.clone(), d.data[0]);
222 return (div, rem.into());
223 }
224
225 match u.cmp(d) {
227 Less => return (BigUint::ZERO, u.clone()),
228 Equal => return (One::one(), BigUint::ZERO),
229 Greater => {} }
231
232 let shift = d.data.last().unwrap().leading_zeros() as usize;
239
240 if shift == 0 {
241 div_rem_core(u.clone(), &d.data)
243 } else {
244 let (q, r) = div_rem_core(u << shift, &(d << shift).data);
245 (q, r >> shift)
247 }
248}
249
250fn div_rem_core(mut a: BigUint, b: &[BigDigit]) -> (BigUint, BigUint) {
253 debug_assert!(a.data.len() >= b.len() && b.len() > 1);
254 debug_assert!(b.last().unwrap().leading_zeros() == 0);
255
256 let mut a0 = 0;
275
276 let b0 = b[b.len() - 1];
278 let b1 = b[b.len() - 2];
279
280 let q_len = a.data.len() - b.len() + 1;
281 let mut q = BigUint {
282 data: vec![0; q_len],
283 };
284
285 for j in (0..q_len).rev() {
286 debug_assert!(a.data.len() == b.len() + j);
287
288 let a1 = *a.data.last().unwrap();
289 let a2 = a.data[a.data.len() - 2];
290
291 let (mut q0, mut r) = if a0 < b0 {
294 let (q0, r) = div_wide(a0, a1, b0);
295 (q0, r as DoubleBigDigit)
296 } else {
297 debug_assert!(a0 == b0);
298 (big_digit::MAX, a0 as DoubleBigDigit + a1 as DoubleBigDigit)
301 };
302
303 while r <= big_digit::MAX as DoubleBigDigit
312 && big_digit::to_doublebigdigit(r as BigDigit, a2)
313 < q0 as DoubleBigDigit * b1 as DoubleBigDigit
314 {
315 q0 -= 1;
316 r += b0 as DoubleBigDigit;
317 }
318
319 let mut borrow = sub_mul_digit_same_len(&mut a.data[j..], b, q0);
323 if borrow > a0 {
324 q0 -= 1;
326 borrow -= __add2(&mut a.data[j..], b);
327 }
328 debug_assert!(borrow == a0);
330
331 q.data[j] = q0;
332
333 a0 = a.data.pop().unwrap();
335 }
336
337 a.data.push(a0);
338 a.normalize();
339
340 debug_assert_eq!(cmp_slice(&a.data, b), Less);
341
342 (q.normalized(), a)
343}
344
345forward_val_ref_binop!(impl Div for BigUint, div);
346forward_ref_val_binop!(impl Div for BigUint, div);
347forward_val_assign!(impl DivAssign for BigUint, div_assign);
348
349impl Div<BigUint> for BigUint {
350 type Output = BigUint;
351
352 #[inline]
353 fn div(self, other: BigUint) -> BigUint {
354 let (q, _) = div_rem(self, other);
355 q
356 }
357}
358
359impl Div<&BigUint> for &BigUint {
360 type Output = BigUint;
361
362 #[inline]
363 fn div(self, other: &BigUint) -> BigUint {
364 let (q, _) = self.div_rem(other);
365 q
366 }
367}
368impl DivAssign<&BigUint> for BigUint {
369 #[inline]
370 fn div_assign(&mut self, other: &BigUint) {
371 *self = &*self / other;
372 }
373}
374
375promote_unsigned_scalars!(impl Div for BigUint, div);
376promote_unsigned_scalars_assign!(impl DivAssign for BigUint, div_assign);
377forward_all_scalar_binop_to_val_val!(impl Div<u32> for BigUint, div);
378forward_all_scalar_binop_to_val_val!(impl Div<u64> for BigUint, div);
379forward_all_scalar_binop_to_val_val!(impl Div<u128> for BigUint, div);
380
381impl Div<u32> for BigUint {
382 type Output = BigUint;
383
384 #[inline]
385 fn div(self, other: u32) -> BigUint {
386 let (q, _) = div_rem_digit(self, other as BigDigit);
387 q
388 }
389}
390impl DivAssign<u32> for BigUint {
391 #[inline]
392 fn div_assign(&mut self, other: u32) {
393 *self = &*self / other;
394 }
395}
396
397impl Div<BigUint> for u32 {
398 type Output = BigUint;
399
400 #[inline]
401 fn div(self, other: BigUint) -> BigUint {
402 match other.data.len() {
403 0 => panic!("attempt to divide by zero"),
404 1 => From::from(self as BigDigit / other.data[0]),
405 _ => BigUint::ZERO,
406 }
407 }
408}
409
410impl Div<u64> for BigUint {
411 type Output = BigUint;
412
413 #[inline]
414 fn div(self, other: u64) -> BigUint {
415 let (q, _) = div_rem(self, From::from(other));
416 q
417 }
418}
419impl DivAssign<u64> for BigUint {
420 #[inline]
421 fn div_assign(&mut self, other: u64) {
422 let temp = mem::replace(self, Self::ZERO);
424 *self = temp / other;
425 }
426}
427
428impl Div<BigUint> for u64 {
429 type Output = BigUint;
430
431 cfg_digit!(
432 #[inline]
433 fn div(self, other: BigUint) -> BigUint {
434 match other.data.len() {
435 0 => panic!("attempt to divide by zero"),
436 1 => From::from(self / u64::from(other.data[0])),
437 2 => From::from(self / big_digit::to_doublebigdigit(other.data[1], other.data[0])),
438 _ => BigUint::ZERO,
439 }
440 }
441
442 #[inline]
443 fn div(self, other: BigUint) -> BigUint {
444 match other.data.len() {
445 0 => panic!("attempt to divide by zero"),
446 1 => From::from(self / other.data[0]),
447 _ => BigUint::ZERO,
448 }
449 }
450 );
451}
452
453impl Div<u128> for BigUint {
454 type Output = BigUint;
455
456 #[inline]
457 fn div(self, other: u128) -> BigUint {
458 let (q, _) = div_rem(self, From::from(other));
459 q
460 }
461}
462
463impl DivAssign<u128> for BigUint {
464 #[inline]
465 fn div_assign(&mut self, other: u128) {
466 *self = &*self / other;
467 }
468}
469
470impl Div<BigUint> for u128 {
471 type Output = BigUint;
472
473 cfg_digit!(
474 #[inline]
475 fn div(self, other: BigUint) -> BigUint {
476 use super::u32_to_u128;
477 match other.data.len() {
478 0 => panic!("attempt to divide by zero"),
479 1 => From::from(self / u128::from(other.data[0])),
480 2 => From::from(
481 self / u128::from(big_digit::to_doublebigdigit(other.data[1], other.data[0])),
482 ),
483 3 => From::from(self / u32_to_u128(0, other.data[2], other.data[1], other.data[0])),
484 4 => From::from(
485 self / u32_to_u128(other.data[3], other.data[2], other.data[1], other.data[0]),
486 ),
487 _ => BigUint::ZERO,
488 }
489 }
490
491 #[inline]
492 fn div(self, other: BigUint) -> BigUint {
493 match other.data.len() {
494 0 => panic!("attempt to divide by zero"),
495 1 => From::from(self / other.data[0] as u128),
496 2 => From::from(self / big_digit::to_doublebigdigit(other.data[1], other.data[0])),
497 _ => BigUint::ZERO,
498 }
499 }
500 );
501}
502
503forward_val_ref_binop!(impl Rem for BigUint, rem);
504forward_ref_val_binop!(impl Rem for BigUint, rem);
505forward_val_assign!(impl RemAssign for BigUint, rem_assign);
506
507impl Rem<BigUint> for BigUint {
508 type Output = BigUint;
509
510 #[inline]
511 fn rem(self, other: BigUint) -> BigUint {
512 if let Some(other) = other.to_u32() {
513 &self % other
514 } else {
515 let (_, r) = div_rem(self, other);
516 r
517 }
518 }
519}
520
521impl Rem<&BigUint> for &BigUint {
522 type Output = BigUint;
523
524 #[inline]
525 fn rem(self, other: &BigUint) -> BigUint {
526 if let Some(other) = other.to_u32() {
527 self % other
528 } else {
529 let (_, r) = self.div_rem(other);
530 r
531 }
532 }
533}
534impl RemAssign<&BigUint> for BigUint {
535 #[inline]
536 fn rem_assign(&mut self, other: &BigUint) {
537 *self = &*self % other;
538 }
539}
540
541promote_unsigned_scalars!(impl Rem for BigUint, rem);
542promote_unsigned_scalars_assign!(impl RemAssign for BigUint, rem_assign);
543forward_all_scalar_binop_to_ref_val!(impl Rem<u32> for BigUint, rem);
544forward_all_scalar_binop_to_val_val!(impl Rem<u64> for BigUint, rem);
545forward_all_scalar_binop_to_val_val!(impl Rem<u128> for BigUint, rem);
546
547impl Rem<u32> for &BigUint {
548 type Output = BigUint;
549
550 #[inline]
551 fn rem(self, other: u32) -> BigUint {
552 rem_digit(self, other as BigDigit).into()
553 }
554}
555impl RemAssign<u32> for BigUint {
556 #[inline]
557 fn rem_assign(&mut self, other: u32) {
558 *self = &*self % other;
559 }
560}
561
562impl Rem<&BigUint> for u32 {
563 type Output = BigUint;
564
565 #[inline]
566 fn rem(mut self, other: &BigUint) -> BigUint {
567 self %= other;
568 From::from(self)
569 }
570}
571
572macro_rules! impl_rem_assign_scalar {
573 ($scalar:ty, $to_scalar:ident) => {
574 forward_val_assign_scalar!(impl RemAssign for BigUint, $scalar, rem_assign);
575 impl RemAssign<&BigUint> for $scalar {
576 #[inline]
577 fn rem_assign(&mut self, other: &BigUint) {
578 *self = match other.$to_scalar() {
579 None => *self,
580 Some(0) => panic!("attempt to divide by zero"),
581 Some(v) => *self % v
582 };
583 }
584 }
585 }
586}
587
588impl_rem_assign_scalar!(u128, to_u128);
590impl_rem_assign_scalar!(usize, to_usize);
591impl_rem_assign_scalar!(u64, to_u64);
592impl_rem_assign_scalar!(u32, to_u32);
593impl_rem_assign_scalar!(u16, to_u16);
594impl_rem_assign_scalar!(u8, to_u8);
595impl_rem_assign_scalar!(i128, to_i128);
596impl_rem_assign_scalar!(isize, to_isize);
597impl_rem_assign_scalar!(i64, to_i64);
598impl_rem_assign_scalar!(i32, to_i32);
599impl_rem_assign_scalar!(i16, to_i16);
600impl_rem_assign_scalar!(i8, to_i8);
601
602impl Rem<u64> for BigUint {
603 type Output = BigUint;
604
605 #[inline]
606 fn rem(self, other: u64) -> BigUint {
607 let (_, r) = div_rem(self, From::from(other));
608 r
609 }
610}
611impl RemAssign<u64> for BigUint {
612 #[inline]
613 fn rem_assign(&mut self, other: u64) {
614 *self = &*self % other;
615 }
616}
617
618impl Rem<BigUint> for u64 {
619 type Output = BigUint;
620
621 #[inline]
622 fn rem(mut self, other: BigUint) -> BigUint {
623 self %= other;
624 From::from(self)
625 }
626}
627
628impl Rem<u128> for BigUint {
629 type Output = BigUint;
630
631 #[inline]
632 fn rem(self, other: u128) -> BigUint {
633 let (_, r) = div_rem(self, From::from(other));
634 r
635 }
636}
637
638impl RemAssign<u128> for BigUint {
639 #[inline]
640 fn rem_assign(&mut self, other: u128) {
641 *self = &*self % other;
642 }
643}
644
645impl Rem<BigUint> for u128 {
646 type Output = BigUint;
647
648 #[inline]
649 fn rem(mut self, other: BigUint) -> BigUint {
650 self %= other;
651 From::from(self)
652 }
653}
654
655impl CheckedDiv for BigUint {
656 #[inline]
657 fn checked_div(&self, v: &BigUint) -> Option<BigUint> {
658 if v.is_zero() {
659 return None;
660 }
661 Some(self.div(v))
662 }
663}
664
665impl CheckedEuclid for BigUint {
666 #[inline]
667 fn checked_div_euclid(&self, v: &BigUint) -> Option<BigUint> {
668 if v.is_zero() {
669 return None;
670 }
671 Some(self.div_euclid(v))
672 }
673
674 #[inline]
675 fn checked_rem_euclid(&self, v: &BigUint) -> Option<BigUint> {
676 if v.is_zero() {
677 return None;
678 }
679 Some(self.rem_euclid(v))
680 }
681
682 fn checked_div_rem_euclid(&self, v: &Self) -> Option<(Self, Self)> {
683 Some(self.div_rem_euclid(v))
684 }
685}
686
687impl Euclid for BigUint {
688 #[inline]
689 fn div_euclid(&self, v: &BigUint) -> BigUint {
690 self / v
692 }
693
694 #[inline]
695 fn rem_euclid(&self, v: &BigUint) -> BigUint {
696 self % v
698 }
699
700 fn div_rem_euclid(&self, v: &Self) -> (Self, Self) {
701 self.div_rem(v)
703 }
704}