polyval/field_element/
mul64.rs1use crate::field_element::FieldElement;
9use core::{array, ops::BitXor};
10
11impl FieldElement {
12 #[inline]
17 pub(crate) fn karatsuba_mul(self, rhs: Self) -> Product {
18 let (h0, h1) = self.to_u64x2();
20 let h0r = h0.reverse_bits();
21 let h1r = h1.reverse_bits();
22 let h2 = h0 ^ h1;
23 let h2r = h0r ^ h1r;
24
25 let (y0, y1) = rhs.to_u64x2();
27 let y0r = y0.reverse_bits();
28 let y1r = y1.reverse_bits();
29 let y2 = y0 ^ y1;
30 let y2r = y0r ^ y1r;
31
32 #[inline]
34 fn bmul64(x: u64, y: u64) -> u64 {
35 super::bmul(x, y, 0x1111_1111_1111_1111)
36 }
37
38 let z0 = bmul64(y0, h0);
40 let z1 = bmul64(y1, h1);
41 let mut z2 = bmul64(y2, h2);
42 let mut z0h = bmul64(y0r, h0r);
43 let mut z1h = bmul64(y1r, h1r);
44 let mut z2h = bmul64(y2r, h2r);
45
46 z2 ^= z0 ^ z1;
48 z2h ^= z0h ^ z1h;
49 z0h = z0h.reverse_bits() >> 1;
50 z1h = z1h.reverse_bits() >> 1;
51 z2h = z2h.reverse_bits() >> 1;
52
53 let v0 = z0;
55 let v1 = z0h ^ z2;
56 let v2 = z1 ^ z2h;
57 let v3 = z1h;
58 Product([v0, v1, v2, v3])
59 }
60
61 #[inline]
63 fn to_u64x2(self) -> (u64, u64) {
64 let x = u128::from(self);
65 ((x & 0xFFFF_FFFF_FFFF_FFFF) as u64, (x >> 64) as u64)
66 }
67}
68
69pub(crate) struct Product([u64; 4]);
71
72impl Product {
73 #[inline]
80 pub(crate) fn mont_reduce(self) -> FieldElement {
81 let (v0, mut v1, mut v2, mut v3) = (self.0[0], self.0[1], self.0[2], self.0[3]);
82 v2 ^= v0 ^ (v0 >> 1) ^ (v0 >> 2) ^ (v0 >> 7);
83 v1 ^= (v0 << 63) ^ (v0 << 62) ^ (v0 << 57);
84 v3 ^= v1 ^ (v1 >> 1) ^ (v1 >> 2) ^ (v1 >> 7);
85 v2 ^= (v1 << 63) ^ (v1 << 62) ^ (v1 << 57);
86 (u128::from(v2) | u128::from(v3) << 64).into()
87 }
88}
89
90impl BitXor for Product {
91 type Output = Self;
92
93 #[inline]
94 fn bitxor(self, rhs: Self) -> Self::Output {
95 Self(array::from_fn(|n| self.0[n] ^ rhs.0[n]))
96 }
97}