num_bigint/biguint/
division.rs

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/// Divide a two digit numerator by a one digit divisor, returns quotient and remainder:
16///
17/// Note: the caller must ensure that both the quotient and remainder will fit into a single digit.
18/// This is _not_ true for an arbitrary numerator/denominator.
19///
20/// (This function also matches what the x86 divide instruction does).
21#[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/// For small divisors, we can divide without promoting to `DoubleBigDigit` by
31/// using half-size pieces of digit, like long-division.
32#[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
90/// Subtract a multiple.
91/// a -= b * c
92/// Returns a borrow (if a < b then borrow > 0).
93fn sub_mul_digit_same_len(a: &mut [BigDigit], b: &[BigDigit], c: BigDigit) -> BigDigit {
94    debug_assert!(a.len() == b.len());
95
96    // carry is between -big_digit::MAX and 0, so to avoid overflow we store
97    // offset_carry = carry + big_digit::MAX
98    let mut offset_carry = big_digit::MAX;
99
100    for (x, y) in a.iter_mut().zip(b) {
101        // We want to calculate sum = x - y * c + carry.
102        // sum >= -(big_digit::MAX * big_digit::MAX) - big_digit::MAX
103        // sum <= big_digit::MAX
104        // Offsetting sum by (big_digit::MAX << big_digit::BITS) puts it in DoubleBigDigit range.
105        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    // Return the borrow.
116    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        // reuse d
133        d.data.clear();
134        d += rem;
135        return (div, d);
136    }
137
138    // Required or the q_len calculation below can underflow:
139    match u.cmp(&d) {
140        Less => return (Zero::zero(), u),
141        Equal => {
142            u.set_one();
143            return (u, Zero::zero());
144        }
145        Greater => {} // Do nothing
146    }
147
148    // This algorithm is from Knuth, TAOCP vol 2 section 4.3, algorithm D:
149    //
150    // First, normalize the arguments so the highest bit in the highest digit of the divisor is
151    // set: the main loop uses the highest digit of the divisor for generating guesses, so we
152    // want it to be the largest number we can efficiently divide by.
153    //
154    let shift = d.data.last().unwrap().leading_zeros() as usize;
155
156    if shift == 0 {
157        // no need to clone d
158        div_rem_core(u, &d.data)
159    } else {
160        let (q, r) = div_rem_core(u << shift, &(d << shift).data);
161        // renormalize the remainder
162        (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    // Required or the q_len calculation below can underflow:
184    match u.cmp(d) {
185        Less => return (Zero::zero(), u.clone()),
186        Equal => return (One::one(), Zero::zero()),
187        Greater => {} // Do nothing
188    }
189
190    // This algorithm is from Knuth, TAOCP vol 2 section 4.3, algorithm D:
191    //
192    // First, normalize the arguments so the highest bit in the highest digit of the divisor is
193    // set: the main loop uses the highest digit of the divisor for generating guesses, so we
194    // want it to be the largest number we can efficiently divide by.
195    //
196    let shift = d.data.last().unwrap().leading_zeros() as usize;
197
198    if shift == 0 {
199        // no need to clone d
200        div_rem_core(u.clone(), &d.data)
201    } else {
202        let (q, r) = div_rem_core(u << shift, &(d << shift).data);
203        // renormalize the remainder
204        (q, r >> shift)
205    }
206}
207
208/// An implementation of the base division algorithm.
209/// Knuth, TAOCP vol 2 section 4.3.1, algorithm D, with an improvement from exercises 19-21.
210fn 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    // The algorithm works by incrementally calculating "guesses", q0, for the next digit of the
215    // quotient. Once we have any number q0 such that (q0 << j) * b <= a, we can set
216    //
217    //     q += q0 << j
218    //     a -= (q0 << j) * b
219    //
220    // and then iterate until a < b. Then, (q, a) will be our desired quotient and remainder.
221    //
222    // q0, our guess, is calculated by dividing the last three digits of a by the last two digits of
223    // b - this will give us a guess that is close to the actual quotient, but is possibly greater.
224    // It can only be greater by 1 and only in rare cases, with probability at most
225    // 2^-(big_digit::BITS-1) for random a, see TAOCP 4.3.1 exercise 21.
226    //
227    // If the quotient turns out to be too large, we adjust it by 1:
228    // q -= 1 << j
229    // a += b << j
230
231    // a0 stores an additional extra most significant digit of the dividend, not stored in a.
232    let mut a0 = 0;
233
234    // [b1, b0] are the two most significant digits of the divisor. They never change.
235    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        // The first q0 estimate is [a1,a0] / b0. It will never be too small, it may be too large
250        // by at most 2.
251        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            // Avoid overflowing q0, we know the quotient fits in BigDigit.
257            // [a1,a0] = b0 * (1<<BITS - 1) + (a0 + a1)
258            (big_digit::MAX, a0 as DoubleBigDigit + a1 as DoubleBigDigit)
259        };
260
261        // r = [a1,a0] - q0 * b0
262        //
263        // Now we want to compute a more precise estimate [a2,a1,a0] / [b1,b0] which can only be
264        // less or equal to the current q0.
265        //
266        // q0 is too large if:
267        // [a2,a1,a0] < q0 * [b1,b0]
268        // (r << BITS) + a2 < q0 * b1
269        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        // q0 is now either the correct quotient digit, or in rare cases 1 too large.
278        // Subtract (q0 << j) from a. This may overflow, in which case we will have to correct.
279
280        let mut borrow = sub_mul_digit_same_len(&mut a.data[j..], b, q0);
281        if borrow > a0 {
282            // q0 is too large. We need to add back one multiple of b.
283            q0 -= 1;
284            borrow -= __add2(&mut a.data[j..], b);
285        }
286        // The top digit of a, stored in a0, has now been zeroed.
287        debug_assert!(borrow == a0);
288
289        q.data[j] = q0;
290
291        // Pop off the next top digit of a.
292        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        // a vec of size 0 does not allocate, so this is fairly cheap
381        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
545// we can scalar %= BigUint for any scalar, including signed types
546impl_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}