1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#[inline]
pub(crate) fn multiply_256_by_128_upperbits(a_hi: u128, a_lo: u128, b: u128) -> u128 {
let a_chunks = [
a_lo as u64,
(a_lo >> 64) as u64,
a_hi as u64,
(a_hi >> 64) as u64,
];
let b_chunks = [
b as u64,
(b >> 64) as u64,
];
let mut product = [0; 6];
for (b_index, &b_digit) in b_chunks.iter().enumerate() {
multiply_256_by_64_helper(&mut product[b_index..], &a_chunks, b_digit);
}
((product[5] as u128) << 64) | (product[4] as u128)
}
#[inline]
fn multiply_256_by_64_helper(product: &mut [u64], a: &[u64;4], b: u64) {
if b == 0 {
return;
}
let mut carry = 0;
let (product_lo, product_hi) = product.split_at_mut(a.len());
for (p, &a_digit) in product_lo.iter_mut().zip(a) {
carry += *p as u128;
carry += (a_digit as u128) * (b as u128);
*p = carry as u64;
carry >>= 64;
}
let mut p = product_hi.iter_mut();
while carry != 0 {
let p = p.next().expect("carry overflow during multiplication!");
carry += *p as u128;
*p = carry as u64;
carry >>= 64;
}
}
#[inline]
pub(crate) fn long_multiply(a: &[u64], b: u64, product: &mut [u64]) {
if b == 0 {
return;
}
let mut carry = 0;
let (product_lo, product_hi) = product.split_at_mut(a.len());
for (p, &a_digit) in product_lo.iter_mut().zip(a) {
carry += *p as u128;
carry += (a_digit as u128) * (b as u128);
*p = carry as u64;
carry >>= 64;
}
let mut p = product_hi.iter_mut();
while carry != 0 {
let p = p.next().expect("carry overflow during multiplication!");
carry += *p as u128;
*p = carry as u64;
carry >>= 64;
}
}