Coverage Report

Created: 2026-10-17 07:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/num-bigint-0.5.1/src/biguint/division.rs
Line
Count
Source
1
use super::addition::__add2;
2
use super::shift::biguint_shl;
3
use super::{cmp_slice, ilog2, BigUint};
4
5
use crate::big_digit::{self, BigDigit, BigDigits, DoubleBigDigit, BITS};
6
use crate::UsizePromotion;
7
8
use alloc::borrow::Cow;
9
use core::cmp::Ordering::{Equal, Greater, Less};
10
use core::mem;
11
use core::ops::{Div, DivAssign, Rem, RemAssign};
12
use num_integer::Integer;
13
use num_traits::{CheckedDiv, CheckedEuclid, Euclid, ToPrimitive, Zero};
14
15
pub(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]
25
fn 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]
36
0
fn 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
0
    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
0
        core::arch::asm!(
63
0
            div!(),
64
0
            in(reg) divisor,
65
0
            inout("dx") hi => rem,
66
0
            inout("ax") lo => div,
67
0
            options(pure, nomem, nostack),
68
0
        );
69
70
0
        (div, rem)
71
    }
72
0
}
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]
77
0
fn div_half(rem: BigDigit, digit: BigDigit, divisor: BigDigit) -> (BigDigit, BigDigit) {
78
    use crate::big_digit::{HALF, HALF_BITS};
79
80
0
    debug_assert!(rem < divisor && divisor <= HALF);
81
0
    let (hi, rem) = ((rem << HALF_BITS) | (digit >> HALF_BITS)).div_rem(&divisor);
82
0
    let (lo, rem) = ((rem << HALF_BITS) | (digit & HALF)).div_rem(&divisor);
83
0
    ((hi << HALF_BITS) | lo, rem)
84
0
}
85
86
#[inline]
87
0
pub(super) fn div_rem_digit(mut a: BigUint, b: BigDigit) -> (BigUint, BigDigit) {
88
0
    if b == 0 {
89
0
        panic!("attempt to divide by zero")
90
0
    }
91
92
0
    let mut rem = 0;
93
94
0
    if !FAST_DIV_WIDE && b <= big_digit::HALF {
95
0
        for d in a.data.iter_mut().rev() {
96
0
            let (q, r) = div_half(rem, *d, b);
97
0
            *d = q;
98
0
            rem = r;
99
0
        }
100
    } else {
101
0
        for d in a.data.iter_mut().rev() {
102
0
            let (q, r) = div_wide(rem, *d, b);
103
0
            *d = q;
104
0
            rem = r;
105
0
        }
106
    }
107
108
0
    a.data.normalize();
109
0
    (a, rem)
110
0
}
111
112
#[inline]
113
0
fn rem_digit(a: &BigUint, b: BigDigit) -> BigDigit {
114
0
    if b == 0 {
115
0
        panic!("attempt to divide by zero")
116
0
    }
117
118
0
    let mut rem = 0;
119
120
0
    if !FAST_DIV_WIDE && b <= big_digit::HALF {
121
0
        for &digit in a.data.iter().rev() {
122
0
            let (_, r) = div_half(rem, digit, b);
123
0
            rem = r;
124
0
        }
125
    } else {
126
0
        for &digit in a.data.iter().rev() {
127
0
            let (_, r) = div_wide(rem, digit, b);
128
0
            rem = r;
129
0
        }
130
    }
131
132
0
    rem
133
0
}
134
135
/// Subtract a multiple.
136
/// a -= b * c
137
/// Returns a borrow (if a < b then borrow > 0).
138
0
fn sub_mul_digit_same_len(a: &mut [BigDigit], b: &[BigDigit], c: BigDigit) -> BigDigit {
139
0
    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
0
    let mut offset_carry = big_digit::MAX;
144
145
0
    for (x, y) in a.iter_mut().zip(b) {
146
0
        // We want to calculate sum = x - y * c + carry.
147
0
        // sum >= -(big_digit::MAX * big_digit::MAX) - big_digit::MAX
148
0
        // sum <= big_digit::MAX
149
0
        // Offsetting sum by (big_digit::MAX << big_digit::BITS) puts it in DoubleBigDigit range.
150
0
        let offset_sum = big_digit::to_doublebigdigit(big_digit::MAX, *x)
151
0
            - big_digit::MAX as DoubleBigDigit
152
0
            + offset_carry as DoubleBigDigit
153
0
            - *y as DoubleBigDigit * c as DoubleBigDigit;
154
0
155
0
        let (new_offset_carry, new_x) = big_digit::from_doublebigdigit(offset_sum);
156
0
        offset_carry = new_offset_carry;
157
0
        *x = new_x;
158
0
    }
159
160
    // Return the borrow.
161
0
    big_digit::MAX - offset_carry
162
0
}
163
164
0
fn div_rem(u: BigUint, d: BigUint) -> (BigUint, BigUint) {
165
0
    div_rem_cow(Cow::Owned(u), Cow::Owned(d))
166
0
}
167
168
0
pub(super) fn div_rem_ref(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) {
169
0
    div_rem_cow(Cow::Borrowed(u), Cow::Borrowed(d))
170
0
}
171
172
0
fn div_rem_cow(u: Cow<'_, BigUint>, d: Cow<'_, BigUint>) -> (BigUint, BigUint) {
173
0
    if d.is_zero() {
174
0
        panic!("attempt to divide by zero")
175
0
    }
176
0
    if u.is_zero() {
177
0
        return (BigUint::ZERO, BigUint::ZERO);
178
0
    }
179
180
0
    if let [digit] = *d.data {
181
0
        let u = u.into_owned();
182
0
        if digit == 1 {
183
0
            return (u, BigUint::ZERO);
184
0
        }
185
0
        let (div, rem) = div_rem_digit(u, digit);
186
0
        return (div, rem.into());
187
0
    }
188
189
    // Required or the q_len calculation below can underflow:
190
0
    match u.cmp(&d) {
191
0
        Less => return (BigUint::ZERO, u.into_owned()),
192
0
        Equal => return (BigUint::ONE, BigUint::ZERO),
193
0
        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
0
    let shift = d.data.last().unwrap().leading_zeros();
203
204
0
    if shift == 0 {
205
        // no need to clone d
206
0
        div_rem_core(u, &d)
207
    } else {
208
0
        let u = biguint_shl(u, shift);
209
0
        let d = biguint_shl(d, shift);
210
0
        let (q, r) = div_rem_core(Cow::Owned(u), &d);
211
        // renormalize the remainder
212
0
        (q, r >> shift)
213
    }
214
0
}
215
216
const 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
227
0
fn div_rem_burnikel_ziegler(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) {
228
0
    fn divide_biguint(mut b: BigUint, level: usize) -> (BigUint, BigUint) {
229
0
        if b.data.len() <= level {
230
0
            return (BigUint::ZERO, b);
231
0
        }
232
0
        let mut b1_data = BigDigits::from_slice(&b.data[level..]);
233
0
        b1_data.normalize();
234
0
        b.data.truncate(level);
235
0
        b.data.normalize();
236
0
        (BigUint { data: b1_data }, b)
237
0
    }
238
239
0
    fn normalizing_shift_amount(b: &BigUint, level: usize) -> u64 {
240
0
        (level as u64) * u64::from(BITS) - b.bits()
241
0
    }
242
243
0
    fn concat_biguint(b1: &BigUint, b2: BigUint, level: usize) -> BigUint {
244
0
        let mut data = b2.data;
245
0
        data.reserve(level + b1.data.len() - data.len());
246
0
        data.resize(level, 0);
247
0
        data.extend_from_slice(&b1.data);
248
0
        data.normalize();
249
0
        BigUint { data }
250
0
    }
251
252
0
    fn div_two_digit_by_one(
253
0
        ah: BigUint,
254
0
        al: BigUint,
255
0
        b: BigUint,
256
0
        level: usize,
257
0
    ) -> (BigUint, BigUint) {
258
        // A precondition of this function is that q fits into a single digit.
259
0
        debug_assert!(ah < b);
260
0
        if level <= BURNIKEL_ZIEGLER_THRESHOLD {
261
0
            return div_rem(concat_biguint(&ah, al, level), b);
262
0
        }
263
0
        let shift = normalizing_shift_amount(&b, level);
264
0
        if shift != 0 {
265
0
            let b = b << shift;
266
0
            let (ah, al) = divide_biguint(concat_biguint(&ah, al, level) << shift, level);
267
0
            let (q, r) = div_two_digit_by_one_normalized(ah, al, b, level);
268
0
            (q, r >> shift)
269
        } else {
270
0
            div_two_digit_by_one_normalized(ah, al, b, level)
271
        }
272
0
    }
273
274
0
    fn div_two_digit_by_one_normalized(
275
0
        ah: BigUint,
276
0
        al: BigUint,
277
0
        b: BigUint,
278
0
        level: usize,
279
0
    ) -> (BigUint, BigUint) {
280
0
        let level = level / 2;
281
0
        let (a1, a2) = divide_biguint(ah, level);
282
0
        let (a3, a4) = divide_biguint(al, level);
283
0
        let (b1, b2) = divide_biguint(b, level);
284
0
        let (q1, r) = div_three_halves_by_two(a1, a2, a3, b1.clone(), b2.clone(), level);
285
0
        let (r1, r2) = divide_biguint(r, level);
286
0
        let (q2, s) = div_three_halves_by_two(r1, r2, a4, b1, b2, level);
287
0
        (concat_biguint(&q1, q2, level), s)
288
0
    }
289
290
0
    fn div_three_halves_by_two(
291
0
        a1: BigUint,
292
0
        a2: BigUint,
293
0
        a3: BigUint,
294
0
        b1: BigUint,
295
0
        b2: BigUint,
296
0
        level: usize,
297
0
    ) -> (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
0
        if a1 < b1 {
302
0
            (q, r1) = div_two_digit_by_one(a1, a2, b1.clone(), level);
303
0
            d = &q * &b2;
304
0
        } else {
305
0
            // set Q = βⁿ-1 and set R₁ = [A₁;A₂] - [B₁;0] + [0;B₁]
306
0
            //                        (= [A₁;A₂] - QB₁)
307
0
            q = BigUint {
308
0
                data: BigDigits::from_vec(vec![BigDigit::MAX; level]),
309
0
            };
310
0
            r1 = concat_biguint(&(a1 - &b1), a2, level) + &b1;
311
0
            // also Q*B₂ = (βⁿ-1)B₂ = βⁿB₂ - B₂
312
0
            d = (&b2 << (level * usize::from(BITS))) - &b2;
313
0
        };
314
        // The algorithm guarantees at most two corrections are needed.
315
0
        let mut r = concat_biguint(&r1, a3, level);
316
0
        if r < d {
317
0
            let b = concat_biguint(&b1, b2, level);
318
0
            q -= 1u32;
319
0
            r += &b;
320
0
            if r < d {
321
0
                q -= 1u32;
322
0
                r += &b;
323
0
            }
324
0
        }
325
0
        (q, r - d)
326
0
    }
327
328
0
    let mut level = 1 << ilog2(u.data.len());
329
0
    if d.data.len() > level {
330
0
        level *= 2;
331
0
    }
332
0
    let (u1, u2) = divide_biguint(u.clone(), level);
333
0
    if &u1 >= d {
334
0
        div_two_digit_by_one(BigUint::ZERO, u.clone(), d.clone(), level * 2)
335
    } else {
336
0
        div_two_digit_by_one(u1, u2, d.clone(), level)
337
    }
338
0
}
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.
342
0
fn div_rem_core(a: Cow<'_, BigUint>, b: &BigUint) -> (BigUint, BigUint) {
343
0
    if (a.data.len() > BURNIKEL_ZIEGLER_THRESHOLD * 2)
344
0
        && (b.data.len() > BURNIKEL_ZIEGLER_THRESHOLD)
345
    {
346
0
        return div_rem_burnikel_ziegler(&a, b);
347
0
    }
348
349
0
    let mut a = a.into_owned();
350
0
    let b = &*b.data;
351
0
    debug_assert!(a.data.len() >= b.len() && b.len() > 1);
352
0
    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
0
    let mut a0 = 0;
373
374
    // [b1, b0] are the two most significant digits of the divisor. They never change.
375
0
    let b0 = b[b.len() - 1];
376
0
    let b1 = b[b.len() - 2];
377
378
0
    let q_len = a.data.len() - b.len() + 1;
379
0
    let mut q = BigUint {
380
0
        data: BigDigits::from_vec(vec![0; q_len]),
381
0
    };
382
383
0
    for j in (0..q_len).rev() {
384
0
        debug_assert!(a.data.len() == b.len() + j);
385
386
0
        let a1 = *a.data.last().unwrap();
387
0
        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
0
        let (mut q0, mut r) = if a0 < b0 {
392
0
            let (q0, r) = div_wide(a0, a1, b0);
393
0
            (q0, r as DoubleBigDigit)
394
        } else {
395
0
            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
0
            (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
0
        while r <= big_digit::MAX as DoubleBigDigit
410
0
            && big_digit::to_doublebigdigit(r as BigDigit, a2)
411
0
                < q0 as DoubleBigDigit * b1 as DoubleBigDigit
412
0
        {
413
0
            q0 -= 1;
414
0
            r += b0 as DoubleBigDigit;
415
0
        }
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
0
        let mut borrow = sub_mul_digit_same_len(&mut a.data[j..], b, q0);
421
0
        if borrow > a0 {
422
0
            // q0 is too large. We need to add back one multiple of b.
423
0
            q0 -= 1;
424
0
            borrow -= __add2(&mut a.data[j..], b);
425
0
        }
426
        // The top digit of a, stored in a0, has now been zeroed.
427
0
        debug_assert!(borrow == a0);
428
429
0
        q.data[j] = q0;
430
431
        // Pop off the next top digit of a.
432
0
        a0 = a.data.pop().unwrap();
433
    }
434
435
0
    if a0 != 0 {
436
0
        a.data.push(a0);
437
0
        a.data.shrink();
438
0
    } else {
439
0
        a.data.normalize();
440
0
    }
441
442
0
    debug_assert_eq!(cmp_slice(&a.data, b), Less);
443
444
0
    q.data.normalize();
445
0
    (q, a)
446
0
}
447
448
forward_val_ref_binop!(impl Div for BigUint, div);
449
forward_ref_val_binop!(impl Div for BigUint, div);
450
forward_val_assign!(impl DivAssign for BigUint, div_assign);
451
452
impl Div<BigUint> for BigUint {
453
    type Output = BigUint;
454
455
    #[inline]
456
0
    fn div(self, other: BigUint) -> BigUint {
457
0
        let (q, _) = div_rem(self, other);
458
0
        q
459
0
    }
460
}
461
462
impl Div<&BigUint> for &BigUint {
463
    type Output = BigUint;
464
465
    #[inline]
466
0
    fn div(self, other: &BigUint) -> BigUint {
467
0
        let (q, _) = self.div_rem(other);
468
0
        q
469
0
    }
470
}
471
impl DivAssign<&BigUint> for BigUint {
472
    #[inline]
473
0
    fn div_assign(&mut self, other: &BigUint) {
474
0
        *self = &*self / other;
475
0
    }
476
}
477
478
promote_unsigned_scalars!(impl Div for BigUint, div);
479
promote_unsigned_scalars_assign!(impl DivAssign for BigUint, div_assign);
480
forward_all_scalar_binop_to_val_val!(impl Div<u32> for BigUint, div);
481
forward_all_scalar_binop_to_val_val!(impl Div<u64> for BigUint, div);
482
forward_all_scalar_binop_to_val_val!(impl Div<u128> for BigUint, div);
483
484
impl Div<u32> for BigUint {
485
    type Output = BigUint;
486
487
    #[inline]
488
0
    fn div(self, other: u32) -> BigUint {
489
0
        let (q, _) = div_rem_digit(self, other as BigDigit);
490
0
        q
491
0
    }
492
}
493
impl DivAssign<u32> for BigUint {
494
    #[inline]
495
0
    fn div_assign(&mut self, other: u32) {
496
0
        *self = &*self / other;
497
0
    }
498
}
499
500
impl Div<BigUint> for u32 {
501
    type Output = BigUint;
502
503
    #[inline]
504
0
    fn div(self, other: BigUint) -> BigUint {
505
0
        match *other.data {
506
0
            [] => panic!("attempt to divide by zero"),
507
0
            [x] => BigUint::from(self as BigDigit / x),
508
0
            _ => BigUint::ZERO,
509
        }
510
0
    }
511
}
512
513
impl Div<u64> for BigUint {
514
    type Output = BigUint;
515
516
    #[inline]
517
0
    fn div(self, other: u64) -> BigUint {
518
0
        let (q, _) = div_rem(self, From::from(other));
519
0
        q
520
0
    }
521
}
522
impl DivAssign<u64> for BigUint {
523
    #[inline]
524
0
    fn div_assign(&mut self, other: u64) {
525
        // a vec of size 0 does not allocate, so this is fairly cheap
526
0
        let temp = mem::replace(self, Self::ZERO);
527
0
        *self = temp / other;
528
0
    }
529
}
530
531
impl 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
0
        fn div(self, other: BigUint) -> BigUint {
547
0
            match *other.data {
548
0
                [] => panic!("attempt to divide by zero"),
549
0
                [x] => BigUint::from(self / x),
550
0
                _ => BigUint::ZERO,
551
            }
552
0
        }
553
    );
554
}
555
556
impl Div<u128> for BigUint {
557
    type Output = BigUint;
558
559
    #[inline]
560
0
    fn div(self, other: u128) -> BigUint {
561
0
        let (q, _) = div_rem(self, From::from(other));
562
0
        q
563
0
    }
564
}
565
566
impl DivAssign<u128> for BigUint {
567
    #[inline]
568
0
    fn div_assign(&mut self, other: u128) {
569
0
        *self = &*self / other;
570
0
    }
571
}
572
573
impl 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
0
        fn div(self, other: BigUint) -> BigUint {
592
0
            match *other.data {
593
0
                [] => panic!("attempt to divide by zero"),
594
0
                [x] => BigUint::from(self / u128::from(x)),
595
0
                [x, y] => BigUint::from(self / big_digit::to_doublebigdigit(y, x)),
596
0
                _ => BigUint::ZERO,
597
            }
598
0
        }
599
    );
600
}
601
602
forward_val_ref_binop!(impl Rem for BigUint, rem);
603
forward_ref_val_binop!(impl Rem for BigUint, rem);
604
forward_val_assign!(impl RemAssign for BigUint, rem_assign);
605
606
impl Rem<BigUint> for BigUint {
607
    type Output = BigUint;
608
609
    #[inline]
610
0
    fn rem(self, other: BigUint) -> BigUint {
611
0
        if let Some(other) = other.to_u32() {
612
0
            &self % other
613
        } else {
614
0
            let (_, r) = div_rem(self, other);
615
0
            r
616
        }
617
0
    }
618
}
619
620
impl Rem<&BigUint> for &BigUint {
621
    type Output = BigUint;
622
623
    #[inline]
624
0
    fn rem(self, other: &BigUint) -> BigUint {
625
0
        if let Some(other) = other.to_u32() {
626
0
            self % other
627
        } else {
628
0
            let (_, r) = self.div_rem(other);
629
0
            r
630
        }
631
0
    }
632
}
633
impl RemAssign<&BigUint> for BigUint {
634
    #[inline]
635
0
    fn rem_assign(&mut self, other: &BigUint) {
636
0
        *self = &*self % other;
637
0
    }
638
}
639
640
promote_unsigned_scalars!(impl Rem for BigUint, rem);
641
promote_unsigned_scalars_assign!(impl RemAssign for BigUint, rem_assign);
642
forward_all_scalar_binop_to_ref_val!(impl Rem<u32> for BigUint, rem);
643
forward_all_scalar_binop_to_val_val!(impl Rem<u64> for BigUint, rem);
644
forward_all_scalar_binop_to_val_val!(impl Rem<u128> for BigUint, rem);
645
646
impl Rem<u32> for &BigUint {
647
    type Output = BigUint;
648
649
    #[inline]
650
0
    fn rem(self, other: u32) -> BigUint {
651
0
        rem_digit(self, other as BigDigit).into()
652
0
    }
653
}
654
impl RemAssign<u32> for BigUint {
655
    #[inline]
656
0
    fn rem_assign(&mut self, other: u32) {
657
0
        *self = &*self % other;
658
0
    }
659
}
660
661
impl Rem<&BigUint> for u32 {
662
    type Output = BigUint;
663
664
    #[inline]
665
0
    fn rem(mut self, other: &BigUint) -> BigUint {
666
0
        self %= other;
667
0
        From::from(self)
668
0
    }
669
}
670
671
macro_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
0
            fn rem_assign(&mut self, other: &BigUint) {
677
0
                *self = match other.$to_scalar() {
678
0
                    None => *self,
679
0
                    Some(0) => panic!("attempt to divide by zero"),
680
0
                    Some(v) => *self % v
681
                };
682
0
            }
Unexecuted instantiation: <u128 as core::ops::arith::RemAssign<&num_bigint::biguint::BigUint>>::rem_assign
Unexecuted instantiation: <usize as core::ops::arith::RemAssign<&num_bigint::biguint::BigUint>>::rem_assign
Unexecuted instantiation: <u64 as core::ops::arith::RemAssign<&num_bigint::biguint::BigUint>>::rem_assign
Unexecuted instantiation: <u32 as core::ops::arith::RemAssign<&num_bigint::biguint::BigUint>>::rem_assign
Unexecuted instantiation: <u16 as core::ops::arith::RemAssign<&num_bigint::biguint::BigUint>>::rem_assign
Unexecuted instantiation: <u8 as core::ops::arith::RemAssign<&num_bigint::biguint::BigUint>>::rem_assign
Unexecuted instantiation: <i128 as core::ops::arith::RemAssign<&num_bigint::biguint::BigUint>>::rem_assign
Unexecuted instantiation: <isize as core::ops::arith::RemAssign<&num_bigint::biguint::BigUint>>::rem_assign
Unexecuted instantiation: <i64 as core::ops::arith::RemAssign<&num_bigint::biguint::BigUint>>::rem_assign
Unexecuted instantiation: <i32 as core::ops::arith::RemAssign<&num_bigint::biguint::BigUint>>::rem_assign
Unexecuted instantiation: <i16 as core::ops::arith::RemAssign<&num_bigint::biguint::BigUint>>::rem_assign
Unexecuted instantiation: <i8 as core::ops::arith::RemAssign<&num_bigint::biguint::BigUint>>::rem_assign
683
        }
684
    }
685
}
686
687
// we can scalar %= BigUint for any scalar, including signed types
688
impl_rem_assign_scalar!(u128, to_u128);
689
impl_rem_assign_scalar!(usize, to_usize);
690
impl_rem_assign_scalar!(u64, to_u64);
691
impl_rem_assign_scalar!(u32, to_u32);
692
impl_rem_assign_scalar!(u16, to_u16);
693
impl_rem_assign_scalar!(u8, to_u8);
694
impl_rem_assign_scalar!(i128, to_i128);
695
impl_rem_assign_scalar!(isize, to_isize);
696
impl_rem_assign_scalar!(i64, to_i64);
697
impl_rem_assign_scalar!(i32, to_i32);
698
impl_rem_assign_scalar!(i16, to_i16);
699
impl_rem_assign_scalar!(i8, to_i8);
700
701
impl Rem<u64> for BigUint {
702
    type Output = BigUint;
703
704
    #[inline]
705
0
    fn rem(self, other: u64) -> BigUint {
706
0
        let (_, r) = div_rem(self, From::from(other));
707
0
        r
708
0
    }
709
}
710
impl RemAssign<u64> for BigUint {
711
    #[inline]
712
0
    fn rem_assign(&mut self, other: u64) {
713
0
        *self = &*self % other;
714
0
    }
715
}
716
717
impl Rem<BigUint> for u64 {
718
    type Output = BigUint;
719
720
    #[inline]
721
0
    fn rem(mut self, other: BigUint) -> BigUint {
722
0
        self %= other;
723
0
        From::from(self)
724
0
    }
725
}
726
727
impl Rem<u128> for BigUint {
728
    type Output = BigUint;
729
730
    #[inline]
731
0
    fn rem(self, other: u128) -> BigUint {
732
0
        let (_, r) = div_rem(self, From::from(other));
733
0
        r
734
0
    }
735
}
736
737
impl RemAssign<u128> for BigUint {
738
    #[inline]
739
0
    fn rem_assign(&mut self, other: u128) {
740
0
        *self = &*self % other;
741
0
    }
742
}
743
744
impl Rem<BigUint> for u128 {
745
    type Output = BigUint;
746
747
    #[inline]
748
0
    fn rem(mut self, other: BigUint) -> BigUint {
749
0
        self %= other;
750
0
        From::from(self)
751
0
    }
752
}
753
754
impl CheckedDiv for BigUint {
755
    #[inline]
756
0
    fn checked_div(&self, v: &BigUint) -> Option<BigUint> {
757
0
        if v.is_zero() {
758
0
            return None;
759
0
        }
760
0
        Some(self.div(v))
761
0
    }
762
}
763
764
impl CheckedEuclid for BigUint {
765
    #[inline]
766
0
    fn checked_div_euclid(&self, v: &BigUint) -> Option<BigUint> {
767
0
        if v.is_zero() {
768
0
            return None;
769
0
        }
770
0
        Some(self.div_euclid(v))
771
0
    }
772
773
    #[inline]
774
0
    fn checked_rem_euclid(&self, v: &BigUint) -> Option<BigUint> {
775
0
        if v.is_zero() {
776
0
            return None;
777
0
        }
778
0
        Some(self.rem_euclid(v))
779
0
    }
780
781
0
    fn checked_div_rem_euclid(&self, v: &Self) -> Option<(Self, Self)> {
782
0
        Some(self.div_rem_euclid(v))
783
0
    }
784
}
785
786
impl Euclid for BigUint {
787
    #[inline]
788
0
    fn div_euclid(&self, v: &BigUint) -> BigUint {
789
        // trivially same as regular division
790
0
        self / v
791
0
    }
792
793
    #[inline]
794
0
    fn rem_euclid(&self, v: &BigUint) -> BigUint {
795
        // trivially same as regular remainder
796
0
        self % v
797
0
    }
798
799
0
    fn div_rem_euclid(&self, v: &Self) -> (Self, Self) {
800
        // trivially same as regular division and remainder
801
0
        self.div_rem(v)
802
0
    }
803
}