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        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        // The algorithm guarantees at most two corrections are needed.
301        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
325/// An implementation of the base division algorithm.
326/// Knuth, TAOCP vol 2 section 4.3.1, algorithm D, with an improvement from exercises 19-21.
327fn 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    // The algorithm works by incrementally calculating "guesses", q0, for the next digit of the
340    // quotient. Once we have any number q0 such that (q0 << j) * b <= a, we can set
341    //
342    //     q += q0 << j
343    //     a -= (q0 << j) * b
344    //
345    // and then iterate until a < b. Then, (q, a) will be our desired quotient and remainder.
346    //
347    // q0, our guess, is calculated by dividing the last three digits of a by the last two digits of
348    // b - this will give us a guess that is close to the actual quotient, but is possibly greater.
349    // It can only be greater by 1 and only in rare cases, with probability at most
350    // 2^-(big_digit::BITS-1) for random a, see TAOCP 4.3.1 exercise 21.
351    //
352    // If the quotient turns out to be too large, we adjust it by 1:
353    // q -= 1 << j
354    // a += b << j
355
356    // a0 stores an additional extra most significant digit of the dividend, not stored in a.
357    let mut a0 = 0;
358
359    // [b1, b0] are the two most significant digits of the divisor. They never change.
360    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        // The first q0 estimate is [a1,a0] / b0. It will never be too small, it may be too large
375        // by at most 2.
376        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            // Avoid overflowing q0, we know the quotient fits in BigDigit.
382            // [a1,a0] = b0 * (1<<BITS - 1) + (a0 + a1)
383            (big_digit::MAX, a0 as DoubleBigDigit + a1 as DoubleBigDigit)
384        };
385
386        // r = [a1,a0] - q0 * b0
387        //
388        // Now we want to compute a more precise estimate [a2,a1,a0] / [b1,b0] which can only be
389        // less or equal to the current q0.
390        //
391        // q0 is too large if:
392        // [a2,a1,a0] < q0 * [b1,b0]
393        // (r << BITS) + a2 < q0 * b1
394        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        // q0 is now either the correct quotient digit, or in rare cases 1 too large.
403        // Subtract (q0 << j) from a. This may overflow, in which case we will have to correct.
404
405        let mut borrow = sub_mul_digit_same_len(&mut a.data[j..], b, q0);
406        if borrow > a0 {
407            // q0 is too large. We need to add back one multiple of b.
408            q0 -= 1;
409            borrow -= __add2(&mut a.data[j..], b);
410        }
411        // The top digit of a, stored in a0, has now been zeroed.
412        debug_assert!(borrow == a0);
413
414        q.data[j] = q0;
415
416        // Pop off the next top digit of a.
417        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        // a vec of size 0 does not allocate, so this is fairly cheap
511        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
672// we can scalar %= BigUint for any scalar, including signed types
673impl_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        // trivially same as regular division
775        self / v
776    }
777
778    #[inline]
779    fn rem_euclid(&self, v: &BigUint) -> BigUint {
780        // trivially same as regular remainder
781        self % v
782    }
783
784    fn div_rem_euclid(&self, v: &Self) -> (Self, Self) {
785        // trivially same as regular division and remainder
786        self.div_rem(v)
787    }
788}