/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 | | } |