binius_field/
packed_aes_field.rs

1// Copyright 2024-2025 Irreducible Inc.
2
3pub use crate::arch::{
4	packed_aes_128::*, packed_aes_16::*, packed_aes_256::*, packed_aes_32::*, packed_aes_512::*,
5	packed_aes_64::*, packed_aes_8::*,
6};
7
8#[cfg(test)]
9mod test_utils {
10	/// Test if `mult_func` operation is a valid multiply operation on the given values for
11	/// all possible packed fields defined on 8-512 bits.
12	macro_rules! define_multiply_tests {
13		($mult_func:path, $constraint:ty) => {
14			$crate::packed_binary_field::test_utils::define_check_packed_mul!(
15				$mult_func,
16				$constraint
17			);
18
19			proptest! {
20				#[test]
21				fn test_mul_packed_8(a_val in any::<u8>(), b_val in any::<u8>()) {
22					use $crate::arch::packed_aes_8::*;
23
24					TestMult::<PackedAESBinaryField1x8b>::test_mul(
25						a_val.into(),
26						b_val.into(),
27					);
28				}
29
30				#[test]
31				fn test_mul_packed_16(a_val in any::<u16>(), b_val in any::<u16>()) {
32					use $crate::arch::packed_aes_16::*;
33
34					TestMult::<PackedAESBinaryField2x8b>::test_mul(
35						a_val.into(),
36						b_val.into(),
37					);
38					TestMult::<PackedAESBinaryField1x16b>::test_mul(
39						a_val.into(),
40						b_val.into(),
41					);
42				}
43
44				#[test]
45				fn test_mul_packed_32(a_val in any::<u32>(), b_val in any::<u32>()) {
46					use $crate::arch::packed_aes_32::*;
47
48					TestMult::<PackedAESBinaryField4x8b>::test_mul(
49						a_val.into(),
50						b_val.into(),
51					);
52					TestMult::<PackedAESBinaryField2x16b>::test_mul(
53						a_val.into(),
54						b_val.into(),
55					);
56					TestMult::<PackedAESBinaryField1x32b>::test_mul(
57						a_val.into(),
58						b_val.into(),
59					);
60				}
61
62				#[test]
63				fn test_mul_packed_64(a_val in any::<u64>(), b_val in any::<u64>()) {
64					use $crate::arch::packed_aes_64::*;
65
66					TestMult::<PackedAESBinaryField8x8b>::test_mul(
67						a_val.into(),
68						b_val.into(),
69					);
70					TestMult::<PackedAESBinaryField4x16b>::test_mul(
71						a_val.into(),
72						b_val.into(),
73					);
74					TestMult::<PackedAESBinaryField2x32b>::test_mul(
75						a_val.into(),
76						b_val.into(),
77					);
78					TestMult::<PackedAESBinaryField1x64b>::test_mul(
79						a_val.into(),
80						b_val.into(),
81					);
82				}
83
84				#[test]
85				fn test_mul_packed_128(a_val in any::<u128>(), b_val in any::<u128>()) {
86					use $crate::arch::packed_aes_128::*;
87
88					TestMult::<PackedAESBinaryField16x8b>::test_mul(
89						a_val.into(),
90						b_val.into(),
91					);
92					TestMult::<PackedAESBinaryField8x16b>::test_mul(
93						a_val.into(),
94						b_val.into(),
95					);
96					TestMult::<PackedAESBinaryField4x32b>::test_mul(
97						a_val.into(),
98						b_val.into(),
99					);
100					TestMult::<PackedAESBinaryField2x64b>::test_mul(
101						a_val.into(),
102						b_val.into(),
103					);
104					TestMult::<PackedAESBinaryField1x128b>::test_mul(
105						a_val.into(),
106						b_val.into(),
107					);
108				}
109
110				#[test]
111				fn test_mul_packed_256(a_val in any::<[u128; 2]>(), b_val in any::<[u128; 2]>()) {
112					use $crate::arch::packed_aes_256::*;
113
114					TestMult::<PackedAESBinaryField32x8b>::test_mul(
115						a_val.into(),
116						b_val.into(),
117					);
118					TestMult::<PackedAESBinaryField16x16b>::test_mul(
119						a_val.into(),
120						b_val.into(),
121					);
122					TestMult::<PackedAESBinaryField8x32b>::test_mul(
123						a_val.into(),
124						b_val.into(),
125					);
126					TestMult::<PackedAESBinaryField4x64b>::test_mul(
127						a_val.into(),
128						b_val.into(),
129					);
130					TestMult::<PackedAESBinaryField2x128b>::test_mul(
131						a_val.into(),
132						b_val.into(),
133					);
134				}
135
136				#[test]
137				fn test_mul_packed_512(a_val in any::<[u128; 4]>(), b_val in any::<[u128; 4]>()) {
138					use $crate::arch::packed_aes_512::*;
139
140					TestMult::<PackedAESBinaryField64x8b>::test_mul(
141						a_val.into(),
142						b_val.into(),
143					);
144					TestMult::<PackedAESBinaryField32x16b>::test_mul(
145						a_val.into(),
146						b_val.into(),
147					);
148					TestMult::<PackedAESBinaryField16x32b>::test_mul(
149						a_val.into(),
150						b_val.into(),
151					);
152					TestMult::<PackedAESBinaryField8x64b>::test_mul(
153						a_val.into(),
154						b_val.into(),
155					);
156					TestMult::<PackedAESBinaryField4x128b>::test_mul(
157						a_val.into(),
158						b_val.into(),
159					);
160				}
161			}
162		};
163	}
164
165	/// Test if `square_func` operation is a valid square operation on the given value for
166	/// all possible packed fields.
167	macro_rules! define_square_tests {
168		($square_func:path, $constraint:ident) => {
169			$crate::packed_binary_field::test_utils::define_check_packed_square!(
170				$square_func,
171				$constraint
172			);
173
174			proptest! {
175				#[test]
176				fn test_square_packed_8(a_val in any::<u8>()) {
177					use $crate::arch::packed_aes_8::*;
178
179					TestSquare::<PackedAESBinaryField1x8b>::test_square(a_val.into());
180				}
181
182				#[test]
183				fn test_square_packed_16(a_val in any::<u16>()) {
184					use $crate::arch::packed_aes_16::*;
185
186					TestSquare::<PackedAESBinaryField2x8b>::test_square(a_val.into());
187					TestSquare::<PackedAESBinaryField1x16b>::test_square(a_val.into());
188				}
189
190				#[test]
191				fn test_square_packed_32(a_val in any::<u32>()) {
192					use $crate::arch::packed_aes_32::*;
193
194					TestSquare::<PackedAESBinaryField4x8b>::test_square(a_val.into());
195					TestSquare::<PackedAESBinaryField2x16b>::test_square(a_val.into());
196					TestSquare::<PackedAESBinaryField1x32b>::test_square(a_val.into());
197				}
198
199				#[test]
200				fn test_square_packed_64(a_val in any::<u64>()) {
201					use $crate::arch::packed_aes_64::*;
202
203					TestSquare::<PackedAESBinaryField8x8b>::test_square(a_val.into());
204					TestSquare::<PackedAESBinaryField4x16b>::test_square(a_val.into());
205					TestSquare::<PackedAESBinaryField2x32b>::test_square(a_val.into());
206					TestSquare::<PackedAESBinaryField1x64b>::test_square(a_val.into());
207				}
208
209				#[test]
210				fn test_square_packed_128(a_val in any::<u128>()) {
211					use $crate::arch::packed_aes_128::*;
212
213					TestSquare::<PackedAESBinaryField16x8b>::test_square(a_val.into());
214					TestSquare::<PackedAESBinaryField8x16b>::test_square(a_val.into());
215					TestSquare::<PackedAESBinaryField4x32b>::test_square(a_val.into());
216					TestSquare::<PackedAESBinaryField2x64b>::test_square(a_val.into());
217					TestSquare::<PackedAESBinaryField1x128b>::test_square(a_val.into());
218				}
219
220				#[test]
221				fn test_square_packed_256(a_val in any::<[u128; 2]>()) {
222					use $crate::arch::packed_aes_256::*;
223
224					TestSquare::<PackedAESBinaryField32x8b>::test_square(a_val.into());
225					TestSquare::<PackedAESBinaryField16x16b>::test_square(a_val.into());
226					TestSquare::<PackedAESBinaryField8x32b>::test_square(a_val.into());
227					TestSquare::<PackedAESBinaryField4x64b>::test_square(a_val.into());
228					TestSquare::<PackedAESBinaryField2x128b>::test_square(a_val.into());
229				}
230
231				#[test]
232				fn test_square_packed_512(a_val in any::<[u128; 4]>()) {
233					use $crate::arch::packed_aes_512::*;
234
235					TestSquare::<PackedAESBinaryField64x8b>::test_square(a_val.into());
236					TestSquare::<PackedAESBinaryField32x16b>::test_square(a_val.into());
237					TestSquare::<PackedAESBinaryField16x32b>::test_square(a_val.into());
238					TestSquare::<PackedAESBinaryField8x64b>::test_square(a_val.into());
239					TestSquare::<PackedAESBinaryField4x128b>::test_square(a_val.into());
240				}
241			}
242		};
243	}
244
245	/// Test if `invert_func` operation is a valid invert operation on the given value for
246	/// all possible packed fields.
247	macro_rules! define_invert_tests {
248		($invert_func:path, $constraint:ident) => {
249			$crate::packed_binary_field::test_utils::define_check_packed_inverse!(
250				$invert_func,
251				$constraint
252			);
253
254			proptest! {
255				#[test]
256				fn test_invert_packed_8(a_val in any::<u8>()) {
257					use $crate::arch::packed_aes_8::*;
258
259					TestSquare::<PackedAESBinaryField1x8b>::test_invert(a_val.into());
260				}
261
262				#[test]
263				fn test_invert_packed_16(a_val in any::<u16>()) {
264					use $crate::arch::packed_aes_16::*;
265
266					TestSquare::<PackedAESBinaryField2x8b>::test_invert(a_val.into());
267					TestSquare::<PackedAESBinaryField1x16b>::test_invert(a_val.into());
268				}
269
270				#[test]
271				fn test_invert_packed_32(a_val in any::<u32>()) {
272					use $crate::arch::packed_aes_32::*;
273
274					TestSquare::<PackedAESBinaryField4x8b>::test_invert(a_val.into());
275					TestSquare::<PackedAESBinaryField2x16b>::test_invert(a_val.into());
276					TestSquare::<PackedAESBinaryField1x32b>::test_invert(a_val.into());
277				}
278
279				#[test]
280				fn test_invert_packed_64(a_val in any::<u64>()) {
281					use $crate::arch::packed_aes_64::*;
282
283					TestSquare::<PackedAESBinaryField8x8b>::test_invert(a_val.into());
284					TestSquare::<PackedAESBinaryField4x16b>::test_invert(a_val.into());
285					TestSquare::<PackedAESBinaryField2x32b>::test_invert(a_val.into());
286					TestSquare::<PackedAESBinaryField1x64b>::test_invert(a_val.into());
287				}
288
289				#[test]
290				fn test_invert_packed_128(a_val in any::<u128>()) {
291					use $crate::arch::packed_aes_128::*;
292
293					TestInvert::<PackedAESBinaryField16x8b>::test_invert(a_val.into());
294					TestInvert::<PackedAESBinaryField8x16b>::test_invert(a_val.into());
295					TestInvert::<PackedAESBinaryField4x32b>::test_invert(a_val.into());
296					TestInvert::<PackedAESBinaryField2x64b>::test_invert(a_val.into());
297					TestInvert::<PackedAESBinaryField1x128b>::test_invert(a_val.into());
298				}
299
300				#[test]
301				fn test_invert_packed_256(a_val in any::<[u128; 2]>()) {
302					use $crate::arch::packed_aes_256::*;
303
304					TestInvert::<PackedAESBinaryField32x8b>::test_invert(a_val.into());
305					TestInvert::<PackedAESBinaryField16x16b>::test_invert(a_val.into());
306					TestInvert::<PackedAESBinaryField8x32b>::test_invert(a_val.into());
307					TestInvert::<PackedAESBinaryField4x64b>::test_invert(a_val.into());
308					TestInvert::<PackedAESBinaryField2x128b>::test_invert(a_val.into());
309				}
310
311				#[test]
312				fn test_invert_packed_512(a_val in any::<[u128; 4]>()) {
313					use $crate::arch::packed_aes_512::*;
314
315					TestInvert::<PackedAESBinaryField64x8b>::test_invert(a_val.into());
316					TestInvert::<PackedAESBinaryField32x16b>::test_invert(a_val.into());
317					TestInvert::<PackedAESBinaryField16x32b>::test_invert(a_val.into());
318					TestInvert::<PackedAESBinaryField8x64b>::test_invert(a_val.into());
319					TestInvert::<PackedAESBinaryField4x128b>::test_invert(a_val.into());
320				}
321			}
322		};
323	}
324
325	macro_rules! define_transformation_tests {
326		($constraint:path) => {
327			$crate::packed_binary_field::test_utils::define_check_packed_transformation!(
328				$constraint
329			);
330
331			proptest::proptest! {
332				#[test]
333				fn test_transformation_packed_aes_8(a_val in proptest::prelude::any::<u8>()) {
334					use crate::arch::packed_aes_8::*;
335
336					TestTransformation::<PackedAESBinaryField1x8b>::test_transformation(a_val.into());
337				}
338
339				#[test]
340				fn test_transformation_packed_aes_16(a_val in proptest::prelude::any::<u16>()) {
341					use crate::arch::packed_aes_16::*;
342
343					TestTransformation::<PackedAESBinaryField1x16b>::test_transformation(a_val.into());
344					TestTransformation::<PackedAESBinaryField2x8b>::test_transformation(a_val.into());
345				}
346
347				#[test]
348				fn test_transformation_packed_aes_32(a_val in proptest::prelude::any::<u32>()) {
349					use crate::arch::packed_aes_32::*;
350
351					TestTransformation::<PackedAESBinaryField1x32b>::test_transformation(a_val.into());
352					TestTransformation::<PackedAESBinaryField2x16b>::test_transformation(a_val.into());
353					TestTransformation::<PackedAESBinaryField4x8b>::test_transformation(a_val.into());
354				}
355
356				#[test]
357				fn test_transformation_packed_aes_64(a_val in proptest::prelude::any::<u64>()) {
358					use crate::arch::packed_aes_64::*;
359
360					TestTransformation::<PackedAESBinaryField1x64b>::test_transformation(a_val.into());
361					TestTransformation::<PackedAESBinaryField2x32b>::test_transformation(a_val.into());
362					TestTransformation::<PackedAESBinaryField4x16b>::test_transformation(a_val.into());
363					TestTransformation::<PackedAESBinaryField8x8b>::test_transformation(a_val.into());
364				}
365
366				#[test]
367				fn test_transformation_packed_aes_128(a_val in proptest::prelude::any::<u128>()) {
368					use crate::arch::packed_aes_128::*;
369
370					TestTransformation::<PackedAESBinaryField1x128b>::test_transformation(a_val.into());
371					TestTransformation::<PackedAESBinaryField2x64b>::test_transformation(a_val.into());
372					TestTransformation::<PackedAESBinaryField4x32b>::test_transformation(a_val.into());
373					TestTransformation::<PackedAESBinaryField8x16b>::test_transformation(a_val.into());
374					TestTransformation::<PackedAESBinaryField16x8b>::test_transformation(a_val.into());
375				}
376
377				#[test]
378				fn test_transformation_packed_aes_256(a_val in proptest::prelude::any::<[u128; 2]>()) {
379					use crate::arch::packed_aes_256::*;
380
381					TestTransformation::<PackedAESBinaryField2x128b>::test_transformation(a_val.into());
382					TestTransformation::<PackedAESBinaryField4x64b>::test_transformation(a_val.into());
383					TestTransformation::<PackedAESBinaryField8x32b>::test_transformation(a_val.into());
384					TestTransformation::<PackedAESBinaryField16x16b>::test_transformation(a_val.into());
385					TestTransformation::<PackedAESBinaryField32x8b>::test_transformation(a_val.into());
386				}
387
388				#[test]
389				fn test_transformation_packed_aes_512(a_val in proptest::prelude::any::<[u128; 4]>()) {
390					use crate::arch::packed_aes_512::*;
391
392					TestTransformation::<PackedAESBinaryField4x128b>::test_transformation(a_val.into());
393					TestTransformation::<PackedAESBinaryField8x64b>::test_transformation(a_val.into());
394					TestTransformation::<PackedAESBinaryField16x32b>::test_transformation(a_val.into());
395					TestTransformation::<PackedAESBinaryField32x16b>::test_transformation(a_val.into());
396					TestTransformation::<PackedAESBinaryField64x8b>::test_transformation(a_val.into());
397				}
398			}
399		};
400	}
401
402	pub(crate) use define_invert_tests;
403	pub(crate) use define_multiply_tests;
404	pub(crate) use define_square_tests;
405	pub(crate) use define_transformation_tests;
406}
407
408#[cfg(test)]
409mod tests {
410	use std::ops::Mul;
411
412	use proptest::prelude::*;
413
414	use super::{
415		test_utils::{
416			define_invert_tests, define_multiply_tests, define_square_tests,
417			define_transformation_tests,
418		},
419		*,
420	};
421	use crate::{
422		arch::{
423			packed_128::*, packed_16::*, packed_256::*, packed_32::*, packed_512::*, packed_64::*,
424			packed_8::*,
425		},
426		linear_transformation::PackedTransformationFactory,
427		test_utils::implements_transformation_factory,
428		PackedField,
429	};
430
431	define_multiply_tests!(Mul::mul, PackedField);
432
433	define_square_tests!(PackedField::square, PackedField);
434
435	define_invert_tests!(PackedField::invert_or_zero, PackedField);
436
437	#[allow(unused)]
438	trait SelfTransformationFactory: PackedTransformationFactory<Self> {}
439
440	impl<T: PackedTransformationFactory<T>> SelfTransformationFactory for T {}
441
442	define_transformation_tests!(SelfTransformationFactory);
443
444	/// Compile-time test to ensure packed fields implement `PackedTransformationFactory`.
445	#[allow(unused)]
446	const fn test_implement_transformation_factory() {
447		// 8 bit packed aes tower
448		implements_transformation_factory::<PackedAESBinaryField1x8b, PackedAESBinaryField1x8b>();
449		implements_transformation_factory::<PackedBinaryField1x8b, PackedAESBinaryField1x8b>();
450
451		// 16 bit packed aes tower
452		implements_transformation_factory::<PackedAESBinaryField2x8b, PackedAESBinaryField2x8b>();
453		implements_transformation_factory::<PackedBinaryField2x8b, PackedAESBinaryField2x8b>();
454		implements_transformation_factory::<PackedAESBinaryField1x16b, PackedAESBinaryField1x16b>();
455		implements_transformation_factory::<PackedBinaryField1x16b, PackedAESBinaryField1x16b>();
456
457		// 32 bit packed aes tower
458		implements_transformation_factory::<PackedAESBinaryField4x8b, PackedAESBinaryField4x8b>();
459		implements_transformation_factory::<PackedBinaryField4x8b, PackedAESBinaryField4x8b>();
460		implements_transformation_factory::<PackedAESBinaryField2x16b, PackedAESBinaryField2x16b>();
461		implements_transformation_factory::<PackedBinaryField2x16b, PackedAESBinaryField2x16b>();
462		implements_transformation_factory::<PackedAESBinaryField1x32b, PackedAESBinaryField1x32b>();
463		implements_transformation_factory::<PackedBinaryField1x32b, PackedAESBinaryField1x32b>();
464
465		// 64 bit packed aes tower
466		implements_transformation_factory::<PackedAESBinaryField8x8b, PackedAESBinaryField8x8b>();
467		implements_transformation_factory::<PackedBinaryField8x8b, PackedAESBinaryField8x8b>();
468		implements_transformation_factory::<PackedAESBinaryField4x16b, PackedAESBinaryField4x16b>();
469		implements_transformation_factory::<PackedBinaryField4x16b, PackedAESBinaryField4x16b>();
470		implements_transformation_factory::<PackedAESBinaryField2x32b, PackedAESBinaryField2x32b>();
471		implements_transformation_factory::<PackedBinaryField2x32b, PackedAESBinaryField2x32b>();
472		implements_transformation_factory::<PackedAESBinaryField1x64b, PackedAESBinaryField1x64b>();
473		implements_transformation_factory::<PackedBinaryField1x64b, PackedAESBinaryField1x64b>();
474
475		// 128 bit packed aes tower
476		implements_transformation_factory::<PackedAESBinaryField16x8b, PackedAESBinaryField16x8b>();
477		implements_transformation_factory::<PackedBinaryField16x8b, PackedAESBinaryField16x8b>();
478		implements_transformation_factory::<PackedAESBinaryField8x16b, PackedAESBinaryField8x16b>();
479		implements_transformation_factory::<PackedBinaryField8x16b, PackedAESBinaryField8x16b>();
480		implements_transformation_factory::<PackedAESBinaryField4x32b, PackedAESBinaryField4x32b>();
481		implements_transformation_factory::<PackedBinaryField4x32b, PackedAESBinaryField4x32b>();
482		implements_transformation_factory::<PackedAESBinaryField2x64b, PackedAESBinaryField2x64b>();
483		implements_transformation_factory::<PackedBinaryField2x64b, PackedAESBinaryField2x64b>();
484		implements_transformation_factory::<PackedAESBinaryField1x128b, PackedAESBinaryField1x128b>(
485		);
486		implements_transformation_factory::<PackedBinaryField1x128b, PackedAESBinaryField1x128b>();
487
488		// 256 bit packed aes tower
489		implements_transformation_factory::<PackedAESBinaryField32x8b, PackedAESBinaryField32x8b>();
490		implements_transformation_factory::<PackedBinaryField32x8b, PackedAESBinaryField32x8b>();
491		implements_transformation_factory::<PackedAESBinaryField16x16b, PackedAESBinaryField16x16b>(
492		);
493		implements_transformation_factory::<PackedBinaryField16x16b, PackedAESBinaryField16x16b>();
494		implements_transformation_factory::<PackedAESBinaryField8x32b, PackedAESBinaryField8x32b>();
495		implements_transformation_factory::<PackedBinaryField8x32b, PackedAESBinaryField8x32b>();
496		implements_transformation_factory::<PackedAESBinaryField4x64b, PackedAESBinaryField4x64b>();
497		implements_transformation_factory::<PackedBinaryField4x64b, PackedAESBinaryField4x64b>();
498		implements_transformation_factory::<PackedAESBinaryField2x128b, PackedAESBinaryField2x128b>(
499		);
500		implements_transformation_factory::<PackedBinaryField2x128b, PackedAESBinaryField2x128b>();
501
502		// 512 bit packed aes tower
503		implements_transformation_factory::<PackedAESBinaryField64x8b, PackedAESBinaryField64x8b>();
504		implements_transformation_factory::<PackedBinaryField64x8b, PackedAESBinaryField64x8b>();
505		implements_transformation_factory::<PackedAESBinaryField32x16b, PackedAESBinaryField32x16b>(
506		);
507		implements_transformation_factory::<PackedBinaryField32x16b, PackedAESBinaryField32x16b>();
508		implements_transformation_factory::<PackedAESBinaryField16x32b, PackedAESBinaryField16x32b>(
509		);
510		implements_transformation_factory::<PackedBinaryField16x32b, PackedAESBinaryField16x32b>();
511		implements_transformation_factory::<PackedAESBinaryField8x64b, PackedAESBinaryField8x64b>();
512		implements_transformation_factory::<PackedBinaryField8x64b, PackedAESBinaryField8x64b>();
513		implements_transformation_factory::<PackedAESBinaryField4x128b, PackedAESBinaryField4x128b>(
514		);
515		implements_transformation_factory::<PackedBinaryField4x128b, PackedAESBinaryField4x128b>();
516	}
517}