bigdecimal/arithmetic/
division.rs1use crate::*;
5
6pub(crate) fn scaled_uint_division_into<'a, N, D>(
7 dest: &mut WithScale<BigUint>,
8 num: N,
9 den: D,
10 max_precision_bits: u64,
11)
12where
13 N: Into<WithScale<&'a BigUint>>,
14 D: Into<WithScale<&'a BigUint>>,
15{
16 impl_scaled_uint_division_into(dest, num.into(), den.into(), max_precision_bits);
17}
18
19pub(crate) fn impl_scaled_uint_division_into(
21 dest: &mut WithScale<BigUint>,
22 num: WithScale<&BigUint>,
23 den: WithScale<&BigUint>,
24 max_precision_bits: u64,
25) {
26 if true {
if !!den.value.is_zero() {
::core::panicking::panic("assertion failed: !den.value.is_zero()")
};
};debug_assert!(!den.value.is_zero());
27
28 if num.value.is_zero() {
29 dest.value = num.value.clone();
30 dest.scale = num.scale - den.scale;
31 return;
32 }
33
34 if den.value.is_one() && den.scale == 0 {
35 return;
36 }
37
38 let WithScale { value: num, scale: num_scale } = num;
39 let WithScale { value: den, scale: den_scale } = den;
40
41 match den.bits().checked_sub(num.bits()) {
43 None => {
44 dest.scale = num_scale - den_scale;
45 dest.value = num.clone();
46 }
47 Some(0) => {
48 dest.scale = num_scale - den_scale + 1;
49 dest.value = num * 10u8;
50 }
51 Some(diff) => {
52 let digit_count = bit_to_digit_count(diff);
53 dest.scale = num_scale - den_scale + digit_count as i64;
54 dest.value = BigUint::from(10u8).pow(digit_count);
55 dest.value *= num;
56 }
57 }
58
59 let (quotient, mut remainder) = dest.value.div_rem(den);
60
61 dest.value = quotient;
62
63 let mut precision_bits = dest.bits();
65
66 let step_scale = 1i64;
68 let step_factor = 10u64.pow(step_scale as u32);
69
70 remainder *= step_factor;
73
74 while !remainder.is_zero() && precision_bits < max_precision_bits {
75 let (q, r) = remainder.div_rem(den);
76 dest.scale += step_scale;
77 dest.value *= step_factor;
78 dest.value += q;
79 precision_bits = dest.bits();
80 remainder = r * step_factor;
81 }
82
83 let excess_u64_count = precision_bits.saturating_sub(max_precision_bits) / 64;
84
85 for _ in 1..excess_u64_count {
87 dest.value /= 1_0000000000000000000u64;
88 dest.scale -= 19;
89 }
90}