1use super::addition::__add2;
2#[cfg(not(u64_digit))]
3use super::u32_to_u128;
4use super::{cmp_slice, BigUint};
5
6use crate::big_digit::{self, BigDigit, DoubleBigDigit};
7use crate::UsizePromotion;
8
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, One, ToPrimitive, Zero};
14
15#[inline]
22fn div_wide(hi: BigDigit, lo: BigDigit, divisor: BigDigit) -> (BigDigit, BigDigit) {
23 debug_assert!(hi < divisor);
24
25 let lhs = big_digit::to_doublebigdigit(hi, lo);
26 let rhs = DoubleBigDigit::from(divisor);
27 ((lhs / rhs) as BigDigit, (lhs % rhs) as BigDigit)
28}
29
30#[inline]
33fn div_half(rem: BigDigit, digit: BigDigit, divisor: BigDigit) -> (BigDigit, BigDigit) {
34 use crate::big_digit::{HALF, HALF_BITS};
35
36 debug_assert!(rem < divisor && divisor <= HALF);
37 let (hi, rem) = ((rem << HALF_BITS) | (digit >> HALF_BITS)).div_rem(&divisor);
38 let (lo, rem) = ((rem << HALF_BITS) | (digit & HALF)).div_rem(&divisor);
39 ((hi << HALF_BITS) | lo, rem)
40}
41
42#[inline]
43pub(super) fn div_rem_digit(mut a: BigUint, b: BigDigit) -> (BigUint, BigDigit) {
44 if b == 0 {
45 panic!("attempt to divide by zero")
46 }
47
48 let mut rem = 0;
49
50 if b <= big_digit::HALF {
51 for d in a.data.iter_mut().rev() {
52 let (q, r) = div_half(rem, *d, b);
53 *d = q;
54 rem = r;
55 }
56 } else {
57 for d in a.data.iter_mut().rev() {
58 let (q, r) = div_wide(rem, *d, b);
59 *d = q;
60 rem = r;
61 }
62 }
63
64 (a.normalized(), rem)
65}
66
67#[inline]
68fn rem_digit(a: &BigUint, b: BigDigit) -> BigDigit {
69 if b == 0 {
70 panic!("attempt to divide by zero")
71 }
72
73 let mut rem = 0;
74
75 if b <= big_digit::HALF {
76 for &digit in a.data.iter().rev() {
77 let (_, r) = div_half(rem, digit, b);
78 rem = r;
79 }
80 } else {
81 for &digit in a.data.iter().rev() {
82 let (_, r) = div_wide(rem, digit, b);
83 rem = r;
84 }
85 }
86
87 rem
88}
89
90fn sub_mul_digit_same_len(a: &mut [BigDigit], b: &[BigDigit], c: BigDigit) -> BigDigit {
94 debug_assert!(a.len() == b.len());
95
96 let mut offset_carry = big_digit::MAX;
99
100 for (x, y) in a.iter_mut().zip(b) {
101 let offset_sum = big_digit::to_doublebigdigit(big_digit::MAX, *x)
106 - big_digit::MAX as DoubleBigDigit
107 + offset_carry as DoubleBigDigit
108 - *y as DoubleBigDigit * c as DoubleBigDigit;
109
110 let (new_offset_carry, new_x) = big_digit::from_doublebigdigit(offset_sum);
111 offset_carry = new_offset_carry;
112 *x = new_x;
113 }
114
115 big_digit::MAX - offset_carry
117}
118
119fn div_rem(mut u: BigUint, mut d: BigUint) -> (BigUint, BigUint) {
120 if d.is_zero() {
121 panic!("attempt to divide by zero")
122 }
123 if u.is_zero() {
124 return (Zero::zero(), Zero::zero());
125 }
126
127 if d.data.len() == 1 {
128 if d.data == [1] {
129 return (u, Zero::zero());
130 }
131 let (div, rem) = div_rem_digit(u, d.data[0]);
132 d.data.clear();
134 d += rem;
135 return (div, d);
136 }
137
138 match u.cmp(&d) {
140 Less => return (Zero::zero(), u),
141 Equal => {
142 u.set_one();
143 return (u, Zero::zero());
144 }
145 Greater => {} }
147
148 let shift = d.data.last().unwrap().leading_zeros() as usize;
155
156 if shift == 0 {
157 div_rem_core(u, &d.data)
159 } else {
160 let (q, r) = div_rem_core(u << shift, &(d << shift).data);
161 (q, r >> shift)
163 }
164}
165
166pub(super) fn div_rem_ref(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) {
167 if d.is_zero() {
168 panic!("attempt to divide by zero")
169 }
170 if u.is_zero() {
171 return (Zero::zero(), Zero::zero());
172 }
173
174 if d.data.len() == 1 {
175 if d.data == [1] {
176 return (u.clone(), Zero::zero());
177 }
178
179 let (div, rem) = div_rem_digit(u.clone(), d.data[0]);
180 return (div, rem.into());
181 }
182
183 match u.cmp(d) {
185 Less => return (Zero::zero(), u.clone()),
186 Equal => return (One::one(), Zero::zero()),
187 Greater => {} }
189
190 let shift = d.data.last().unwrap().leading_zeros() as usize;
197
198 if shift == 0 {
199 div_rem_core(u.clone(), &d.data)
201 } else {
202 let (q, r) = div_rem_core(u << shift, &(d << shift).data);
203 (q, r >> shift)
205 }
206}
207
208fn div_rem_core(mut a: BigUint, b: &[BigDigit]) -> (BigUint, BigUint) {
211 debug_assert!(a.data.len() >= b.len() && b.len() > 1);
212 debug_assert!(b.last().unwrap().leading_zeros() == 0);
213
214 let mut a0 = 0;
233
234 let b0 = *b.last().unwrap();
236 let b1 = b[b.len() - 2];
237
238 let q_len = a.data.len() - b.len() + 1;
239 let mut q = BigUint {
240 data: vec![0; q_len],
241 };
242
243 for j in (0..q_len).rev() {
244 debug_assert!(a.data.len() == b.len() + j);
245
246 let a1 = *a.data.last().unwrap();
247 let a2 = a.data[a.data.len() - 2];
248
249 let (mut q0, mut r) = if a0 < b0 {
252 let (q0, r) = div_wide(a0, a1, b0);
253 (q0, r as DoubleBigDigit)
254 } else {
255 debug_assert!(a0 == b0);
256 (big_digit::MAX, a0 as DoubleBigDigit + a1 as DoubleBigDigit)
259 };
260
261 while r <= big_digit::MAX as DoubleBigDigit
270 && big_digit::to_doublebigdigit(r as BigDigit, a2)
271 < q0 as DoubleBigDigit * b1 as DoubleBigDigit
272 {
273 q0 -= 1;
274 r += b0 as DoubleBigDigit;
275 }
276
277 let mut borrow = sub_mul_digit_same_len(&mut a.data[j..], b, q0);
281 if borrow > a0 {
282 q0 -= 1;
284 borrow -= __add2(&mut a.data[j..], b);
285 }
286 debug_assert!(borrow == a0);
288
289 q.data[j] = q0;
290
291 a0 = a.data.pop().unwrap();
293 }
294
295 a.data.push(a0);
296 a.normalize();
297
298 debug_assert_eq!(cmp_slice(&a.data, b), Less);
299
300 (q.normalized(), a)
301}
302
303forward_val_ref_binop!(impl Div for BigUint, div);
304forward_ref_val_binop!(impl Div for BigUint, div);
305forward_val_assign!(impl DivAssign for BigUint, div_assign);
306
307impl Div<BigUint> for BigUint {
308 type Output = BigUint;
309
310 #[inline]
311 fn div(self, other: BigUint) -> BigUint {
312 let (q, _) = div_rem(self, other);
313 q
314 }
315}
316
317impl<'a, 'b> Div<&'b BigUint> for &'a BigUint {
318 type Output = BigUint;
319
320 #[inline]
321 fn div(self, other: &BigUint) -> BigUint {
322 let (q, _) = self.div_rem(other);
323 q
324 }
325}
326impl<'a> DivAssign<&'a BigUint> for BigUint {
327 #[inline]
328 fn div_assign(&mut self, other: &'a BigUint) {
329 *self = &*self / other;
330 }
331}
332
333promote_unsigned_scalars!(impl Div for BigUint, div);
334promote_unsigned_scalars_assign!(impl DivAssign for BigUint, div_assign);
335forward_all_scalar_binop_to_val_val!(impl Div<u32> for BigUint, div);
336forward_all_scalar_binop_to_val_val!(impl Div<u64> for BigUint, div);
337forward_all_scalar_binop_to_val_val!(impl Div<u128> for BigUint, div);
338
339impl Div<u32> for BigUint {
340 type Output = BigUint;
341
342 #[inline]
343 fn div(self, other: u32) -> BigUint {
344 let (q, _) = div_rem_digit(self, other as BigDigit);
345 q
346 }
347}
348impl DivAssign<u32> for BigUint {
349 #[inline]
350 fn div_assign(&mut self, other: u32) {
351 *self = &*self / other;
352 }
353}
354
355impl Div<BigUint> for u32 {
356 type Output = BigUint;
357
358 #[inline]
359 fn div(self, other: BigUint) -> BigUint {
360 match other.data.len() {
361 0 => panic!("attempt to divide by zero"),
362 1 => From::from(self as BigDigit / other.data[0]),
363 _ => Zero::zero(),
364 }
365 }
366}
367
368impl Div<u64> for BigUint {
369 type Output = BigUint;
370
371 #[inline]
372 fn div(self, other: u64) -> BigUint {
373 let (q, _) = div_rem(self, From::from(other));
374 q
375 }
376}
377impl DivAssign<u64> for BigUint {
378 #[inline]
379 fn div_assign(&mut self, other: u64) {
380 let temp = mem::replace(self, Zero::zero());
382 *self = temp / other;
383 }
384}
385
386impl Div<BigUint> for u64 {
387 type Output = BigUint;
388
389 #[cfg(not(u64_digit))]
390 #[inline]
391 fn div(self, other: BigUint) -> BigUint {
392 match other.data.len() {
393 0 => panic!("attempt to divide by zero"),
394 1 => From::from(self / u64::from(other.data[0])),
395 2 => From::from(self / big_digit::to_doublebigdigit(other.data[1], other.data[0])),
396 _ => Zero::zero(),
397 }
398 }
399
400 #[cfg(u64_digit)]
401 #[inline]
402 fn div(self, other: BigUint) -> BigUint {
403 match other.data.len() {
404 0 => panic!("attempt to divide by zero"),
405 1 => From::from(self / other.data[0]),
406 _ => Zero::zero(),
407 }
408 }
409}
410
411impl Div<u128> for BigUint {
412 type Output = BigUint;
413
414 #[inline]
415 fn div(self, other: u128) -> BigUint {
416 let (q, _) = div_rem(self, From::from(other));
417 q
418 }
419}
420
421impl DivAssign<u128> for BigUint {
422 #[inline]
423 fn div_assign(&mut self, other: u128) {
424 *self = &*self / other;
425 }
426}
427
428impl Div<BigUint> for u128 {
429 type Output = BigUint;
430
431 #[cfg(not(u64_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 / u128::from(other.data[0])),
437 2 => From::from(
438 self / u128::from(big_digit::to_doublebigdigit(other.data[1], other.data[0])),
439 ),
440 3 => From::from(self / u32_to_u128(0, other.data[2], other.data[1], other.data[0])),
441 4 => From::from(
442 self / u32_to_u128(other.data[3], other.data[2], other.data[1], other.data[0]),
443 ),
444 _ => Zero::zero(),
445 }
446 }
447
448 #[cfg(u64_digit)]
449 #[inline]
450 fn div(self, other: BigUint) -> BigUint {
451 match other.data.len() {
452 0 => panic!("attempt to divide by zero"),
453 1 => From::from(self / other.data[0] as u128),
454 2 => From::from(self / big_digit::to_doublebigdigit(other.data[1], other.data[0])),
455 _ => Zero::zero(),
456 }
457 }
458}
459
460forward_val_ref_binop!(impl Rem for BigUint, rem);
461forward_ref_val_binop!(impl Rem for BigUint, rem);
462forward_val_assign!(impl RemAssign for BigUint, rem_assign);
463
464impl Rem<BigUint> for BigUint {
465 type Output = BigUint;
466
467 #[inline]
468 fn rem(self, other: BigUint) -> BigUint {
469 if let Some(other) = other.to_u32() {
470 &self % other
471 } else {
472 let (_, r) = div_rem(self, other);
473 r
474 }
475 }
476}
477
478impl<'a, 'b> Rem<&'b BigUint> for &'a BigUint {
479 type Output = BigUint;
480
481 #[inline]
482 fn rem(self, other: &BigUint) -> BigUint {
483 if let Some(other) = other.to_u32() {
484 self % other
485 } else {
486 let (_, r) = self.div_rem(other);
487 r
488 }
489 }
490}
491impl<'a> RemAssign<&'a BigUint> for BigUint {
492 #[inline]
493 fn rem_assign(&mut self, other: &BigUint) {
494 *self = &*self % other;
495 }
496}
497
498promote_unsigned_scalars!(impl Rem for BigUint, rem);
499promote_unsigned_scalars_assign!(impl RemAssign for BigUint, rem_assign);
500forward_all_scalar_binop_to_ref_val!(impl Rem<u32> for BigUint, rem);
501forward_all_scalar_binop_to_val_val!(impl Rem<u64> for BigUint, rem);
502forward_all_scalar_binop_to_val_val!(impl Rem<u128> for BigUint, rem);
503
504impl<'a> Rem<u32> for &'a BigUint {
505 type Output = BigUint;
506
507 #[inline]
508 fn rem(self, other: u32) -> BigUint {
509 rem_digit(self, other as BigDigit).into()
510 }
511}
512impl RemAssign<u32> for BigUint {
513 #[inline]
514 fn rem_assign(&mut self, other: u32) {
515 *self = &*self % other;
516 }
517}
518
519impl<'a> Rem<&'a BigUint> for u32 {
520 type Output = BigUint;
521
522 #[inline]
523 fn rem(mut self, other: &'a BigUint) -> BigUint {
524 self %= other;
525 From::from(self)
526 }
527}
528
529macro_rules! impl_rem_assign_scalar {
530 ($scalar:ty, $to_scalar:ident) => {
531 forward_val_assign_scalar!(impl RemAssign for BigUint, $scalar, rem_assign);
532 impl<'a> RemAssign<&'a BigUint> for $scalar {
533 #[inline]
534 fn rem_assign(&mut self, other: &BigUint) {
535 *self = match other.$to_scalar() {
536 None => *self,
537 Some(0) => panic!("attempt to divide by zero"),
538 Some(v) => *self % v
539 };
540 }
541 }
542 }
543}
544
545impl_rem_assign_scalar!(u128, to_u128);
547impl_rem_assign_scalar!(usize, to_usize);
548impl_rem_assign_scalar!(u64, to_u64);
549impl_rem_assign_scalar!(u32, to_u32);
550impl_rem_assign_scalar!(u16, to_u16);
551impl_rem_assign_scalar!(u8, to_u8);
552impl_rem_assign_scalar!(i128, to_i128);
553impl_rem_assign_scalar!(isize, to_isize);
554impl_rem_assign_scalar!(i64, to_i64);
555impl_rem_assign_scalar!(i32, to_i32);
556impl_rem_assign_scalar!(i16, to_i16);
557impl_rem_assign_scalar!(i8, to_i8);
558
559impl Rem<u64> for BigUint {
560 type Output = BigUint;
561
562 #[inline]
563 fn rem(self, other: u64) -> BigUint {
564 let (_, r) = div_rem(self, From::from(other));
565 r
566 }
567}
568impl RemAssign<u64> for BigUint {
569 #[inline]
570 fn rem_assign(&mut self, other: u64) {
571 *self = &*self % other;
572 }
573}
574
575impl Rem<BigUint> for u64 {
576 type Output = BigUint;
577
578 #[inline]
579 fn rem(mut self, other: BigUint) -> BigUint {
580 self %= other;
581 From::from(self)
582 }
583}
584
585impl Rem<u128> for BigUint {
586 type Output = BigUint;
587
588 #[inline]
589 fn rem(self, other: u128) -> BigUint {
590 let (_, r) = div_rem(self, From::from(other));
591 r
592 }
593}
594
595impl RemAssign<u128> for BigUint {
596 #[inline]
597 fn rem_assign(&mut self, other: u128) {
598 *self = &*self % other;
599 }
600}
601
602impl Rem<BigUint> for u128 {
603 type Output = BigUint;
604
605 #[inline]
606 fn rem(mut self, other: BigUint) -> BigUint {
607 self %= other;
608 From::from(self)
609 }
610}
611
612impl CheckedDiv for BigUint {
613 #[inline]
614 fn checked_div(&self, v: &BigUint) -> Option<BigUint> {
615 if v.is_zero() {
616 return None;
617 }
618 Some(self.div(v))
619 }
620}