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