bigdecimal/arithmetic/
modulo.rs

1use crate::*;
2
3/// optimized calculation of n % 10
4#[allow(dead_code)]
5pub(crate) fn mod_ten_uint(n: &BigUint) -> u8 {
6    mod_ten_2p64_le(n.iter_u64_digits())
7}
8
9/// optimized calculation of n % 10
10pub(crate) fn mod_ten_2p64_le(mut digits: impl Iterator<Item = u64>) -> u8 {
11    let d0 = digits.next().unwrap_or(0) % 10;
12    let mut acc: u64 = digits.map(|d| d % 10).sum();
13    acc *= 6;
14    acc += d0;
15    (acc % 10) as u8
16}
17
18/// optimized calculation of n % 100
19pub(crate) fn mod_100_uint(n: &BigUint) -> u8 {
20    mod_100_2p64_le(n.iter_u64_digits())
21}
22
23/// optimized calculation of n % 100
24/// TODO: compare implementations: https://rust.godbolt.org/z/Kcxor1MT5
25pub(crate) fn mod_100_2p64_le(mut digits: impl Iterator<Item = u64>) -> u8 {
26    let mods_2p64 = [16, 56, 96, 36, 76];
27    let mut acc_v = [ 0,  0,  0,  0,  0];
28    let d0 = digits.next().unwrap_or(0) % 100;
29
30    for (i, d) in digits.enumerate() {
31        acc_v[i % 5] += d % 100;
32    }
33
34    let mut acc = d0;
35    for (&a, m) in acc_v.iter().zip(mods_2p64.iter()) {
36        acc += m * (a % 100);
37    }
38    (acc % 100) as u8
39}