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