Skip to main content

bigdecimal/arithmetic/
multiplication.rs

1//! Routines for multiplying numbers
2//!
3#![allow(dead_code)]
4#![allow(clippy::identity_op)]
5
6use stdlib::num::NonZeroU64;
7use num_traits::AsPrimitive;
8
9use crate::*;
10use crate::rounding::{NonDigitRoundingData, InsigData};
11
12use super::log10;
13
14use crate::bigdigit::{
15    radix::{RadixType, RadixPowerOfTen, RADIX_u64, RADIX_10_u8, RADIX_10p19_u64},
16    endian::{Endianness, LittleEndian, BigEndian},
17    digitvec::{DigitVec, DigitSlice},
18};
19
20type BigDigitVec = DigitVec<RADIX_u64, LittleEndian>;
21type BigDigitVecBe = DigitVec<RADIX_u64, BigEndian>;
22type BigDigitSliceU64<'a> = DigitSlice<'a, RADIX_u64, LittleEndian>;
23
24type BigDigitVecP19 = DigitVec<RADIX_10p19_u64, LittleEndian>;
25type BigDigitSliceP19<'a> = DigitSlice<'a, RADIX_10p19_u64, LittleEndian>;
26
27type SmallDigitVec = DigitVec<RADIX_10_u8, LittleEndian>;
28
29const BASE2_BIGINT_MUL_THRESHOLD: u64 = 128;
30
31
32/// Generic form of BigDecimal *= BigDecimalRef
33#[inline(always)]
34pub(crate) fn mulassign_bigdecimal_ref<'a>(
35    dest: &mut BigDecimal,
36    rhs: impl Into<BigDecimalRef<'a>>,
37) {
38   impl_mulassign_bigdecimal_ref(dest, rhs.into());
39}
40
41/// Implementation of BigDecimal *= BigDecimalRef
42pub(crate) fn impl_mulassign_bigdecimal_ref(
43    dest: &mut BigDecimal,
44    rhs: BigDecimalRef,
45) {
46    dest.scale += rhs.scale;
47    mulassign_bigint_biguint_ref(&mut dest.int_val, rhs.digits);
48    if rhs.sign == Sign::Minus {
49        dest.int_val *= -1;
50    }
51}
52
53/// Implement bigint *= biguint
54///
55/// Saves clone for small values
56///
57pub(crate) fn mulassign_bigint_biguint_ref(
58    dest: &mut BigInt,
59    n: &BigUint,
60) {
61    match n.to_u128() {
62        Some(n) => {
63            dest.mul_assign(n);
64        }
65        None => {
66            dest.mul_assign(BigInt::from(n.clone()));
67        }
68    }
69}
70
71/// Generic form of BigDecimal = BigDecimalRef * BigDecimalRef
72pub(crate) fn multiply_decimals_with_context<'a>(
73    dest: &mut BigDecimal,
74    a: impl Into<BigDecimalRef<'a>>,
75    b: impl Into<BigDecimalRef<'a>>,
76    ctx: &Context,
77) {
78    let a = a.into();
79    let b = b.into();
80
81    impl_multiply_decimals_with_context(dest, a, b, ctx);
82}
83
84/// Generic form of BigDecimal = BigDecimalRef * BigDecimalRef
85pub fn impl_multiply_decimals_with_context(
86    dest: &mut BigDecimal,
87    a: BigDecimalRef,
88    b: BigDecimalRef,
89    ctx: &Context,
90) {
91    if a.is_zero() || b.is_zero() {
92        *dest = BigDecimal::zero();
93        return;
94    }
95
96    let sign = a.sign() * b.sign();
97    let rounding_data = NonDigitRoundingData {
98        sign: sign,
99        mode: ctx.rounding_mode(),
100    };
101
102    let a_uint = a.digits;
103    let b_uint = b.digits;
104
105    match (a, b.is_one_quickcheck(), b, a.is_one_quickcheck()) {
106        (x, Some(true), _, _) | (_, _, x, Some(true)) => {
107            let WithScale {
108                value: rounded_uint,
109                scale: rounded_scale,
110            } = rounding_data.round_biguint_to_prec(x.digits.clone(), ctx.precision());
111
112            dest.scale = x.scale + rounded_scale;
113            dest.int_val = BigInt::from_biguint(sign, rounded_uint);
114            return;
115        }
116        _ => {}
117    }
118
119    if let (Some(x), Some(y)) = (a_uint.to_u64(), b_uint.to_u64()) {
120        multiply_scaled_u64_into_decimal(
121            dest,
122            WithScale { value: x, scale: a.scale },
123            WithScale { value: y, scale: b.scale },
124            ctx.precision(),
125            rounding_data,
126        );
127        if true {
    {
        match (&dest.sign(), &sign) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(dest.sign(), sign);
128        return;
129    }
130
131    let a_vec = BigDigitVec::from(a_uint);
132    let b_vec = BigDigitVec::from(b_uint);
133
134    let digit_vec = BigDigitVec::new();
135    let mut digit_vec_scale = WithScale::from((digit_vec, 0));
136
137    multiply_scaled_u64_slices_with_prec_into(
138        &mut digit_vec_scale,
139        WithScale { value: a_vec.as_digit_slice(), scale: a.scale },
140        WithScale { value: b_vec.as_digit_slice(), scale: b.scale },
141        ctx.precision(),
142        rounding_data,
143    );
144
145    dest.int_val = BigInt::from_biguint(sign, digit_vec_scale.value.into());
146    dest.scale = digit_vec_scale.scale;
147}
148
149pub(crate) fn multiply_scaled_u64_into_decimal(
150    dest: &mut BigDecimal,
151    a: WithScale<u64>,
152    b: WithScale<u64>,
153    prec: NonZeroU64,
154    rounding_data: NonDigitRoundingData,
155) {
156    use crate::arithmetic::decimal::count_digits_u128;
157
158    let mut product = a.value as u128 * b.value as u128;
159    let digit_count = count_digits_u128(product) as u64;
160
161    let mut digits_to_remove = digit_count.saturating_sub(prec.get()) as u32;
162
163    if digits_to_remove == 0 {
164        dest.int_val = BigInt::from_biguint(rounding_data.sign, product.into());
165        dest.scale = a.scale + b.scale;
166        return;
167    }
168
169    let shifter = 10u128.pow(digits_to_remove - 1);
170    let (hi, trailing) = product.div_rem(&shifter);
171    let (shifted_product, insig_digit) = hi.div_rem(&10);
172    let sig_digit = (shifted_product % 10) as u8;
173
174    let rounded_digit = rounding_data.round_pair(
175        (sig_digit, insig_digit as u8),
176        trailing == 0,
177    );
178
179    product = shifted_product - sig_digit as u128 + rounded_digit as u128;
180
181    if rounded_digit >= 10 {
182        if true {
    {
        match (&rounded_digit, &10) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(rounded_digit, 10);
183
184        let old_digit_count = digit_count - digits_to_remove as u64;
185        if true {
    {
        match (&old_digit_count, &(count_digits_u128(shifted_product) as u64))
            {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(old_digit_count, count_digits_u128(shifted_product) as u64);
186
187        let rounded_digit_count = count_digits_u128(product) as u64;
188        if old_digit_count != rounded_digit_count {
189            if true {
    {
        match (&rounded_digit_count, &(old_digit_count + 1)) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(rounded_digit_count, old_digit_count + 1);
190            product /= 10;
191            digits_to_remove += 1;
192        }
193    }
194
195    let digit_array = mul_split_u128_to_u32x4(product);
196    dest.int_val.assign_from_slice(rounding_data.sign, &digit_array);
197
198    dest.scale = a.scale + b.scale - digits_to_remove as i64;
199}
200
201/// Multiply digits in slices a and b, ignoring all factors that come from
202/// digits "below" the given index (which is stored at index 0 in the dest)
203///
204/// ```ignore
205///     a₀ a₁ a₂ a₃ ...
206///  b₀| 0  1  2  3
207///  b₁| 1  2  3  4   <- indexes in vector of the 'full' product
208///  b₂| 2  3  4  5 ...
209///  ```
210///  If given idx '3', `dest[0] = a₁b₂ + a₂b₁ + a₃b₀` and `dest[1] = a₂b₂+...` etc
211///
212/// Carrying from lower digits is not calculated, so care must be given
213/// to ensure data enough digits are provided.
214///
215pub(crate) fn multiply_at_product_index<R, E, EA, EB>(
216    dest: &mut DigitVec<R, E>,
217    a: DigitSlice<R, EA>,
218    b: DigitSlice<R, EB>,
219    idx: usize,
220) where
221    R: RadixType,
222    E: Endianness,
223    EA: Endianness,
224    EB: Endianness,
225{
226    if true {
    if !(b.len() <= a.len()) {
        ::core::panicking::panic("assertion failed: b.len() <= a.len()")
    };
};debug_assert!(b.len() <= a.len());
227
228    dest.resize((a.len() + b.len()).saturating_sub(idx));
229
230    let b_idx_min = idx.saturating_sub(a.len() - 1);
231
232    for (b_idx, &x) in b.iter_le().enumerate().skip(b_idx_min).rev() {
233        let a_idx_min = idx.saturating_sub(b_idx);
234        if true {
    if !(a_idx_min < a.len()) {
        ::core::panicking::panic("assertion failed: a_idx_min < a.len()")
    };
};debug_assert!(a_idx_min < a.len());
235
236        let dest_idx = a_idx_min + b_idx - idx;
237
238        let mut dest_digits = dest.iter_le_mut().skip(dest_idx);
239        let mut carry = Zero::zero();
240        for &y in a.iter_le().skip(a_idx_min) {
241            R::carrying_mul_add_inplace(
242                x, y, dest_digits.next().unwrap(), &mut carry
243            );
244        }
245        R::add_carry_into(dest_digits, &mut carry);
246        if !carry.is_zero() {
247            dest.push_significant_digit(carry);
248        }
249    }
250}
251
252
253pub(crate) fn multiply_at_idx_into<R: RadixType>(
254    dest: &mut DigitVec<R, LittleEndian>,
255    a: DigitSlice<R, LittleEndian>,
256    b: DigitSlice<R, LittleEndian>,
257    idx: usize,
258) {
259    if true {
    if !(a.len() + b.len() <= dest.len() + idx) {
        ::core::panicking::panic("assertion failed: a.len() + b.len() <= dest.len() + idx")
    };
};debug_assert!(a.len() + b.len() <= dest.len() + idx);
260    for (ia, &da) in a.digits.iter().enumerate() {
261        if da.is_zero() {
262            continue;
263        }
264        let mut carry = Zero::zero();
265        for (&db, result) in b.digits.iter().zip(dest.digits.iter_mut().skip(idx + ia)) {
266            R::carrying_mul_add_inplace(da, db, result, &mut carry);
267        }
268        dest.add_value_at(idx + ia + b.len(), carry);
269    }
270}
271
272pub(crate) fn multiply_big_int_with_ctx(a: &BigInt, b: &BigInt, ctx: Context) -> WithScale<BigInt> {
273    let sign = a.sign() * b.sign();
274    // Rounding prec: usize
275    let rounding_data = NonDigitRoundingData {
276        sign: sign,
277        mode: ctx.rounding_mode(),
278    };
279
280    // if bits are under this threshold, just multiply full integer and round
281    if a.bits() + b.bits() < BASE2_BIGINT_MUL_THRESHOLD {
282        return ctx.round_bigint(a * b);
283    }
284
285    let mut tmp = Vec::new();
286    let a_p19_vec = BigDigitVecP19::from_biguint_using_tmp(a.magnitude(), &mut tmp);
287    let b_p19_vec = BigDigitVecP19::from_biguint_using_tmp(b.magnitude(), &mut tmp);
288
289    let mut result = WithScale::default();
290    multiply_slices_with_prec_into_p19(
291        &mut result,
292        a_p19_vec.as_digit_slice(),
293        b_p19_vec.as_digit_slice(),
294        ctx.precision(),
295        rounding_data
296    );
297
298    WithScale {
299        scale: result.scale,
300        value: result.value.into_bigint(sign),
301    }
302}
303
304/// Store product of 'a' & 'b' into dest, only calculating 'prec'
305/// number of digits
306///
307/// Use 'rounding' to round at requested position.
308/// Assumes 'a' & 'b' are full numbers, so all insignificant digits
309/// are zero.
310///
311pub(crate) fn multiply_slices_with_prec_into_p19(
312    dest: &mut WithScale<BigDigitVecP19>,
313    a: BigDigitSliceP19,
314    b: BigDigitSliceP19,
315    prec: NonZeroU64,
316    rounding: NonDigitRoundingData
317) {
318    multiply_slices_with_prec_into_p19_z(dest, a, b, prec, rounding, true)
319}
320
321
322/// Store product of 'a' & 'b' into dest, only calculating 'prec' number of digits
323///
324/// Use 'rounding' information to round at requested position.
325/// The 'assume_trailing_zeros' parameter determines proper rounding technique if
326/// 'a' & 'b' are partial numbers, where trailing insignificant digits may or may
327/// not be zero.
328///
329pub(crate) fn multiply_slices_with_prec_into_p19_z(
330    dest: &mut WithScale<BigDigitVecP19>,
331    a: BigDigitSliceP19,
332    b: BigDigitSliceP19,
333    prec: NonZeroU64,
334    rounding: NonDigitRoundingData,
335    assume_trailing_zeros: bool,
336) {
337    use super::bigdigit::alignment::BigDigitSplitter;
338    use super::bigdigit::alignment::BigDigitSliceSplitterIter;
339    type R = RADIX_10p19_u64;
340
341    if a.len() < b.len() {
342        // ensure a is the longer of the two digit slices
343        return multiply_slices_with_prec_into_p19_z(dest, b, a, prec, rounding, assume_trailing_zeros);
344    }
345
346    dest.value.clear();
347
348    if b.is_all_zeros() || a.is_all_zeros() {
349        // multiplication by zero: return after clearing dest
350        return;
351    }
352
353    if true {
    {
        match (&a.len(), &0) {
            (left_val, right_val) => {
                if *left_val == *right_val {
                    let kind = ::core::panicking::AssertKind::Ne;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_ne!(a.len(), 0);
354    if true {
    {
        match (&b.len(), &0) {
            (left_val, right_val) => {
                if *left_val == *right_val {
                    let kind = ::core::panicking::AssertKind::Ne;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_ne!(b.len(), 0);
355
356    let WithScale { value: dest, scale: result_scale } = dest;
357
358    // minimum possible length of each integer, given length of bigdigit vecs
359    let pessimistic_product_digit_count = (a.len() + b.len() - 2) * R::DIGITS + 1;
360
361    // require more digits of precision for overflow and rounding
362    // max number of digits produced by adding all bigdigits at any
363    // particular "digit-index" i of the product
364    //  log10( Σ a_m × b_n (∀ m+n=i) )
365    let max_digit_sum_width = (2.0 * log10(R::max() as f64) + log10(b.len() as f64)).ceil() as usize;
366    let max_bigdigit_sum_width = R::divceil_digit_count(max_digit_sum_width);
367    // the "index" of the product which could affect the significant results
368    let digits_to_skip = pessimistic_product_digit_count.saturating_sub(prec.get() as usize + 1);
369    let bigdigits_to_skip = R::divceil_digit_count(digits_to_skip)
370                              .saturating_sub(max_bigdigit_sum_width);
371
372    let a_start;
373    let b_start;
374    if bigdigits_to_skip == 0 {
375        // we've requested more digits than product will produce; don't skip any digits
376        a_start = 0;
377        b_start = 0;
378    } else {
379        // the indices of the least significant bigdigits in a and b which may contribute
380        // to the significant digits in the product
381        a_start = bigdigits_to_skip.saturating_sub(b.len());
382        b_start = bigdigits_to_skip.saturating_sub(a.len());
383    }
384
385    let a_sig = a.trim_insignificant(a_start);
386    let b_sig = b.trim_insignificant(b_start);
387
388    let a_sig_digit_count = a_sig.count_decimal_digits();
389    let b_sig_digit_count = b_sig.count_decimal_digits();
390
391    // calculate maximum number of digits from product
392    let max_sigproduct_bigdigit_count = R::divceil_digit_count(a_sig_digit_count + b_sig_digit_count + 1);
393    let mut product =
394        BigDigitVecP19::with_capacity(max_sigproduct_bigdigit_count + max_bigdigit_sum_width + 1);
395
396    *result_scale -= (R::DIGITS * bigdigits_to_skip) as i64;
397
398    multiply_at_product_index(&mut product, a, b, bigdigits_to_skip);
399    product.remove_leading_zeros();
400
401    let product_digit_count = product.count_decimal_digits();
402
403    // precision plus the rounding digit
404    let digits_to_remove = product_digit_count.saturating_sub(prec.get() as usize);
405    if digits_to_remove == 0 {
406        if true {
    {
        match (&a_start, &0) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(a_start, 0);
407        if true {
    {
        match (&b_start, &0) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(b_start, 0);
408        if true {
    {
        match (&bigdigits_to_skip, &0) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(bigdigits_to_skip, 0);
409
410        // no need to trim the results, everything was significant;
411        *dest = product;
412        return;
413    }
414
415    // removing insignificant digits decreases the scale
416    *result_scale -= digits_to_remove as i64;
417
418    // keep adding more multiplication terms if the number ends with 999999...., until
419    // the nines stop or it overflows.
420    // NOTE: the insignificant digits in 'product' will be _wrong_ and must be ignored
421    let trailing_zeros = assume_trailing_zeros && calculate_partial_product_trailing_zeros(
422        &mut product, a, b, bigdigits_to_skip, digits_to_remove
423    );
424
425    // remove the digits, returning the top one to be used
426    let insig_digit = product.shift_n_digits_returning_high(digits_to_remove);
427    let sig_digit = (product.digits[0] % 10) as u8;
428
429    let insig_rounding_data = InsigData {
430        rounding_data: rounding,
431        digit: insig_digit,
432        trailing_zeros,
433    };
434
435    let rounded_digit = insig_rounding_data.round_digit(sig_digit);
436
437    let mut carry = rounded_digit as u64;
438
439    product.digits[0] -= sig_digit as u64;
440
441    R::add_carry_into_slice(
442        &mut product.digits, &mut carry
443    );
444
445    if carry != 0 {
446        if true {
    if !product.digits.iter().all(|&d| d == 0) {
        ::core::panicking::panic("assertion failed: product.digits.iter().all(|&d| d == 0)")
    };
};debug_assert!(product.digits.iter().all(|&d| d == 0));
447        *result_scale -= 1;
448        *product.digits.last_mut().unwrap() = (R::RADIX as u64) / 10;
449    }
450
451    if rounded_digit == 10 && product.count_decimal_digits() != prec.get() as usize {
452        *result_scale -= 1;
453
454        if let Some((hi, zeros)) = product.digits.split_last_mut() {
455            if true {
    if !(*hi >= 10) {
        ::core::panicking::panic("assertion failed: *hi >= 10")
    };
};debug_assert!(*hi >= 10);
456            if true {
    if !zeros.iter().all(|&d| d == 0) {
        ::core::panicking::panic("assertion failed: zeros.iter().all(|&d| d == 0)")
    };
};debug_assert!(zeros.iter().all(|&d| d == 0));
457            *hi /= 10;
458        } else {
459            ::core::panicking::panic("internal error: entered unreachable code");unreachable!();
460        }
461    }
462
463    *dest = product;
464}
465
466/// Store `a * b` into dest, to limited precision
467pub(crate) fn multiply_scaled_u64_slices_with_prec_into(
468    dest: &mut WithScale<BigDigitVec>,
469    a: WithScale<BigDigitSliceU64>,
470    b: WithScale<BigDigitSliceU64>,
471    prec: NonZeroU64,
472    rounding: NonDigitRoundingData,
473) {
474    let a_base10: BigDigitVecP19 = a.value.into();
475    let b_base10: BigDigitVecP19 = b.value.into();
476
477    let mut product = WithScale::default();
478    multiply_slices_with_prec_into_p19(
479        &mut product,
480        a_base10.as_digit_slice(),
481        b_base10.as_digit_slice(),
482        prec,
483        rounding,
484    );
485
486    dest.scale = a.scale + b.scale + product.scale;
487    dest.value = product.value.into();
488}
489
490/// Calculate the 'backwards' product of a & b, stopping when it can be
491/// proven that no further overflow can happen
492///
493/// Return true if the product after overflow-calculation has all
494/// trailing zeros.
495///
496/// Parameter 'v' here is the pre-calculated "extended" product of a & b,
497/// extended meaning it has incorrect insignificant digits that were
498/// calculated to add overflow/carrys into the significant digits.
499/// This function continues multiplying trailing digits if there is a
500/// chance that a rounding.
501///
502/// 'product_idx' is the index of the true product where v starts
503/// (i.e. v[0] corresponds to true_product[product_idx], used here for
504/// calculating the insignificant product of a and b, backwards.
505///
506/// 'digits_to_remove' is the number of digits in v that should be
507/// considered insignificant, and may be changed by this function.
508///
509fn calculate_partial_product_trailing_zeros(
510    v: &mut BigDigitVecP19,
511    a: BigDigitSliceP19,
512    b: BigDigitSliceP19,
513    product_idx: usize,
514    digits_to_remove: usize,
515) -> bool {
516    type R = RADIX_10p19_u64;
517
518    if digits_to_remove == 0 {
519        return true;
520    }
521
522    if true {
    if !(b.len() <= a.len()) {
        ::core::panicking::panic("assertion failed: b.len() <= a.len()")
    };
};debug_assert!(b.len() <= a.len());
523    if true {
    if !(digits_to_remove <= v.count_decimal_digits()) {
        ::core::panicking::panic("assertion failed: digits_to_remove <= v.count_decimal_digits()")
    };
};debug_assert!(digits_to_remove <= v.count_decimal_digits());
524
525    let (insig_bd_count, insig_d_count) = R::divmod_digit_count(digits_to_remove);
526    if true {
    if !(insig_bd_count > 0 || insig_d_count > 0) {
        ::core::panicking::panic("assertion failed: insig_bd_count > 0 || insig_d_count > 0")
    };
};debug_assert!(insig_bd_count > 0 || insig_d_count > 0);
527
528    let trailing_zeros;
529    let trailing_nines;
530
531    // index of the first "full" insignificant big-digit
532    let top_insig_idx;
533
534    match (insig_bd_count, insig_d_count as u8) {
535        (0, 0) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
536        (0, 1) => {
537            return true;
538        }
539        (0, 2) => {
540            return v.digits[0] % 10 == 0;
541        }
542        (0, n) => {
543            let splitter = ten_to_the_u64(n - 1);
544            return v.digits[0] % splitter == 0;
545        }
546        (1, 0) => {
547            let splitter = ten_to_the_u64(R::DIGITS as u8 - 1);
548            return v.digits[0] % splitter == 0;
549        }
550        (1, 1) => {
551            return v.digits[0] == 0;
552        }
553        (i, 1) => {
554            // special case when the 'top' insignificant digit is
555            // with the other digits
556            trailing_zeros = v.digits[i - 1] == 0;
557            trailing_nines = v.digits[i - 1] == R::max();
558            top_insig_idx = i - 1;
559        }
560        (i, 0) => {
561            // split on a boundary, check previous bigdigit
562            let insig = v.digits[i - 1];
563            let splitter = ten_to_the_u64(R::DIGITS as u8 - 1);
564            let insig_digits = insig % splitter;
565            trailing_zeros = insig_digits == 0
566                             && v.iter_le().take(i - 1).all(Zero::is_zero);
567            trailing_nines = insig_digits == splitter - 1;
568            top_insig_idx = i - 2;
569        }
570        (i, n) => {
571            let insig = v.digits[i];
572            let splitter = ten_to_the_u64(n - 1);
573            let insig_digits = insig % splitter;
574            trailing_zeros = insig_digits == 0
575                             && v.iter_le().take(i).all(Zero::is_zero);
576            trailing_nines = insig_digits == splitter - 1;
577            top_insig_idx = i - 1;
578        }
579    }
580
581
582    // the insignificant digits should be at least one bigdigit wider
583    // than the maximum overflow from one iteration of preceding digits
584    // debug_assert!(insig_bd_count >= max_bigdigit_sum_width, "{}, {}", insig_bd_count, max_bigdigit_sum_width);
585
586    // not zero and no chance for overflow
587    if !trailing_zeros && !trailing_nines {
588        return false;
589    }
590
591    if product_idx == 0 {
592        // no new multiplications needs to happen, just return if
593        // product has trailing zeros
594        return trailing_zeros
595            && v.digits[..top_insig_idx].iter().all(|&d| d == 0);
596    }
597
598    // check if last bigdigit in product is not zero before iterative multiplication
599    if trailing_zeros && (a.digits[0].saturating_mul(b.digits[0])) != 0 {
600       return false;
601    }
602
603    for idx in (0..product_idx).rev() {
604        let a_range;
605        let b_range;
606        if idx < b.len() {
607            // up to and including 'idx'
608            a_range = 0..idx + 1;
609            b_range = 0..idx + 1;
610        } else if idx < a.len() {
611            a_range = idx - b.len() + 1..idx + 1;
612            b_range = 0..b.len();
613        } else {
614            a_range = idx - b.len() + 1..a.len();
615            b_range = idx - a.len() + 1..b.len();
616        }
617        if true {
    {
        match (&(a_range.end - a_range.start), &(b_range.end - b_range.start))
            {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(
618            a_range.end - a_range.start,
619            b_range.end - b_range.start,
620        );
621
622        let a_start = a_range.start;
623        let b_start = b_range.start;
624        let a_digits = a.digits[a_range].iter();
625        let b_digits = b.digits[b_range].iter().rev();
626
627        let mut d0 = 0;
628
629        let mut carry = Zero::zero();
630        for (&x, &y) in a_digits.zip(b_digits) {
631            R::carrying_mul_add_inplace(x, y, &mut d0, &mut carry);
632            R::add_carry_into(v.digits.iter_mut(), &mut carry);
633        }
634        if true {
    {
        match (&carry, &0) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(carry, 0);
635
636        let top_insig = v.digits[top_insig_idx];
637        if top_insig != R::max() {
638            // we have overflowed!
639            return v.least_n_are_zero(top_insig_idx)
640                && a.least_n_are_zero(a_start)
641                && b.least_n_are_zero(b_start);
642        }
643
644        // shift the insignificant digits in the vector by one
645        // (i.e. the '9999999' in highest insig bigdigit may be ignored)
646        v.digits.copy_within(..top_insig_idx, 1);
647        v.digits[0] = d0;
648    }
649
650    // never overflowed, therefore "trailing zeros" is false
651    return false;
652}
653
654/// Calculate dest = a * b to at most 'prec' number of bigdigits, truncating (not rounding)
655/// the results.
656///
657/// The scale of these vector/slices is number of *bigdigits*, not number of digits.
658///
659/// Returns the number of 'skipped' bigdigits in the result.
660///
661pub(crate) fn mul_scaled_slices_truncating_into<R, E, EA, EB>(
662    dest: &mut WithScale<DigitVec<R, E>>,
663    a: WithScale<DigitSlice<'_, R, EA>>,
664    b: WithScale<DigitSlice<'_, R, EB>>,
665    prec: u64,
666) -> usize
667where
668    R: RadixType,
669    E: Endianness,
670    EA: Endianness,
671    EB: Endianness,
672{
673    use super::bigdigit::alignment::BigDigitSplitter;
674    use super::bigdigit::alignment::BigDigitSliceSplitterIter;
675    type R = RADIX_10p19_u64;
676
677    if a.value.len() < b.value.len() {
678        // ensure a is the longer of the two digit slices
679        return mul_scaled_slices_truncating_into(dest, b, a, prec);
680    }
681
682    let WithScale { value: product, scale: dest_scale } = dest;
683    let WithScale { value: a, scale: a_scale } = a;
684    let WithScale { value: b, scale: b_scale } = b;
685
686    *dest_scale = a_scale + b_scale;
687    product.clear();
688
689    if b.is_all_zeros() || a.is_all_zeros() {
690        // multiplication by zero: return after clearing dest
691        return 0;
692    }
693
694    if true {
    {
        match (&a.len(), &0) {
            (left_val, right_val) => {
                if *left_val == *right_val {
                    let kind = ::core::panicking::AssertKind::Ne;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_ne!(a.len(), 0);
695    if true {
    {
        match (&b.len(), &0) {
            (left_val, right_val) => {
                if *left_val == *right_val {
                    let kind = ::core::panicking::AssertKind::Ne;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_ne!(b.len(), 0);
696
697    // require more digits of precision for overflow and rounding
698    // max number of digits produced by adding all bigdigits at any
699    // particular "digit-index" i of the product
700    //  log10( Σ a_m × b_n (∀ m+n=i) )
701    let max_digit_sum_width = (2.0 * log10(R::max() as f64) + log10(b.len() as f64)).ceil() as usize;
702    let max_bigdigit_sum_width = R::divceil_digit_count(max_digit_sum_width);
703
704    let max_product_size = a.len() + b.len();
705    let max_vector_size = prec as usize + max_bigdigit_sum_width;
706    let bigdigits_to_skip = max_product_size.saturating_sub(max_vector_size);
707
708    *dest_scale -= bigdigits_to_skip as i64;
709
710    multiply_at_product_index(product, a, b, bigdigits_to_skip);
711    product.remove_leading_zeros();
712    let extra_digit_count = product.len().saturating_sub(prec as usize);
713    product.remove_insignificant_digits(extra_digit_count);
714    *dest_scale -= extra_digit_count as i64;
715
716    return bigdigits_to_skip;
717}
718
719
720/// split u64 into high and low bits
721fn split_u64(x: u64) -> (u64, u64) {
722    x.div_rem(&(1 << 32))
723}
724
725fn mul_split_u64_u64(a: u64, b: u64) -> [u32; 4] {
726    let p = u128::from(a) * u128::from(b);
727    mul_split_u128_to_u32x4(p)
728}
729
730fn mul_split_u128_to_u32x4(n: u128) -> [u32; 4] {
731    [
732        (n >> 0).as_(),
733        (n >> 32).as_(),
734        (n >> 64).as_(),
735        (n >> 96).as_(),
736    ]
737}
738
739/// Add carry into dest
740#[inline]
741fn _apply_carry_u64(dest: &mut [u32], mut idx: usize, mut carry: u64) {
742    while carry != 0 {
743        idx += 1;
744        let (c, r) = split_u64(dest[idx] as u64 + carry);
745        dest[idx] = r as u32;
746        carry = c;
747    }
748}
749
750/// Evaluate (a + (b << 64))^2, where a and b are u64's, storing
751/// the result as u32's in *dest*, starting at location *idx*
752///
753/// This is useful for a and b as adjacent big-digits in a big-
754/// number, or components of a u128, squared.
755///
756/// (a + (b << 64))^2 = a^2 + (2 ab) << 64 + (b^2) << 128
757///
758pub(crate) fn multiply_2_u64_into_u32(
759    dest: &mut [u32], mut idx: usize, a: u64, b: u64
760) {
761    let [aa0, aa1, aa2, aa3] = mul_split_u64_u64(a, a);
762    let [ab0, ab1, ab2, ab3] = mul_split_u64_u64(a, b);
763    let [bb0, bb1, bb2, bb3] = mul_split_u64_u64(b, b);
764
765    let (carry, r0) = split_u64(dest[idx] as u64         + aa0 as u64);
766    dest[idx] = r0 as u32;
767
768    idx += 1;
769    let (carry, r1) = split_u64(dest[idx] as u64 + carry + aa1 as u64);
770    dest[idx] = r1 as u32;
771
772    idx += 1;
773    let (carry, r2) = split_u64(dest[idx] as u64 + carry + aa2 as u64 + ab0 as u64 * 2);
774    dest[idx] = r2 as u32;
775
776    idx += 1;
777    let (carry, r3) = split_u64(dest[idx] as u64 + carry + aa3 as u64 + ab1 as u64 * 2);
778    dest[idx] = r3 as u32;
779
780    idx += 1;
781    let (carry, r4) = split_u64(dest[idx] as u64 + carry              + ab2 as u64 * 2 + bb0 as u64);
782    dest[idx] = r4 as u32;
783
784    idx += 1;
785    let (carry, r5) = split_u64(dest[idx] as u64 + carry              + ab3 as u64 * 2 + bb1 as u64);
786    dest[idx] = r5 as u32;
787
788    idx += 1;
789    let (carry, r6) = split_u64(dest[idx] as u64 + carry                               + bb2 as u64);
790    dest[idx] = r6 as u32;
791
792    idx += 1;
793    let (carry, r7) = split_u64(dest[idx] as u64 + carry                               + bb3 as u64);
794    dest[idx] = r7 as u32;
795
796    _apply_carry_u64(dest, idx + 1, carry);
797}
798
799/// dest += ((b<<64) + a) * ((z<<64) + y)
800pub(crate) fn _multiply_into_4_u64(
801    dest: &mut [u32], idx: usize, a: u64, b: u64, y: u64, z: u64
802) {
803    let [ay0, ay1, ay2, ay3] = mul_split_u64_u64(a, y);
804    let [az0, az1, az2, az3] = mul_split_u64_u64(a, z);
805    let [by0, by1, by2, by3] = mul_split_u64_u64(b, y);
806    let [bz0, bz1, bz2, bz3] = mul_split_u64_u64(b, z);
807
808    let (carry, r0) = split_u64(dest[idx + 0] as u64         + (ay0 as u64                                       ) * 2);
809    dest[idx + 0] = r0 as u32;
810
811    let (carry, r1) = split_u64(dest[idx + 1] as u64 + carry + (ay1 as u64                                       ) * 2);
812    dest[idx + 1] = r1 as u32;
813
814    let (carry, r2) = split_u64(dest[idx + 2] as u64 + carry + (ay2 as u64 + az0 as u64 + by0 as u64             ) * 2);
815    dest[idx + 2] = r2 as u32;
816
817    let (carry, r3) = split_u64(dest[idx + 3] as u64 + carry + (ay3 as u64 + az1 as u64 + by1 as u64             ) * 2);
818    dest[idx + 3] = r3 as u32;
819
820    let (carry, r4) = split_u64(dest[idx + 4] as u64 + carry + (             az2 as u64 + by2 as u64 + bz0 as u64) * 2);
821    dest[idx + 4] = r4 as u32;
822
823    let (carry, r5) = split_u64(dest[idx + 5] as u64 + carry + (             az3 as u64 + by3 as u64 + bz1 as u64) * 2);
824    dest[idx + 5] = r5 as u32;
825
826    let (carry, r6) = split_u64(dest[idx + 6] as u64 + carry + (                                       bz2 as u64) * 2);
827    dest[idx + 6] = r6 as u32;
828
829    let (carry, r7) = split_u64(dest[idx + 7] as u64 + carry + (                                       bz3 as u64) * 2);
830    dest[idx + 7] = r7 as u32;
831
832    _apply_carry_u64(dest, idx + 8, carry);
833}
834
835/// dest[idx..] += a ** 2
836pub(crate) fn _multiply_1_u64_into_u32(
837    dest: &mut [u32],
838    mut idx: usize,
839    a: u64
840) {
841    let [a0, a1, a2, a3] = mul_split_u64_u64(a, a);
842
843    let (carry, r0) = split_u64(dest[idx] as u64 + a0 as u64);
844    dest[idx] = r0 as u32;
845
846    idx += 1;
847    let (carry, r1) = split_u64(dest[idx] as u64 + carry + a1 as u64);
848    dest[idx] = r1 as u32;
849
850    idx += 1;
851    let (carry, r2) = split_u64(dest[idx] as u64 + carry + a2 as u64);
852    dest[idx] = r2 as u32;
853
854    idx += 1;
855    let (carry, r3) = split_u64(dest[idx] as u64 + carry + a3 as u64);
856    dest[idx] = r3 as u32;
857
858    _apply_carry_u64(dest, idx + 1, carry);
859}
860
861
862/// Evaluate (a + b << 64)^2 and store in dest at location idx
863pub(crate) fn _multiply_2_u64_into_u32(
864    dest: &mut [u32],
865    mut idx: usize,
866    a: u64,
867    b: u64,
868) {
869    let [aa0, aa1, aa2, aa3] =  mul_split_u64_u64(a, a);
870    let [ab0, ab1, ab2, ab3] =  mul_split_u64_u64(a, b);
871    let [bb0, bb1, bb2, bb3] =  mul_split_u64_u64(b, b);
872
873    let (carry, r0) = split_u64(dest[idx] as u64         + aa0 as u64);
874    dest[idx] = r0 as u32;
875
876    idx += 1;
877    let (carry, r1) = split_u64(dest[idx] as u64 + carry + aa1 as u64);
878    dest[idx] = r1 as u32;
879
880    idx += 1;
881    let (carry, r2) = split_u64(dest[idx] as u64 + carry + aa2 as u64 + ab0 as u64 * 2);
882    dest[idx] = r2 as u32;
883
884    idx += 1;
885    let (carry, r3) = split_u64(dest[idx] as u64 + carry + aa3 as u64 + ab1 as u64 * 2);
886    dest[idx] = r3 as u32;
887
888    idx += 1;
889    let (carry, r4) = split_u64(dest[idx] as u64 + carry              + ab2 as u64 * 2 + bb0 as u64);
890    dest[idx] = r4 as u32;
891
892    idx += 1;
893    let (carry, r5) = split_u64(dest[idx] as u64 + carry              + ab3 as u64 * 2 + bb1 as u64);
894    dest[idx] = r5 as u32;
895
896    idx += 1;
897    let (carry, r6) = split_u64(dest[idx] as u64 + carry                               + bb2 as u64);
898    dest[idx] = r6 as u32;
899
900    idx += 1;
901    let (carry, r7) = split_u64(dest[idx] as u64 + carry                               + bb3 as u64);
902    dest[idx] = r7 as u32;
903
904    _apply_carry_u64(dest, idx + 1, carry);
905}
906
907
908/// Evaluate z * (a + b << 64) and store in dest at location idx
909pub(crate) fn _multiply_3_u64_into_u32(
910    dest: &mut [u32],
911    mut idx: usize,
912    a: u64,
913    b: u64,
914    z: u64,
915) {
916    let [az0, az1, az2, az3] = mul_split_u64_u64(a, z);
917    let [bz0, bz1, bz2, bz3] = mul_split_u64_u64(b, z);
918
919    let (carry, r0) = split_u64(dest[idx] as u64         + (az0 as u64             ) * 2);
920    dest[idx] = r0 as u32;
921
922    idx += 1;
923    let (carry, r1) = split_u64(dest[idx] as u64 + carry + (az1 as u64             ) * 2);
924    dest[idx] = r1 as u32;
925
926    idx += 1;
927    let (carry, r2) = split_u64(dest[idx] as u64 + carry + (az2 as u64 + bz0 as u64) * 2);
928    dest[idx] = r2 as u32;
929
930    idx += 1;
931    let (carry, r3) = split_u64(dest[idx] as u64 + carry + (az3 as u64 + bz1 as u64) * 2);
932    dest[idx] = r3 as u32;
933
934    idx += 1;
935    let (carry, r4) = split_u64(dest[idx] as u64 + carry + (             bz2 as u64) * 2);
936    dest[idx] = r4 as u32;
937
938    idx += 1;
939    let (carry, r5) = split_u64(dest[idx] as u64 + carry + (             bz3 as u64) * 2);
940    dest[idx] = r5 as u32;
941
942    _apply_carry_u64(dest, idx + 1, carry);
943}
944
945
946/// dest[idx0..] += (a + (b << 64)) * z
947pub(crate) fn multiply_thrup_spread_into(
948    dest: &mut [u32],
949    idx0: usize,
950    a: u32,
951    b: u32,
952    z: u32,
953) {
954    let a = a as u64;
955    let b = b as u64;
956    let z = z as u64;
957
958    let az = a * z;
959    let bz = b * z;
960
961    let (azh, azl) = split_u64(az);
962    let (bzh, bzl) = split_u64(bz);
963
964    let (carry, r0) = split_u64(dest[idx0 + 0] as u64 + azl * 2);
965    dest[idx0 + 0] = r0 as u32;
966
967    let (carry, r1) = split_u64(dest[idx0 + 1] as u64 + carry + (azh + bzl) * 2);
968    dest[idx0 + 1] = r1 as u32;
969
970    let (mut carry, r2) = split_u64(dest[idx0 + 2] as u64 + carry + bzh * 2);
971    dest[idx0 + 2] = r2 as u32;
972
973    let mut idx = idx0 + 3;
974    while carry != 0 {
975        let (c, overflow) = split_u64(dest[idx] as u64 + carry);
976        dest[idx] = overflow as u32;
977        carry = c;
978        idx += 1;
979    }
980}
981
982/// Multiply two pairs of bigdigits, storing carries into dest,
983///
984pub(crate) fn multiply_thrup_spread_into_wrapped(
985    dest: &mut [u32],
986    idx0: usize,
987    a: u32,
988    b: u32,
989    z: u32,
990) {
991    let a = a as u64;
992    let b = b as u64;
993    let z = z as u64;
994
995    let az = a * z;
996    let bz = b * z;
997
998    let (azh, azl) = split_u64(az);
999    let (bzh, bzl) = split_u64(bz);
1000
1001    let (carry, r0) = split_u64(dest[idx0 + 0] as u64 + azl * 2);
1002    dest[idx0 + 0] = r0 as u32;
1003
1004    let (carry, r1) = split_u64(dest[idx0 + 1] as u64 + carry + (azh + bzl) * 2);
1005    dest[idx0 + 1] = r1 as u32;
1006
1007    let (mut carry, r2) = split_u64(dest[idx0 + 2] as u64 + carry + bzh * 2);
1008    dest[idx0 + 2] = r2 as u32;
1009
1010    let mut idx = idx0 + 3;
1011    while carry != 0 {
1012        let (c, overflow) = split_u64(dest[idx] as u64 + carry);
1013        dest[idx] = overflow as u32;
1014        carry = c;
1015        idx += 1;
1016    }
1017}
1018
1019/// Multiply two pairs of bigdigits, storing carries into dest,
1020///
1021/// Used for multiplying `(a + b) * (y + z) => (ay + by + az + bz)`
1022/// Where (a,b) and (x,y) pairs are consecutive bigdigits.
1023///
1024/// Results of the multiplication are stored in 'dest' starting
1025/// with ay at index 'idx'
1026///
1027pub(crate) fn multiply_quad_spread_into(
1028    dest: &mut [u32],
1029    idx0: usize,
1030    a: u32,
1031    b: u32,
1032    y: u32,
1033    z: u32,
1034) {
1035    let ay = a as u64 * y as u64;
1036    let az = a as u64 * z as u64;
1037
1038    let by = b as u64 * y as u64;
1039    let bz = b as u64 * z as u64;
1040
1041    let (ayh, ayl) = split_u64(ay);
1042    let (azh, azl) = split_u64(az);
1043    let (byh, byl) = split_u64(by);
1044    let (bzh, bzl) = split_u64(bz);
1045
1046    let (carry, r0) = split_u64(dest[idx0 + 0] as u64 + ayl * 2);
1047    dest[idx0 + 0] = r0 as u32;
1048
1049    let (carry, r1) = split_u64(dest[idx0 + 1] as u64 + carry + (ayh + azl + byl) * 2);
1050    dest[idx0 + 1] = r1 as u32;
1051
1052    let (carry, r2) = split_u64(dest[idx0 + 2] as u64 + carry + (azh + byh + bzl) * 2);
1053    dest[idx0 + 2] = r2 as u32;
1054
1055    let (mut carry, r3) = split_u64(dest[idx0 + 3] as u64 + carry + bzh * 2);
1056    dest[idx0 + 3] = r3 as u32;
1057
1058    let mut idx = idx0 + 4;
1059    while carry != 0 {
1060        let (c, overflow) = split_u64(dest[idx] as u64 + carry);
1061        dest[idx] = overflow as u32;
1062        carry = c;
1063        idx += 1;
1064    }
1065}
1066
1067/// multiply_quad_spread_into
1068///
1069pub(crate) fn multiply_quad_spread_into_wrapping(
1070    dest: &mut [u32],
1071    idx: usize,
1072    a: u32,
1073    b: u32,
1074    y: u32,
1075    z: u32,
1076) {
1077    let ay = a as u64 * y as u64;
1078    let az = a as u64 * z as u64;
1079
1080    let by = b as u64 * y as u64;
1081    let bz = b as u64 * z as u64;
1082
1083    let (ayh, ayl) = split_u64(ay);
1084    let (azh, azl) = split_u64(az);
1085    let (byh, byl) = split_u64(by);
1086    let (bzh, bzl) = split_u64(bz);
1087
1088    let wrap = dest.len();
1089    let mut idx = idx % wrap;
1090
1091    let (carry, r0) = split_u64(dest[idx] as u64 + ayl * 2);
1092    dest[idx] = r0 as u32;
1093
1094    idx = (idx + 1) % wrap;
1095    let (carry, r1) = split_u64(dest[idx] as u64 + carry + (ayh + azl + byl) * 2);
1096    dest[idx] = r1 as u32;
1097
1098    idx = (idx + 1) % wrap;
1099    let (carry, r2) = split_u64(dest[idx] as u64 + carry + (azh + byh + bzl) * 2);
1100    dest[idx] = r2 as u32;
1101
1102    idx = (idx + 1) % wrap;
1103    let (mut carry, r3) = split_u64(dest[idx] as u64 + carry + bzh * 2);
1104    dest[idx] = r3 as u32;
1105
1106    while carry != 0 {
1107        idx = (idx + 1) % wrap;
1108        let (c, overflow) = split_u64(dest[idx] as u64 + carry);
1109        dest[idx] = overflow as u32;
1110        carry = c;
1111    }
1112}
1113
1114#[cfg(test)]
1115mod test {
1116    use super::*;
1117    include!("multiplication.tests.rs");
1118}