Skip to main content

binius_field/
packed_aes.rs

1// Copyright 2024-2025 Irreducible Inc.
2// Copyright 2026 The Binius Developers
3
4use 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 tests {
53	use super::*;
54	use crate::{WideMul, packed_binary_field::test_utils::packed_field_tests};
55
56	packed_field_tests!(aes_1x8b, PackedAESBinaryField1x8b);
57	packed_field_tests!(aes_16x8b, PackedAESBinaryField16x8b);
58	packed_field_tests!(aes_32x8b, PackedAESBinaryField32x8b);
59	packed_field_tests!(aes_64x8b, PackedAESBinaryField64x8b);
60
61	#[test]
62	fn test_wide_mul_exhaustive_scalar_pairs() {
63		// The scalar field has only 2^8 elements, so every product admits an exhaustive check.
64		// Each byte pair is broadcast across the 128-bit packing and multiplied deferred.
65		//
66		//     reduce(wide_mul(a, b)) must equal the scalar product in every lane.
67		//
68		// The scalar multiply is an independent oracle: it runs the tower-field log/exp tables,
69		// not the packed widening path under test.
70		for a in 0..=u8::MAX {
71			for b in 0..=u8::MAX {
72				let expected = crate::AESTowerField8b::new(a) * crate::AESTowerField8b::new(b);
73
74				let a_packed =
75					crate::PackedAESBinaryField16x8b::broadcast(crate::AESTowerField8b::new(a));
76				let b_packed =
77					crate::PackedAESBinaryField16x8b::broadcast(crate::AESTowerField8b::new(b));
78				let reduced = crate::PackedAESBinaryField16x8b::reduce(
79					crate::PackedAESBinaryField16x8b::wide_mul(a_packed, b_packed),
80				);
81
82				assert_eq!(
83					reduced,
84					crate::PackedAESBinaryField16x8b::broadcast(expected),
85					"a={a:#04x} b={b:#04x}"
86				);
87			}
88		}
89	}
90}