Skip to main content

num_bigint/biguint/
division.rs

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/// Divide a two digit numerator by a one digit divisor, returns quotient and remainder:
18///
19/// Note: the caller must ensure that both the quotient and remainder will fit into a single digit.
20/// This is _not_ true for an arbitrary numerator/denominator.
21///
22/// (This function also matches what the x86 divide instruction does).
23#[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/// x86 and x86_64 can use a real `div` instruction.
34#[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    // This debug assertion covers the potential #DE for divisor==0 or a quotient too large for one
38    // register, otherwise in release mode it will become a target-specific fault like SIGFPE.
39    // This should never occur with the inputs from our few `div_wide` callers.
40    debug_assert!(hi < divisor);
41
42    // SAFETY: The `div` instruction only affects registers, reading the explicit operand as the
43    // divisor, and implicitly reading RDX:RAX or EDX:EAX as the dividend. The result is implicitly
44    // written back to RAX or EAX for the quotient and RDX or EDX for the remainder. No memory is
45    // used, and flags are not preserved.
46    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/// For small divisors, we can divide without promoting to `DoubleBigDigit` by
75/// using half-size pieces of digit, like long-division.
76#[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
135/// Subtract a multiple.
136/// a -= b * c
137/// Returns a borrow (if a < b then borrow > 0).
138fn sub_mul_digit_same_len(a: &mut [BigDigit], b: &[BigDigit], c: BigDigit) -> BigDigit {
139    debug_assert!(a.len() == b.len());
140
141    // carry is between -big_digit::MAX and 0, so to avoid overflow we store
142    // offset_carry = carry + big_digit::MAX
143    let mut offset_carry = big_digit::MAX;
144
145    for (x, y) in a.iter_mut().zip(b) {
146        // We want to calculate sum = x - y * c + carry.
147        // sum >= -(big_digit::MAX * big_digit::MAX) - big_digit::MAX
148        // sum <= big_digit::MAX
149        // Offsetting sum by (big_digit::MAX << big_digit::BITS) puts it in DoubleBigDigit range.
150        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    // Return the borrow.
161    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    // Required or the q_len calculation below can underflow:
190    match u.cmp(&d) {
191        Less => return (BigUint::ZERO, u.into_owned()),
192        Equal => return (BigUint::ONE, BigUint::ZERO),
193        Greater => {} // Do nothing
194    }
195
196    // This algorithm is from Knuth, TAOCP vol 2 section 4.3, algorithm D:
197    //
198    // First, normalize the arguments so the highest bit in the highest digit of the divisor is
199    // set: the main loop uses the highest digit of the divisor for generating guesses, so we
200    // want it to be the largest number we can efficiently divide by.
201    //
202    let shift = d.data.last().unwrap().leading_zeros();
203
204    if shift == 0 {
205        // no need to clone d
206        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        // renormalize the remainder
212        (q, r >> shift)
213    }
214}
215
216const BURNIKEL_ZIEGLER_THRESHOLD: usize = 64;
217
218/// This algorithm is from Burnikel and Ziegler, "Fast Recursive Division", Algorithm 1.
219/// It is a recursive algorithm that divides the dividend and divisor into blocks of digits
220/// and uses a divide-and-conquer approach to find the quotient.
221///
222/// The algorithm is more complex than the base algorithm, but it is faster for large operands.
223///
224/// Time complexity of this algorithm is the same as the algorithm used for the multiplication.
225///
226/// link: https://pure.mpg.de/rest/items/item_1819444_4/component/file_2599480/content
227fn 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        // A precondition of this function is that q fits into a single digit.
259        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        // Algorithm 2 step 3 distinguishes A₁<B₁ or A₁≥B₁, preserving
299        // div_two_digit_by_one's asserted invariant that `ah < b`.
300        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            // set Q = βⁿ-1 and set R₁ = [A₁;A₂] - [B₁;0] + [0;B₁]
306            //                        (= [A₁;A₂] - QB₁)
307            q = BigUint {
308                data: BigDigits::from_vec(vec![BigDigit::MAX; level]),
309            };
310            r1 = concat_biguint(&(a1 - &b1), a2, level) + &b1;
311            // also Q*B₂ = (βⁿ-1)B₂ = βⁿB₂ - B₂
312            d = (&b2 << (level * usize::from(BITS))) - &b2;
313        };
314        // The algorithm guarantees at most two corrections are needed.
315        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
340/// An implementation of the base division algorithm.
341/// Knuth, TAOCP vol 2 section 4.3.1, algorithm D, with an improvement from exercises 19-21.
342fn 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    // The algorithm works by incrementally calculating "guesses", q0, for the next digit of the
355    // quotient. Once we have any number q0 such that (q0 << j) * b <= a, we can set
356    //
357    //     q += q0 << j
358    //     a -= (q0 << j) * b
359    //
360    // and then iterate until a < b. Then, (q, a) will be our desired quotient and remainder.
361    //
362    // q0, our guess, is calculated by dividing the last three digits of a by the last two digits of
363    // b - this will give us a guess that is close to the actual quotient, but is possibly greater.
364    // It can only be greater by 1 and only in rare cases, with probability at most
365    // 2^-(big_digit::BITS-1) for random a, see TAOCP 4.3.1 exercise 21.
366    //
367    // If the quotient turns out to be too large, we adjust it by 1:
368    // q -= 1 << j
369    // a += b << j
370
371    // a0 stores an additional extra most significant digit of the dividend, not stored in a.
372    let mut a0 = 0;
373
374    // [b1, b0] are the two most significant digits of the divisor. They never change.
375    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        // The first q0 estimate is [a1,a0] / b0. It will never be too small, it may be too large
390        // by at most 2.
391        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            // Avoid overflowing q0, we know the quotient fits in BigDigit.
397            // [a1,a0] = b0 * (1<<BITS - 1) + (a0 + a1)
398            (big_digit::MAX, a0 as DoubleBigDigit + a1 as DoubleBigDigit)
399        };
400
401        // r = [a1,a0] - q0 * b0
402        //
403        // Now we want to compute a more precise estimate [a2,a1,a0] / [b1,b0] which can only be
404        // less or equal to the current q0.
405        //
406        // q0 is too large if:
407        // [a2,a1,a0] < q0 * [b1,b0]
408        // (r << BITS) + a2 < q0 * b1
409        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        // q0 is now either the correct quotient digit, or in rare cases 1 too large.
418        // Subtract (q0 << j) from a. This may overflow, in which case we will have to correct.
419
420        let mut borrow = sub_mul_digit_same_len(&mut a.data[j..], b, q0);
421        if borrow > a0 {
422            // q0 is too large. We need to add back one multiple of b.
423            q0 -= 1;
424            borrow -= __add2(&mut a.data[j..], b);
425        }
426        // The top digit of a, stored in a0, has now been zeroed.
427        debug_assert!(borrow == a0);
428
429        q.data[j] = q0;
430
431        // Pop off the next top digit of a.
432        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        // a vec of size 0 does not allocate, so this is fairly cheap
526        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
687// we can scalar %= BigUint for any scalar, including signed types
688impl_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        // trivially same as regular division
790        self / v
791    }
792
793    #[inline]
794    fn rem_euclid(&self, v: &BigUint) -> BigUint {
795        // trivially same as regular remainder
796        self % v
797    }
798
799    fn div_rem_euclid(&self, v: &Self) -> (Self, Self) {
800        // trivially same as regular division and remainder
801        self.div_rem(v)
802    }
803}