1use crate::{
5 aes_field::AESTowerField8b,
6 arch::{
7 AesInvert1x, AesInvert16x, AesInvert32x, AesInvert64x, AesSquare1x, AesSquare16x,
8 AesSquare32x, AesSquare64x, AesWideMul1x, AesWideMul16x, AesWideMul32x, AesWideMul64x,
9 M128, M256, M512, MulFromWideMul,
10 portable::packed_macros::{portable_macros::*, *},
11 },
12};
13
14define_packed_binary_field!(
15 PackedAESBinaryField1x8b,
16 AESTowerField8b,
17 u8,
18 (MulFromWideMul),
19 (AesSquare1x),
20 (AesInvert1x),
21 (AesWideMul1x)
22);
23define_packed_binary_field!(
24 PackedAESBinaryField16x8b,
25 AESTowerField8b,
26 M128,
27 (MulFromWideMul),
28 (AesSquare16x),
29 (AesInvert16x),
30 (AesWideMul16x)
31);
32define_packed_binary_field!(
33 PackedAESBinaryField32x8b,
34 AESTowerField8b,
35 M256,
36 (MulFromWideMul),
37 (AesSquare32x),
38 (AesInvert32x),
39 (AesWideMul32x)
40);
41define_packed_binary_field!(
42 PackedAESBinaryField64x8b,
43 AESTowerField8b,
44 M512,
45 (MulFromWideMul),
46 (AesSquare64x),
47 (AesInvert64x),
48 (AesWideMul64x)
49);
50
51#[cfg(test)]
52mod test_utils {
53 macro_rules! define_multiply_tests {
56 ($mult_func:path, $constraint:ty) => {
57 $crate::packed_binary_field::test_utils::define_check_packed_mul!(
58 $mult_func,
59 $constraint
60 );
61
62 proptest! {
63 #[test]
64 fn test_mul_packed_8(a_val in any::<u8>(), b_val in any::<u8>()) {
65 TestMult::<$crate::PackedAESBinaryField1x8b>::test_mul(
66 a_val.into(),
67 b_val.into(),
68 );
69 }
70
71 #[test]
72 fn test_mul_packed_128(a_val in any::<u128>(), b_val in any::<u128>()) {
73 TestMult::<$crate::PackedAESBinaryField16x8b>::test_mul(
74 a_val.into(),
75 b_val.into(),
76 );
77 }
78
79 #[test]
80 fn test_mul_packed_256(a_val in any::<[u128; 2]>(), b_val in any::<[u128; 2]>()) {
81 TestMult::<$crate::PackedAESBinaryField32x8b>::test_mul(
82 a_val.into(),
83 b_val.into(),
84 );
85 }
86
87 #[test]
88 fn test_mul_packed_512(a_val in any::<[u128; 4]>(), b_val in any::<[u128; 4]>()) {
89 TestMult::<$crate::PackedAESBinaryField64x8b>::test_mul(
90 a_val.into(),
91 b_val.into(),
92 );
93 }
94 }
95 };
96 }
97
98 macro_rules! define_square_tests {
101 ($square_func:path, $constraint:ident) => {
102 $crate::packed_binary_field::test_utils::define_check_packed_square!(
103 $square_func,
104 $constraint
105 );
106
107 proptest! {
108 #[test]
109 fn test_square_packed_8(a_val in any::<u8>()) {
110 TestSquare::<$crate::PackedAESBinaryField1x8b>::test_square(a_val.into());
111 }
112
113 #[test]
114 fn test_square_packed_128(a_val in any::<u128>()) {
115 TestSquare::<$crate::PackedAESBinaryField16x8b>::test_square(a_val.into());
116 }
117
118 #[test]
119 fn test_square_packed_256(a_val in any::<[u128; 2]>()) {
120 TestSquare::<$crate::PackedAESBinaryField32x8b>::test_square(a_val.into());
121 }
122
123 #[test]
124 fn test_square_packed_512(a_val in any::<[u128; 4]>()) {
125 TestSquare::<$crate::PackedAESBinaryField64x8b>::test_square(a_val.into());
126 }
127 }
128 };
129 }
130
131 macro_rules! define_invert_tests {
134 ($invert_func:path, $constraint:ident) => {
135 $crate::packed_binary_field::test_utils::define_check_packed_inverse!(
136 $invert_func,
137 $constraint
138 );
139
140 proptest! {
141 #[test]
142 fn test_invert_packed_8(a_val in any::<u8>()) {
143 TestSquare::<$crate::PackedAESBinaryField1x8b>::test_invert(a_val.into());
144 }
145
146 #[test]
147 fn test_invert_packed_128(a_val in any::<u128>()) {
148 TestInvert::<$crate::PackedAESBinaryField16x8b>::test_invert(a_val.into());
149 }
150
151 #[test]
152 fn test_invert_packed_256(a_val in any::<[u128; 2]>()) {
153 TestInvert::<$crate::PackedAESBinaryField32x8b>::test_invert(a_val.into());
154 }
155
156 #[test]
157 fn test_invert_packed_512(a_val in any::<[u128; 4]>()) {
158 TestInvert::<$crate::PackedAESBinaryField64x8b>::test_invert(a_val.into());
159 }
160 }
161 };
162 }
163
164 macro_rules! define_wide_mul_tests {
166 () => {
167 fn check_widening_correctness<P>(a: P::Underlier, b: P::Underlier)
168 where
169 P: $crate::PackedField<Scalar = $crate::AESTowerField8b>
170 + $crate::WideMul
171 + $crate::underlier::WithUnderlier,
172 {
173 let a = P::from_underlier(a);
174 let b = P::from_underlier(b);
175 let wide = P::wide_mul(a, b);
177 let reduced = P::reduce(wide);
178 assert_eq!(reduced, a * b);
179 }
180
181 fn check_widening_linearity<P>(
182 a1: P::Underlier,
183 b1: P::Underlier,
184 a2: P::Underlier,
185 b2: P::Underlier,
186 ) where
187 P: $crate::PackedField<Scalar = $crate::AESTowerField8b>
188 + $crate::WideMul
189 + $crate::underlier::WithUnderlier,
190 {
191 let (a1, b1) = (P::from_underlier(a1), P::from_underlier(b1));
192 let (a2, b2) = (P::from_underlier(a2), P::from_underlier(b2));
193 let sum_reduced = P::reduce(P::wide_mul(a1, b1) + P::wide_mul(a2, b2));
197 assert_eq!(sum_reduced, a1 * b1 + a2 * b2);
198 }
199
200 proptest! {
201 #[test]
202 fn test_wide_mul_correctness_8(a in any::<u8>(), b in any::<u8>()) {
203 check_widening_correctness::<$crate::PackedAESBinaryField1x8b>(a, b);
204 }
205
206 #[test]
207 fn test_wide_mul_correctness_128(a in any::<u128>(), b in any::<u128>()) {
208 check_widening_correctness::<$crate::PackedAESBinaryField16x8b>(
209 a.into(),
210 b.into(),
211 );
212 }
213
214 #[test]
215 fn test_wide_mul_correctness_256(a in any::<[u128; 2]>(), b in any::<[u128; 2]>()) {
216 check_widening_correctness::<$crate::PackedAESBinaryField32x8b>(
217 a.into(),
218 b.into(),
219 );
220 }
221
222 #[test]
223 fn test_wide_mul_correctness_512(a in any::<[u128; 4]>(), b in any::<[u128; 4]>()) {
224 check_widening_correctness::<$crate::PackedAESBinaryField64x8b>(
225 a.into(),
226 b.into(),
227 );
228 }
229
230 #[test]
231 fn test_wide_mul_linearity_8(
232 a1 in any::<u8>(), b1 in any::<u8>(),
233 a2 in any::<u8>(), b2 in any::<u8>(),
234 ) {
235 check_widening_linearity::<$crate::PackedAESBinaryField1x8b>(a1, b1, a2, b2);
236 }
237
238 #[test]
239 fn test_wide_mul_linearity_128(
240 a1 in any::<u128>(), b1 in any::<u128>(),
241 a2 in any::<u128>(), b2 in any::<u128>(),
242 ) {
243 check_widening_linearity::<$crate::PackedAESBinaryField16x8b>(
244 a1.into(), b1.into(), a2.into(), b2.into(),
245 );
246 }
247
248 #[test]
249 fn test_wide_mul_linearity_256(
250 a1 in any::<[u128; 2]>(), b1 in any::<[u128; 2]>(),
251 a2 in any::<[u128; 2]>(), b2 in any::<[u128; 2]>(),
252 ) {
253 check_widening_linearity::<$crate::PackedAESBinaryField32x8b>(
254 a1.into(), b1.into(), a2.into(), b2.into(),
255 );
256 }
257
258 #[test]
259 fn test_wide_mul_linearity_512(
260 a1 in any::<[u128; 4]>(), b1 in any::<[u128; 4]>(),
261 a2 in any::<[u128; 4]>(), b2 in any::<[u128; 4]>(),
262 ) {
263 check_widening_linearity::<$crate::PackedAESBinaryField64x8b>(
264 a1.into(), b1.into(), a2.into(), b2.into(),
265 );
266 }
267 }
268 };
269 }
270
271 pub(crate) use define_invert_tests;
272 pub(crate) use define_multiply_tests;
273 pub(crate) use define_square_tests;
274 pub(crate) use define_wide_mul_tests;
275}
276
277#[cfg(test)]
278mod tests {
279 use std::ops::Mul;
280
281 use proptest::prelude::*;
282
283 use super::test_utils::{
284 define_invert_tests, define_multiply_tests, define_square_tests, define_wide_mul_tests,
285 };
286 use crate::{
287 PackedField, WideMul,
288 arithmetic_traits::{InvertOrZero, Square},
289 };
290
291 define_multiply_tests!(Mul::mul, PackedField);
292
293 define_square_tests!(Square::square, PackedField);
294
295 define_invert_tests!(InvertOrZero::invert_or_zero, PackedField);
296
297 define_wide_mul_tests!();
298
299 #[test]
300 fn test_wide_mul_exhaustive_scalar_pairs() {
301 for a in 0..=u8::MAX {
309 for b in 0..=u8::MAX {
310 let expected = crate::AESTowerField8b::new(a) * crate::AESTowerField8b::new(b);
311
312 let a_packed =
313 crate::PackedAESBinaryField16x8b::broadcast(crate::AESTowerField8b::new(a));
314 let b_packed =
315 crate::PackedAESBinaryField16x8b::broadcast(crate::AESTowerField8b::new(b));
316 let reduced = crate::PackedAESBinaryField16x8b::reduce(
317 crate::PackedAESBinaryField16x8b::wide_mul(a_packed, b_packed),
318 );
319
320 assert_eq!(
321 reduced,
322 crate::PackedAESBinaryField16x8b::broadcast(expected),
323 "a={a:#04x} b={b:#04x}"
324 );
325 }
326 }
327 }
328}