1use crate::{
5 BinaryField128bGhash,
6 arch::{
7 GhashInvert1x, GhashInvert2x, GhashInvert4x, GhashSquare1x, GhashSquare2x, GhashSquare4x,
8 GhashWideMul1x, GhashWideMul2x, GhashWideMul4x, M128, M256, M512, MulFromWideMul,
9 portable::packed_macros::{portable_macros::*, *},
10 },
11};
12
13define_packed_binary_field!(
14 PackedBinaryGhash1x128b,
15 BinaryField128bGhash,
16 M128,
17 (MulFromWideMul),
18 (GhashSquare1x),
19 (GhashInvert1x),
20 (GhashWideMul1x)
21);
22
23define_packed_binary_field!(
24 PackedBinaryGhash2x128b,
25 BinaryField128bGhash,
26 M256,
27 (MulFromWideMul),
28 (GhashSquare2x),
29 (GhashInvert2x),
30 (GhashWideMul2x)
31);
32
33define_packed_binary_field!(
34 PackedBinaryGhash4x128b,
35 BinaryField128bGhash,
36 M512,
37 (MulFromWideMul),
38 (GhashSquare4x),
39 (GhashInvert4x),
40 (GhashWideMul4x)
41);
42
43#[cfg(test)]
44mod test_utils {
45 macro_rules! define_multiply_tests {
48 ($mult_func:path, $constraint:ty) => {
49 $crate::packed_binary_field::test_utils::define_check_packed_mul!(
50 $mult_func,
51 $constraint
52 );
53
54 proptest! {
55 #[test]
56 fn test_mul_packed_128(a_val in any::<u128>(), b_val in any::<u128>()) {
57 TestMult::<$crate::PackedBinaryGhash1x128b>::test_mul(
58 a_val.into(),
59 b_val.into(),
60 );
61 }
62
63 #[test]
64 fn test_mul_packed_256(a_val in any::<[u128; 2]>(), b_val in any::<[u128; 2]>()) {
65 TestMult::<$crate::PackedBinaryGhash2x128b>::test_mul(
66 a_val.into(),
67 b_val.into(),
68 );
69 }
70
71 #[test]
72 fn test_mul_packed_512(a_val in any::<[u128; 4]>(), b_val in any::<[u128; 4]>()) {
73 TestMult::<$crate::PackedBinaryGhash4x128b>::test_mul(
74 a_val.into(),
75 b_val.into(),
76 );
77 }
78 }
79 };
80 }
81
82 macro_rules! define_square_tests {
85 ($square_func:path, $constraint:ident) => {
86 $crate::packed_binary_field::test_utils::define_check_packed_square!(
87 $square_func,
88 $constraint
89 );
90
91 proptest! {
92 #[test]
93 fn test_square_packed_128(a_val in any::<u128>()) {
94 TestSquare::<$crate::PackedBinaryGhash1x128b>::test_square(a_val.into());
95 }
96
97 #[test]
98 fn test_square_packed_256(a_val in any::<[u128; 2]>()) {
99 TestSquare::<$crate::PackedBinaryGhash2x128b>::test_square(a_val.into());
100 }
101
102 #[test]
103 fn test_square_packed_512(a_val in any::<[u128; 4]>()) {
104 TestSquare::<$crate::PackedBinaryGhash4x128b>::test_square(a_val.into());
105 }
106 }
107 };
108 }
109
110 macro_rules! define_invert_tests {
113 ($invert_func:path, $constraint:ident) => {
114 $crate::packed_binary_field::test_utils::define_check_packed_inverse!(
115 $invert_func,
116 $constraint
117 );
118
119 proptest! {
120 #[test]
121 fn test_invert_packed_128(a_val in any::<u128>()) {
122 TestInvert::<$crate::PackedBinaryGhash1x128b>::test_invert(a_val.into());
123 }
124
125 #[test]
126 fn test_invert_packed_256(a_val in any::<[u128; 2]>()) {
127 TestInvert::<$crate::PackedBinaryGhash2x128b>::test_invert(a_val.into());
128 }
129
130 #[test]
131 fn test_invert_packed_512(a_val in any::<[u128; 4]>()) {
132 TestInvert::<$crate::PackedBinaryGhash4x128b>::test_invert(a_val.into());
133 }
134 }
135 };
136 }
137
138 macro_rules! define_wide_mul_tests {
139 () => {
140 fn check_widening_correctness<P>(a: P::Underlier, b: P::Underlier)
141 where
142 P: $crate::PackedField<Scalar = $crate::BinaryField128bGhash>
143 + $crate::WideMul
144 + $crate::underlier::WithUnderlier,
145 {
146 let a = P::from_underlier(a);
147 let b = P::from_underlier(b);
148 let wide = P::wide_mul(a, b);
149 let reduced = P::reduce(wide);
150 assert_eq!(reduced, a * b);
151 }
152
153 fn check_widening_linearity<P>(
154 a1: P::Underlier,
155 b1: P::Underlier,
156 a2: P::Underlier,
157 b2: P::Underlier,
158 ) where
159 P: $crate::PackedField<Scalar = $crate::BinaryField128bGhash>
160 + $crate::WideMul
161 + $crate::underlier::WithUnderlier,
162 {
163 let (a1, b1) = (P::from_underlier(a1), P::from_underlier(b1));
164 let (a2, b2) = (P::from_underlier(a2), P::from_underlier(b2));
165 let sum_reduced = P::reduce(P::wide_mul(a1, b1) + P::wide_mul(a2, b2));
166 assert_eq!(sum_reduced, a1 * b1 + a2 * b2);
167 }
168
169 proptest! {
170 #[test]
171 fn test_wide_mul_correctness_128(a in any::<u128>(), b in any::<u128>()) {
172 check_widening_correctness::<$crate::PackedBinaryGhash1x128b>(a.into(), b.into());
173 }
174
175 #[test]
176 fn test_wide_mul_correctness_256(a in any::<[u128; 2]>(), b in any::<[u128; 2]>()) {
177 check_widening_correctness::<$crate::PackedBinaryGhash2x128b>(a.into(), b.into());
178 }
179
180 #[test]
181 fn test_wide_mul_correctness_512(a in any::<[u128; 4]>(), b in any::<[u128; 4]>()) {
182 check_widening_correctness::<$crate::PackedBinaryGhash4x128b>(a.into(), b.into());
183 }
184
185 #[test]
186 fn test_wide_mul_linearity_128(
187 a1 in any::<u128>(), b1 in any::<u128>(),
188 a2 in any::<u128>(), b2 in any::<u128>(),
189 ) {
190 check_widening_linearity::<$crate::PackedBinaryGhash1x128b>(
191 a1.into(), b1.into(), a2.into(), b2.into(),
192 );
193 }
194
195 #[test]
196 fn test_wide_mul_linearity_256(
197 a1 in any::<[u128; 2]>(), b1 in any::<[u128; 2]>(),
198 a2 in any::<[u128; 2]>(), b2 in any::<[u128; 2]>(),
199 ) {
200 check_widening_linearity::<$crate::PackedBinaryGhash2x128b>(
201 a1.into(), b1.into(), a2.into(), b2.into(),
202 );
203 }
204
205 #[test]
206 fn test_wide_mul_linearity_512(
207 a1 in any::<[u128; 4]>(), b1 in any::<[u128; 4]>(),
208 a2 in any::<[u128; 4]>(), b2 in any::<[u128; 4]>(),
209 ) {
210 check_widening_linearity::<$crate::PackedBinaryGhash4x128b>(
211 a1.into(), b1.into(), a2.into(), b2.into(),
212 );
213 }
214 }
215 };
216 }
217
218 pub(crate) use define_invert_tests;
219 pub(crate) use define_multiply_tests;
220 pub(crate) use define_square_tests;
221 pub(crate) use define_wide_mul_tests;
222}
223
224#[cfg(test)]
225mod tests {
226 use std::ops::Mul;
227
228 use proptest::{arbitrary::any, proptest};
229
230 use super::{
231 PackedBinaryGhash2x128b, PackedBinaryGhash4x128b,
232 test_utils::{
233 define_invert_tests, define_multiply_tests, define_square_tests, define_wide_mul_tests,
234 },
235 };
236 use crate::{
237 BinaryField128bGhash, PackedField,
238 arithmetic_traits::{InvertOrZero, Square},
239 underlier::WithUnderlier,
240 };
241
242 fn check_get_set<const WIDTH: usize, PT>(a: [u128; WIDTH], b: [u128; WIDTH])
243 where
244 PT: PackedField<Scalar = BinaryField128bGhash>
245 + WithUnderlier<Underlier: From<[u128; WIDTH]>>,
246 {
247 let mut val = PT::from_underlier(a.into());
248 for i in 0..WIDTH {
249 assert_eq!(val.get(i), BinaryField128bGhash::from(a[i]));
250 val.set(i, BinaryField128bGhash::from(b[i]));
251 assert_eq!(val.get(i), BinaryField128bGhash::from(b[i]));
252 }
253 }
254
255 proptest! {
256 #[test]
257 fn test_get_set_256(a in any::<[u128; 2]>(), b in any::<[u128; 2]>()) {
258 check_get_set::<2, PackedBinaryGhash2x128b>(a, b);
259 }
260
261 #[test]
262 fn test_get_set_512(a in any::<[u128; 4]>(), b in any::<[u128; 4]>()) {
263 check_get_set::<4, PackedBinaryGhash4x128b>(a, b);
264 }
265 }
266
267 define_multiply_tests!(Mul::mul, PackedField);
268
269 define_square_tests!(Square::square, PackedField);
270
271 define_invert_tests!(InvertOrZero::invert_or_zero, PackedField);
272
273 define_wide_mul_tests!();
274
275 #[test]
276 fn test_wide_mul_zero_inputs() {
277 use super::PackedBinaryGhash1x128b as P;
278 use crate::{WideMul, field::FieldOps};
279
280 let zero = P::default();
281 let one = P::one();
282
283 assert_eq!(P::reduce(P::wide_mul(zero, zero)), zero);
284 assert_eq!(P::reduce(P::wide_mul(zero, one)), zero);
285 assert_eq!(P::reduce(P::wide_mul(one, zero)), zero);
286 assert_eq!(P::reduce(P::wide_mul(one, one)), one);
287
288 let wide_zero = <P as WideMul>::Output::default();
289 assert_eq!(P::reduce(wide_zero), zero);
290 }
291
292 #[test]
293 fn test_wide_mul_single_accumulation() {
294 use rand::{SeedableRng, rngs::StdRng};
295
296 use super::PackedBinaryGhash1x128b as P;
297 use crate::{Random, WideMul};
298
299 let mut rng = StdRng::seed_from_u64(77);
300 let a = P::random(&mut rng);
301 let b = P::random(&mut rng);
302
303 let wide = P::wide_mul(a, b);
304 let sum = wide + <P as WideMul>::Output::default();
305 assert_eq!(P::reduce(sum), a * b);
306 }
307}