binius_field/
packed_binary_field.rs

1// Copyright 2023-2025 Irreducible Inc.
2
3pub use crate::arch::{
4	packed_1::*, packed_2::*, packed_4::*, packed_8::*, packed_16::*, packed_32::*, packed_64::*,
5	packed_128::*, packed_256::*, packed_512::*,
6};
7
8/// Common code to test different multiply, square and invert implementations
9#[cfg(test)]
10pub mod test_utils {
11	use crate::{
12		BinaryField, PackedField,
13		linear_transformation::PackedTransformationFactory,
14		underlier::{U1, U2, U4, WithUnderlier},
15	};
16
17	pub struct Unit;
18
19	impl From<U1> for Unit {
20		fn from(_: U1) -> Self {
21			Self
22		}
23	}
24
25	impl From<U2> for Unit {
26		fn from(_: U2) -> Self {
27			Self
28		}
29	}
30
31	impl From<U4> for Unit {
32		fn from(_: U4) -> Self {
33			Self
34		}
35	}
36
37	impl From<u8> for Unit {
38		fn from(_: u8) -> Self {
39			Self
40		}
41	}
42
43	impl From<u16> for Unit {
44		fn from(_: u16) -> Self {
45			Self
46		}
47	}
48
49	impl From<u32> for Unit {
50		fn from(_: u32) -> Self {
51			Self
52		}
53	}
54
55	impl From<u64> for Unit {
56		fn from(_: u64) -> Self {
57			Self
58		}
59	}
60
61	impl From<u128> for Unit {
62		fn from(_: u128) -> Self {
63			Self
64		}
65	}
66
67	impl From<[u128; 2]> for Unit {
68		fn from(_: [u128; 2]) -> Self {
69			Self
70		}
71	}
72
73	impl From<[u128; 4]> for Unit {
74		fn from(_: [u128; 4]) -> Self {
75			Self
76		}
77	}
78
79	/// We use such helper macros to run tests only for the
80	/// types that implement the `constraint` trait.
81	/// The idea is inspired by `impls` trait.
82	macro_rules! define_check_packed_mul {
83		($mult_func:path, $constraint:path) => {
84			#[allow(unused)]
85			trait TestMulTrait<T> {
86				fn test_mul(_a: T, _b: T) {}
87			}
88
89			impl<T> TestMulTrait<$crate::packed_binary_field::test_utils::Unit> for T {}
90
91			struct TestMult<T>(std::marker::PhantomData<T>);
92
93			impl<T: $constraint + PackedField + $crate::underlier::WithUnderlier> TestMult<T> {
94				fn test_mul(
95					a: <T as $crate::underlier::WithUnderlier>::Underlier,
96					b: <T as $crate::underlier::WithUnderlier>::Underlier,
97				) {
98					let a = T::from_underlier(a);
99					let b = T::from_underlier(b);
100
101					let c = $mult_func(a, b);
102					for i in 0..T::WIDTH {
103						assert_eq!(c.get(i), a.get(i) * b.get(i));
104					}
105				}
106			}
107		};
108	}
109
110	pub(crate) use define_check_packed_mul;
111
112	macro_rules! define_check_packed_square {
113		($square_func:path, $constraint:path) => {
114			#[allow(unused)]
115			trait TestSquareTrait<T> {
116				fn test_square(_a: T) {}
117			}
118
119			impl<T> TestSquareTrait<$crate::packed_binary_field::test_utils::Unit> for T {}
120
121			struct TestSquare<T>(std::marker::PhantomData<T>);
122
123			impl<T: $constraint + PackedField + $crate::underlier::WithUnderlier> TestSquare<T> {
124				fn test_square(a: <T as $crate::underlier::WithUnderlier>::Underlier) {
125					let a = T::from_underlier(a);
126
127					let c = $square_func(a);
128					for i in 0..T::WIDTH {
129						assert_eq!(c.get(i), a.get(i) * a.get(i));
130					}
131				}
132			}
133		};
134	}
135
136	pub(crate) use define_check_packed_square;
137
138	macro_rules! define_check_packed_inverse {
139		($invert_func:path, $constraint:path) => {
140			#[allow(unused)]
141			trait TestInvertTrait<T> {
142				fn test_invert(_a: T) {}
143			}
144
145			impl<T> TestInvertTrait<$crate::packed_binary_field::test_utils::Unit> for T {}
146
147			struct TestInvert<T>(std::marker::PhantomData<T>);
148
149			#[allow(unused)]
150			impl<T: $constraint + PackedField + $crate::underlier::WithUnderlier> TestInvert<T> {
151				fn test_invert(a: <T as $crate::underlier::WithUnderlier>::Underlier) {
152					use crate::Field;
153
154					let a = T::from_underlier(a);
155
156					let c = $invert_func(a);
157					for i in 0..T::WIDTH {
158						assert!(
159							(c.get(i).is_zero().into()
160								&& a.get(i).is_zero().into()
161								&& c.get(i).is_zero().into())
162								|| T::Scalar::ONE == a.get(i) * c.get(i)
163						);
164					}
165				}
166			}
167		};
168	}
169
170	pub(crate) use define_check_packed_inverse;
171
172	macro_rules! define_check_packed_mul_alpha {
173		($mul_alpha_func:path, $constraint:path) => {
174			#[allow(unused)]
175			trait TestMulAlphaTrait<T> {
176				fn test_mul_alpha(_a: T) {}
177			}
178
179			impl<T> TestMulAlphaTrait<$crate::packed_binary_field::test_utils::Unit> for T {}
180
181			struct TestMulAlpha<T>(std::marker::PhantomData<T>);
182
183			impl<T: $constraint + PackedField + $crate::underlier::WithUnderlier> TestMulAlpha<T>
184			where
185				T::Scalar: $crate::arithmetic_traits::MulAlpha,
186			{
187				fn test_mul_alpha(a: <T as $crate::underlier::WithUnderlier>::Underlier) {
188					use $crate::arithmetic_traits::MulAlpha;
189
190					let a = T::from_underlier(a);
191
192					let c = $mul_alpha_func(a);
193					for i in 0..T::WIDTH {
194						assert_eq!(c.get(i), MulAlpha::mul_alpha(a.get(i)));
195					}
196				}
197			}
198		};
199	}
200
201	pub(crate) use define_check_packed_mul_alpha;
202
203	macro_rules! define_check_packed_transformation {
204		($constraint:path) => {
205			#[allow(unused)]
206			trait TestTransformationTrait<T> {
207				fn test_transformation(_a: T) {}
208			}
209
210			impl<T> TestTransformationTrait<$crate::packed_binary_field::test_utils::Unit> for T {}
211
212			struct TestTransformation<T>(std::marker::PhantomData<T>);
213
214			impl<T: $constraint + PackedField + $crate::underlier::WithUnderlier>
215				TestTransformation<T>
216			{
217				fn test_transformation(a: <T as $crate::underlier::WithUnderlier>::Underlier) {
218					use $crate::linear_transformation::{
219						FieldLinearTransformation, Transformation,
220					};
221
222					let a = T::from_underlier(a);
223
224					// TODO: think how we can use random seed from proptests here
225					let field_transformation =
226						FieldLinearTransformation::<T::Scalar, _>::random(rand::thread_rng());
227					let packed_transformation =
228						T::make_packed_transformation(field_transformation.clone());
229
230					let c = packed_transformation.transform(&a);
231					for i in 0..T::WIDTH {
232						assert_eq!(c.get(i), field_transformation.transform(&a.get(i)));
233					}
234				}
235			}
236		};
237	}
238
239	pub(crate) use define_check_packed_transformation;
240
241	/// Test if `mult_func` operation is a valid multiply operation on the given values for
242	/// all possible packed fields defined on u128.
243	macro_rules! define_multiply_tests {
244		($mult_func:path, $constraint:path) => {
245			$crate::packed_binary_field::test_utils::define_check_packed_mul!(
246				$mult_func,
247				$constraint
248			);
249
250			proptest::proptest! {
251				#[test]
252				fn test_mul_packed_8(a_val in proptest::prelude::any::<u8>(), b_val in proptest::prelude::any::<u8>()) {
253					use $crate::arch::packed_8::*;
254
255					TestMult::<PackedBinaryField8x1b>::test_mul(a_val.into(), b_val.into());
256					TestMult::<PackedBinaryField4x2b>::test_mul(a_val.into(), b_val.into());
257					TestMult::<PackedBinaryField2x4b>::test_mul(a_val.into(), b_val.into());
258					TestMult::<PackedBinaryField1x8b>::test_mul(a_val.into(), b_val.into());
259				}
260
261				#[test]
262				fn test_mul_packed_16(a_val in proptest::prelude::any::<u16>(), b_val in proptest::prelude::any::<u16>()) {
263					use $crate::arch::packed_16::*;
264
265					TestMult::<PackedBinaryField16x1b>::test_mul(a_val.into(), b_val.into());
266					TestMult::<PackedBinaryField8x2b>::test_mul(a_val.into(), b_val.into());
267					TestMult::<PackedBinaryField4x4b>::test_mul(a_val.into(), b_val.into());
268					TestMult::<PackedBinaryField2x8b>::test_mul(a_val.into(), b_val.into());
269					TestMult::<PackedBinaryField1x16b>::test_mul(a_val.into(), b_val.into());
270				}
271
272				#[test]
273				fn test_mul_packed_32(a_val in proptest::prelude::any::<u32>(), b_val in proptest::prelude::any::<u32>()) {
274					use $crate::arch::packed_32::*;
275
276					TestMult::<PackedBinaryField32x1b>::test_mul(a_val.into(), b_val.into());
277					TestMult::<PackedBinaryField16x2b>::test_mul(a_val.into(), b_val.into());
278					TestMult::<PackedBinaryField8x4b>::test_mul(a_val.into(), b_val.into());
279					TestMult::<PackedBinaryField4x8b>::test_mul(a_val.into(), b_val.into());
280					TestMult::<PackedBinaryField2x16b>::test_mul(a_val.into(), b_val.into());
281					TestMult::<PackedBinaryField1x32b>::test_mul(a_val.into(), b_val.into());
282				}
283
284				#[test]
285				fn test_mul_packed_64(a_val in proptest::prelude::any::<u64>(), b_val in proptest::prelude::any::<u64>()) {
286					use $crate::arch::packed_64::*;
287
288					TestMult::<PackedBinaryField64x1b>::test_mul(a_val.into(), b_val.into());
289					TestMult::<PackedBinaryField32x2b>::test_mul(a_val.into(), b_val.into());
290					TestMult::<PackedBinaryField16x4b>::test_mul(a_val.into(), b_val.into());
291					TestMult::<PackedBinaryField8x8b>::test_mul(a_val.into(), b_val.into());
292					TestMult::<PackedBinaryField4x16b>::test_mul(a_val.into(), b_val.into());
293					TestMult::<PackedBinaryField2x32b>::test_mul(a_val.into(), b_val.into());
294					TestMult::<PackedBinaryField1x64b>::test_mul(a_val.into(), b_val.into());
295				}
296
297				#[test]
298				fn test_mul_packed_128(a_val in proptest::prelude::any::<u128>(), b_val in proptest::prelude::any::<u128>()) {
299					use $crate::arch::packed_128::*;
300
301					TestMult::<PackedBinaryField128x1b>::test_mul(a_val.into(), b_val.into());
302					TestMult::<PackedBinaryField64x2b>::test_mul(a_val.into(), b_val.into());
303					TestMult::<PackedBinaryField32x4b>::test_mul(a_val.into(), b_val.into());
304					TestMult::<PackedBinaryField16x8b>::test_mul(a_val.into(), b_val.into());
305					TestMult::<PackedBinaryField8x16b>::test_mul(a_val.into(), b_val.into());
306					TestMult::<PackedBinaryField4x32b>::test_mul(a_val.into(), b_val.into());
307					TestMult::<PackedBinaryField2x64b>::test_mul(a_val.into(), b_val.into());
308					TestMult::<PackedBinaryField1x128b>::test_mul(a_val.into(), b_val.into());
309				}
310
311				#[test]
312				fn test_mul_packed_256(a_val in proptest::prelude::any::<[u128; 2]>(), b_val in proptest::prelude::any::<[u128; 2]>()) {
313					use $crate::arch::packed_256::*;
314
315					TestMult::<PackedBinaryField256x1b>::test_mul(a_val.into(), b_val.into());
316					TestMult::<PackedBinaryField128x2b>::test_mul(a_val.into(), b_val.into());
317					TestMult::<PackedBinaryField64x4b>::test_mul(a_val.into(), b_val.into());
318					TestMult::<PackedBinaryField32x8b>::test_mul(a_val.into(), b_val.into());
319					TestMult::<PackedBinaryField16x16b>::test_mul(a_val.into(), b_val.into());
320					TestMult::<PackedBinaryField8x32b>::test_mul(a_val.into(), b_val.into());
321					TestMult::<PackedBinaryField4x64b>::test_mul(a_val.into(), b_val.into());
322					TestMult::<PackedBinaryField2x128b>::test_mul(a_val.into(), b_val.into());
323				}
324
325				#[test]
326				fn test_mul_packed_512(a_val in proptest::prelude::any::<[u128; 4]>(), b_val in proptest::prelude::any::<[u128; 4]>()) {
327					use $crate::arch::packed_512::*;
328
329					TestMult::<PackedBinaryField512x1b>::test_mul(a_val.into(), b_val.into());
330					TestMult::<PackedBinaryField256x2b>::test_mul(a_val.into(), b_val.into());
331					TestMult::<PackedBinaryField128x4b>::test_mul(a_val.into(), b_val.into());
332					TestMult::<PackedBinaryField64x8b>::test_mul(a_val.into(), b_val.into());
333					TestMult::<PackedBinaryField32x16b>::test_mul(a_val.into(), b_val.into());
334					TestMult::<PackedBinaryField16x32b>::test_mul(a_val.into(), b_val.into());
335					TestMult::<PackedBinaryField8x64b>::test_mul(a_val.into(), b_val.into());
336					TestMult::<PackedBinaryField4x128b>::test_mul(a_val.into(), b_val.into());
337				}
338			}
339		};
340	}
341
342	/// Test if `square_func` operation is a valid square operation on the given value for
343	/// all possible packed fields.
344	macro_rules! define_square_tests {
345		($square_func:path, $constraint:path) => {
346			$crate::packed_binary_field::test_utils::define_check_packed_square!(
347				$square_func,
348				$constraint
349			);
350
351			proptest::proptest! {
352				#[test]
353				fn test_square_packed_8(a_val in proptest::prelude::any::<u8>()) {
354					use $crate::arch::packed_8::*;
355
356					TestSquare::<PackedBinaryField8x1b>::test_square(a_val.into());
357					TestSquare::<PackedBinaryField4x2b>::test_square(a_val.into());
358					TestSquare::<PackedBinaryField2x4b>::test_square(a_val.into());
359					TestSquare::<PackedBinaryField1x8b>::test_square(a_val.into());
360				}
361
362				#[test]
363				fn test_square_packed_16(a_val in proptest::prelude::any::<u16>()) {
364					use $crate::arch::packed_16::*;
365
366					TestSquare::<PackedBinaryField16x1b>::test_square(a_val.into());
367					TestSquare::<PackedBinaryField8x2b>::test_square(a_val.into());
368					TestSquare::<PackedBinaryField4x4b>::test_square(a_val.into());
369					TestSquare::<PackedBinaryField2x8b>::test_square(a_val.into());
370					TestSquare::<PackedBinaryField1x16b>::test_square(a_val.into());
371				}
372
373				#[test]
374				fn test_square_packed_32(a_val in proptest::prelude::any::<u32>()) {
375					use $crate::arch::packed_32::*;
376
377					TestSquare::<PackedBinaryField32x1b>::test_square(a_val.into());
378					TestSquare::<PackedBinaryField16x2b>::test_square(a_val.into());
379					TestSquare::<PackedBinaryField8x4b>::test_square(a_val.into());
380					TestSquare::<PackedBinaryField4x8b>::test_square(a_val.into());
381					TestSquare::<PackedBinaryField2x16b>::test_square(a_val.into());
382					TestSquare::<PackedBinaryField1x32b>::test_square(a_val.into());
383				}
384
385				#[test]
386				fn test_square_packed_64(a_val in proptest::prelude::any::<u64>()) {
387					use $crate::arch::packed_64::*;
388
389					TestSquare::<PackedBinaryField64x1b>::test_square(a_val.into());
390					TestSquare::<PackedBinaryField32x2b>::test_square(a_val.into());
391					TestSquare::<PackedBinaryField16x4b>::test_square(a_val.into());
392					TestSquare::<PackedBinaryField8x8b>::test_square(a_val.into());
393					TestSquare::<PackedBinaryField4x16b>::test_square(a_val.into());
394					TestSquare::<PackedBinaryField2x32b>::test_square(a_val.into());
395					TestSquare::<PackedBinaryField1x64b>::test_square(a_val.into());
396				}
397
398				#[test]
399				fn test_square_packed_128(a_val in proptest::prelude::any::<u128>()) {
400					use $crate::arch::packed_128::*;
401
402					TestSquare::<PackedBinaryField128x1b>::test_square(a_val.into());
403					TestSquare::<PackedBinaryField64x2b>::test_square(a_val.into());
404					TestSquare::<PackedBinaryField32x4b>::test_square(a_val.into());
405					TestSquare::<PackedBinaryField16x8b>::test_square(a_val.into());
406					TestSquare::<PackedBinaryField8x16b>::test_square(a_val.into());
407					TestSquare::<PackedBinaryField4x32b>::test_square(a_val.into());
408					TestSquare::<PackedBinaryField2x64b>::test_square(a_val.into());
409					TestSquare::<PackedBinaryField1x128b>::test_square(a_val.into());
410				}
411
412				#[test]
413				fn test_square_packed_256(a_val in proptest::prelude::any::<[u128; 2]>()) {
414					use $crate::arch::packed_256::*;
415
416					TestSquare::<PackedBinaryField256x1b>::test_square(a_val.into());
417					TestSquare::<PackedBinaryField128x2b>::test_square(a_val.into());
418					TestSquare::<PackedBinaryField64x4b>::test_square(a_val.into());
419					TestSquare::<PackedBinaryField32x8b>::test_square(a_val.into());
420					TestSquare::<PackedBinaryField16x16b>::test_square(a_val.into());
421					TestSquare::<PackedBinaryField8x32b>::test_square(a_val.into());
422					TestSquare::<PackedBinaryField4x64b>::test_square(a_val.into());
423					TestSquare::<PackedBinaryField2x128b>::test_square(a_val.into());
424				}
425
426				#[test]
427				fn test_square_packed_512(a_val in proptest::prelude::any::<[u128; 4]>()) {
428					use $crate::arch::packed_512::*;
429
430					TestSquare::<PackedBinaryField512x1b>::test_square(a_val.into());
431					TestSquare::<PackedBinaryField256x2b>::test_square(a_val.into());
432					TestSquare::<PackedBinaryField128x4b>::test_square(a_val.into());
433					TestSquare::<PackedBinaryField64x8b>::test_square(a_val.into());
434					TestSquare::<PackedBinaryField32x16b>::test_square(a_val.into());
435					TestSquare::<PackedBinaryField16x32b>::test_square(a_val.into());
436					TestSquare::<PackedBinaryField8x64b>::test_square(a_val.into());
437					TestSquare::<PackedBinaryField4x128b>::test_square(a_val.into());
438				}
439			}
440		};
441	}
442
443	/// Test if `invert_func` operation is a valid invert operation on the given value for
444	/// all possible packed fields.
445	macro_rules! define_invert_tests {
446		($invert_func:path, $constraint:path) => {
447			$crate::packed_binary_field::test_utils::define_check_packed_inverse!(
448				$invert_func,
449				$constraint
450			);
451
452			proptest::proptest! {
453				#[test]
454				fn test_invert_packed_8(a_val in proptest::prelude::any::<u8>()) {
455					use $crate::arch::packed_8::*;
456
457					TestInvert::<PackedBinaryField8x1b>::test_invert(a_val.into());
458					TestInvert::<PackedBinaryField4x2b>::test_invert(a_val.into());
459					TestInvert::<PackedBinaryField2x4b>::test_invert(a_val.into());
460					TestInvert::<PackedBinaryField1x8b>::test_invert(a_val.into());
461				}
462
463				#[test]
464				fn test_invert_packed_16(a_val in proptest::prelude::any::<u16>()) {
465					use $crate::arch::packed_16::*;
466
467					TestInvert::<PackedBinaryField16x1b>::test_invert(a_val.into());
468					TestInvert::<PackedBinaryField8x2b>::test_invert(a_val.into());
469					TestInvert::<PackedBinaryField4x4b>::test_invert(a_val.into());
470					TestInvert::<PackedBinaryField2x8b>::test_invert(a_val.into());
471					TestInvert::<PackedBinaryField1x16b>::test_invert(a_val.into());
472				}
473
474				#[test]
475				fn test_invert_packed_32(a_val in proptest::prelude::any::<u32>()) {
476					use $crate::arch::packed_32::*;
477
478					TestInvert::<PackedBinaryField32x1b>::test_invert(a_val.into());
479					TestInvert::<PackedBinaryField16x2b>::test_invert(a_val.into());
480					TestInvert::<PackedBinaryField8x4b>::test_invert(a_val.into());
481					TestInvert::<PackedBinaryField4x8b>::test_invert(a_val.into());
482					TestInvert::<PackedBinaryField2x16b>::test_invert(a_val.into());
483					TestInvert::<PackedBinaryField1x32b>::test_invert(a_val.into());
484				}
485
486				#[test]
487				fn test_invert_packed_64(a_val in proptest::prelude::any::<u64>()) {
488					use $crate::arch::packed_64::*;
489
490					TestInvert::<PackedBinaryField64x1b>::test_invert(a_val.into());
491					TestInvert::<PackedBinaryField32x2b>::test_invert(a_val.into());
492					TestInvert::<PackedBinaryField16x4b>::test_invert(a_val.into());
493					TestInvert::<PackedBinaryField8x8b>::test_invert(a_val.into());
494					TestInvert::<PackedBinaryField4x16b>::test_invert(a_val.into());
495					TestInvert::<PackedBinaryField2x32b>::test_invert(a_val.into());
496					TestInvert::<PackedBinaryField1x64b>::test_invert(a_val.into());
497				}
498
499				#[test]
500				fn test_invert_packed_128(a_val in proptest::prelude::any::<u128>()) {
501					use $crate::arch::packed_128::*;
502
503					TestInvert::<PackedBinaryField128x1b>::test_invert(a_val.into());
504					TestInvert::<PackedBinaryField64x2b>::test_invert(a_val.into());
505					TestInvert::<PackedBinaryField32x4b>::test_invert(a_val.into());
506					TestInvert::<PackedBinaryField16x8b>::test_invert(a_val.into());
507					TestInvert::<PackedBinaryField8x16b>::test_invert(a_val.into());
508					TestInvert::<PackedBinaryField4x32b>::test_invert(a_val.into());
509					TestInvert::<PackedBinaryField2x64b>::test_invert(a_val.into());
510					TestInvert::<PackedBinaryField1x128b>::test_invert(a_val.into());
511				}
512
513				#[test]
514				fn test_invert_packed_256(a_val in proptest::prelude::any::<[u128; 2]>()) {
515					use $crate::arch::packed_256::*;
516
517					TestInvert::<PackedBinaryField256x1b>::test_invert(a_val.into());
518					TestInvert::<PackedBinaryField128x2b>::test_invert(a_val.into());
519					TestInvert::<PackedBinaryField64x4b>::test_invert(a_val.into());
520					TestInvert::<PackedBinaryField32x8b>::test_invert(a_val.into());
521					TestInvert::<PackedBinaryField16x16b>::test_invert(a_val.into());
522					TestInvert::<PackedBinaryField8x32b>::test_invert(a_val.into());
523					TestInvert::<PackedBinaryField4x64b>::test_invert(a_val.into());
524					TestInvert::<PackedBinaryField2x128b>::test_invert(a_val.into());
525				}
526
527				#[test]
528				fn test_invert_packed_512(a_val in proptest::prelude::any::<[u128; 4]>()) {
529					use $crate::arch::packed_512::*;
530
531					TestInvert::<PackedBinaryField512x1b>::test_invert(a_val.into());
532					TestInvert::<PackedBinaryField256x2b>::test_invert(a_val.into());
533					TestInvert::<PackedBinaryField128x4b>::test_invert(a_val.into());
534					TestInvert::<PackedBinaryField64x8b>::test_invert(a_val.into());
535					TestInvert::<PackedBinaryField32x16b>::test_invert(a_val.into());
536					TestInvert::<PackedBinaryField16x32b>::test_invert(a_val.into());
537					TestInvert::<PackedBinaryField8x64b>::test_invert(a_val.into());
538					TestInvert::<PackedBinaryField4x128b>::test_invert(a_val.into());
539				}
540			}
541		};
542	}
543
544	/// Test if `mul_alpha_func` operation is a valid multiply by alpha operation on the given value
545	/// for all possible packed fields.
546	macro_rules! define_mul_alpha_tests {
547		($mul_alpha_func:path, $constraint:path) => {
548			$crate::packed_binary_field::test_utils::define_check_packed_mul_alpha!(
549				$mul_alpha_func,
550				$constraint
551			);
552
553			proptest::proptest! {
554				#[test]
555				fn test_mul_alpha_packed_8(a_val in proptest::prelude::any::<u8>()) {
556					use $crate::arch::packed_8::*;
557
558					TestMulAlpha::<PackedBinaryField8x1b>::test_mul_alpha(a_val.into());
559					TestMulAlpha::<PackedBinaryField4x2b>::test_mul_alpha(a_val.into());
560					TestMulAlpha::<PackedBinaryField2x4b>::test_mul_alpha(a_val.into());
561					TestMulAlpha::<PackedBinaryField1x8b>::test_mul_alpha(a_val.into());
562				}
563
564				#[test]
565				fn test_mul_alpha_packed_16(a_val in proptest::prelude::any::<u16>()) {
566					use $crate::arch::packed_16::*;
567
568					TestMulAlpha::<PackedBinaryField16x1b>::test_mul_alpha(a_val.into());
569					TestMulAlpha::<PackedBinaryField8x2b>::test_mul_alpha(a_val.into());
570					TestMulAlpha::<PackedBinaryField4x4b>::test_mul_alpha(a_val.into());
571					TestMulAlpha::<PackedBinaryField2x8b>::test_mul_alpha(a_val.into());
572					TestMulAlpha::<PackedBinaryField1x16b>::test_mul_alpha(a_val.into());
573				}
574
575				#[test]
576				fn test_mul_alpha_packed_32(a_val in proptest::prelude::any::<u32>()) {
577					use $crate::arch::packed_32::*;
578
579					TestMulAlpha::<PackedBinaryField32x1b>::test_mul_alpha(a_val.into());
580					TestMulAlpha::<PackedBinaryField16x2b>::test_mul_alpha(a_val.into());
581					TestMulAlpha::<PackedBinaryField8x4b>::test_mul_alpha(a_val.into());
582					TestMulAlpha::<PackedBinaryField4x8b>::test_mul_alpha(a_val.into());
583					TestMulAlpha::<PackedBinaryField2x16b>::test_mul_alpha(a_val.into());
584					TestMulAlpha::<PackedBinaryField1x32b>::test_mul_alpha(a_val.into());
585				}
586
587				#[test]
588				fn test_mul_alpha_packed_64(a_val in proptest::prelude::any::<u64>()) {
589					use $crate::arch::packed_64::*;
590
591					TestMulAlpha::<PackedBinaryField64x1b>::test_mul_alpha(a_val.into());
592					TestMulAlpha::<PackedBinaryField32x2b>::test_mul_alpha(a_val.into());
593					TestMulAlpha::<PackedBinaryField16x4b>::test_mul_alpha(a_val.into());
594					TestMulAlpha::<PackedBinaryField8x8b>::test_mul_alpha(a_val.into());
595					TestMulAlpha::<PackedBinaryField4x16b>::test_mul_alpha(a_val.into());
596					TestMulAlpha::<PackedBinaryField2x32b>::test_mul_alpha(a_val.into());
597					TestMulAlpha::<PackedBinaryField1x64b>::test_mul_alpha(a_val.into());
598				}
599
600				#[test]
601				fn test_mul_alpha_packed_128(a_val in proptest::prelude::any::<u128>()) {
602					use $crate::arch::packed_128::*;
603
604					TestMulAlpha::<PackedBinaryField128x1b>::test_mul_alpha(a_val.into());
605					TestMulAlpha::<PackedBinaryField64x2b>::test_mul_alpha(a_val.into());
606					TestMulAlpha::<PackedBinaryField32x4b>::test_mul_alpha(a_val.into());
607					TestMulAlpha::<PackedBinaryField16x8b>::test_mul_alpha(a_val.into());
608					TestMulAlpha::<PackedBinaryField8x16b>::test_mul_alpha(a_val.into());
609					TestMulAlpha::<PackedBinaryField4x32b>::test_mul_alpha(a_val.into());
610					TestMulAlpha::<PackedBinaryField2x64b>::test_mul_alpha(a_val.into());
611					TestMulAlpha::<PackedBinaryField1x128b>::test_mul_alpha(a_val.into());
612				}
613
614				#[test]
615				fn test_mul_alpha_packed_256(a_val in proptest::prelude::any::<[u128; 2]>()) {
616					use $crate::arch::packed_256::*;
617
618					TestMulAlpha::<PackedBinaryField256x1b>::test_mul_alpha(a_val.into());
619					TestMulAlpha::<PackedBinaryField128x2b>::test_mul_alpha(a_val.into());
620					TestMulAlpha::<PackedBinaryField64x4b>::test_mul_alpha(a_val.into());
621					TestMulAlpha::<PackedBinaryField32x8b>::test_mul_alpha(a_val.into());
622					TestMulAlpha::<PackedBinaryField16x16b>::test_mul_alpha(a_val.into());
623					TestMulAlpha::<PackedBinaryField8x32b>::test_mul_alpha(a_val.into());
624					TestMulAlpha::<PackedBinaryField4x64b>::test_mul_alpha(a_val.into());
625					TestMulAlpha::<PackedBinaryField2x128b>::test_mul_alpha(a_val.into());
626				}
627
628				#[test]
629				fn test_mul_alpha_packed_512(a_val in proptest::prelude::any::<[u128; 4]>()) {
630					use $crate::arch::packed_512::*;
631
632					TestMulAlpha::<PackedBinaryField512x1b>::test_mul_alpha(a_val.into());
633					TestMulAlpha::<PackedBinaryField256x2b>::test_mul_alpha(a_val.into());
634					TestMulAlpha::<PackedBinaryField128x4b>::test_mul_alpha(a_val.into());
635					TestMulAlpha::<PackedBinaryField64x8b>::test_mul_alpha(a_val.into());
636					TestMulAlpha::<PackedBinaryField32x16b>::test_mul_alpha(a_val.into());
637					TestMulAlpha::<PackedBinaryField16x32b>::test_mul_alpha(a_val.into());
638					TestMulAlpha::<PackedBinaryField8x64b>::test_mul_alpha(a_val.into());
639					TestMulAlpha::<PackedBinaryField4x128b>::test_mul_alpha(a_val.into());
640				}
641			}
642		};
643	}
644
645	/// Test if `$constraint::make_packed_transformation` operation creates a valid transformation
646	/// operation on the given value for all possible packed fields.
647	macro_rules! define_transformation_tests {
648		($constraint:path) => {
649			$crate::packed_binary_field::test_utils::define_check_packed_transformation!(
650				$constraint
651			);
652
653			proptest::proptest! {
654				#[test]
655				fn test_transformation_packed_1(a_val in 0..2u8) {
656					use crate::arch::packed_1::*;
657
658					TestTransformation::<PackedBinaryField1x1b>::test_transformation($crate::underlier::U1::new_unchecked(a_val).into());
659				}
660
661				#[test]
662				fn test_transformation_packed_2(a_val in 0..4u8) {
663					use crate::arch::packed_2::*;
664
665					TestTransformation::<PackedBinaryField2x1b>::test_transformation($crate::underlier::U2::new_unchecked(a_val).into());
666					TestTransformation::<PackedBinaryField1x2b>::test_transformation($crate::underlier::U2::new_unchecked(a_val).into());
667				}
668
669				#[test]
670				fn test_transformation_packed_4(a_val in 0..16u8) {
671					use crate::arch::packed_4::*;
672
673					TestTransformation::<PackedBinaryField4x1b>::test_transformation($crate::underlier::U4::new_unchecked(a_val).into());
674					TestTransformation::<PackedBinaryField2x2b>::test_transformation($crate::underlier::U4::new_unchecked(a_val).into());
675					TestTransformation::<PackedBinaryField1x4b>::test_transformation($crate::underlier::U4::new_unchecked(a_val).into());
676				}
677
678				#[test]
679				fn test_transformation_packed_8(a_val in proptest::prelude::any::<u8>()) {
680					use crate::arch::packed_8::*;
681
682					TestTransformation::<PackedBinaryField8x1b>::test_transformation(a_val.into());
683					TestTransformation::<PackedBinaryField4x2b>::test_transformation(a_val.into());
684					TestTransformation::<PackedBinaryField2x4b>::test_transformation(a_val.into());
685					TestTransformation::<PackedBinaryField1x8b>::test_transformation(a_val.into());
686				}
687
688				#[test]
689				fn test_transformation_packed_16(a_val in proptest::prelude::any::<u16>()) {
690					use crate::arch::packed_16::*;
691
692					TestTransformation::<PackedBinaryField16x1b>::test_transformation(a_val.into());
693					TestTransformation::<PackedBinaryField8x2b>::test_transformation(a_val.into());
694					TestTransformation::<PackedBinaryField4x4b>::test_transformation(a_val.into());
695					TestTransformation::<PackedBinaryField2x8b>::test_transformation(a_val.into());
696					TestTransformation::<PackedBinaryField1x16b>::test_transformation(a_val.into());
697				}
698
699				#[test]
700				fn test_transformation_packed_32(a_val in proptest::prelude::any::<u32>()) {
701					use crate::arch::packed_32::*;
702
703					TestTransformation::<PackedBinaryField32x1b>::test_transformation(a_val.into());
704					TestTransformation::<PackedBinaryField16x2b>::test_transformation(a_val.into());
705					TestTransformation::<PackedBinaryField8x4b>::test_transformation(a_val.into());
706					TestTransformation::<PackedBinaryField4x8b>::test_transformation(a_val.into());
707					TestTransformation::<PackedBinaryField2x16b>::test_transformation(a_val.into());
708					TestTransformation::<PackedBinaryField1x32b>::test_transformation(a_val.into());
709				}
710
711				#[test]
712				fn test_transformation_packed_64(a_val in proptest::prelude::any::<u64>()) {
713					use $crate::arch::packed_64::*;
714
715					TestTransformation::<PackedBinaryField64x1b>::test_transformation(a_val.into());
716					TestTransformation::<PackedBinaryField32x2b>::test_transformation(a_val.into());
717					TestTransformation::<PackedBinaryField16x4b>::test_transformation(a_val.into());
718					TestTransformation::<PackedBinaryField8x8b>::test_transformation(a_val.into());
719					TestTransformation::<PackedBinaryField4x16b>::test_transformation(a_val.into());
720					TestTransformation::<PackedBinaryField2x32b>::test_transformation(a_val.into());
721					TestTransformation::<PackedBinaryField1x64b>::test_transformation(a_val.into());
722				}
723
724				#[test]
725				fn test_transformation_packed_128(a_val in proptest::prelude::any::<u128>()) {
726					use $crate::arch::packed_128::*;
727
728					TestTransformation::<PackedBinaryField128x1b>::test_transformation(a_val.into());
729					TestTransformation::<PackedBinaryField64x2b>::test_transformation(a_val.into());
730					TestTransformation::<PackedBinaryField32x4b>::test_transformation(a_val.into());
731					TestTransformation::<PackedBinaryField16x8b>::test_transformation(a_val.into());
732					TestTransformation::<PackedBinaryField8x16b>::test_transformation(a_val.into());
733					TestTransformation::<PackedBinaryField4x32b>::test_transformation(a_val.into());
734					TestTransformation::<PackedBinaryField2x64b>::test_transformation(a_val.into());
735					TestTransformation::<PackedBinaryField1x128b>::test_transformation(a_val.into());
736				}
737
738				#[test]
739				fn test_transformation_packed_256(a_val in proptest::prelude::any::<[u128; 2]>()) {
740					use $crate::arch::packed_256::*;
741
742					TestTransformation::<PackedBinaryField256x1b>::test_transformation(a_val.into());
743					TestTransformation::<PackedBinaryField128x2b>::test_transformation(a_val.into());
744					TestTransformation::<PackedBinaryField64x4b>::test_transformation(a_val.into());
745					TestTransformation::<PackedBinaryField32x8b>::test_transformation(a_val.into());
746					TestTransformation::<PackedBinaryField16x16b>::test_transformation(a_val.into());
747					TestTransformation::<PackedBinaryField8x32b>::test_transformation(a_val.into());
748					TestTransformation::<PackedBinaryField4x64b>::test_transformation(a_val.into());
749					TestTransformation::<PackedBinaryField2x128b>::test_transformation(a_val.into());
750				}
751
752				#[test]
753				fn test_transformation_packed_512(a_val in proptest::prelude::any::<[u128; 4]>()) {
754					use $crate::arch::packed_512::*;
755
756					TestTransformation::<PackedBinaryField512x1b>::test_transformation(a_val.into());
757					TestTransformation::<PackedBinaryField256x2b>::test_transformation(a_val.into());
758					TestTransformation::<PackedBinaryField128x4b>::test_transformation(a_val.into());
759					TestTransformation::<PackedBinaryField64x8b>::test_transformation(a_val.into());
760					TestTransformation::<PackedBinaryField32x16b>::test_transformation(a_val.into());
761					TestTransformation::<PackedBinaryField16x32b>::test_transformation(a_val.into());
762					TestTransformation::<PackedBinaryField8x64b>::test_transformation(a_val.into());
763					TestTransformation::<PackedBinaryField4x128b>::test_transformation(a_val.into());
764				}
765			}
766		};
767	}
768
769	pub(crate) use define_invert_tests;
770	pub(crate) use define_mul_alpha_tests;
771	pub(crate) use define_multiply_tests;
772	pub(crate) use define_square_tests;
773	pub(crate) use define_transformation_tests;
774
775	/// Helper function for compile-time checks
776	#[allow(unused)]
777	pub const fn implements_transformation_factory<
778		P1: PackedField<Scalar: BinaryField>,
779		P2: PackedTransformationFactory<P1>,
780	>() {
781	}
782
783	pub fn check_interleave<P: PackedField + WithUnderlier>(
784		lhs: P::Underlier,
785		rhs: P::Underlier,
786		log_block_len: usize,
787	) {
788		let lhs = P::from_underlier(lhs);
789		let rhs = P::from_underlier(rhs);
790		let (a, b) = lhs.interleave(rhs, log_block_len);
791		let block_len = 1 << log_block_len;
792		for i in (0..P::WIDTH).step_by(block_len * 2) {
793			for j in 0..block_len {
794				assert_eq!(a.get(i + j), lhs.get(i + j));
795				assert_eq!(a.get(i + j + block_len), rhs.get(i + j));
796
797				assert_eq!(b.get(i + j), lhs.get(i + j + block_len));
798				assert_eq!(b.get(i + j + block_len), rhs.get(i + j + block_len));
799			}
800		}
801	}
802
803	pub fn check_interleave_all_heights<P: PackedField + WithUnderlier>(
804		lhs: P::Underlier,
805		rhs: P::Underlier,
806	) {
807		for log_block_len in 0..P::LOG_WIDTH {
808			check_interleave::<P>(lhs, rhs, log_block_len);
809		}
810	}
811
812	pub fn check_unzip<P: PackedField + WithUnderlier>(
813		lhs: P::Underlier,
814		rhs: P::Underlier,
815		log_block_len: usize,
816	) {
817		let lhs = P::from_underlier(lhs);
818		let rhs = P::from_underlier(rhs);
819		let block_len = 1 << log_block_len;
820		let (a, b) = lhs.unzip(rhs, log_block_len);
821		for i in (0..P::WIDTH / 2).step_by(block_len) {
822			for j in 0..block_len {
823				assert_eq!(
824					a.get(i + j),
825					lhs.get(2 * i + j),
826					"i: {}, j: {}, log_block_len: {}, P: {:?}",
827					i,
828					j,
829					log_block_len,
830					P::zero()
831				);
832				assert_eq!(
833					b.get(i + j),
834					lhs.get(2 * i + j + block_len),
835					"i: {}, j: {}, log_block_len: {}, P: {:?}",
836					i,
837					j,
838					log_block_len,
839					P::zero()
840				);
841			}
842		}
843
844		for i in (0..P::WIDTH / 2).step_by(block_len) {
845			for j in 0..block_len {
846				assert_eq!(
847					a.get(i + j + P::WIDTH / 2),
848					rhs.get(2 * i + j),
849					"i: {}, j: {}, log_block_len: {}, P: {:?}",
850					i,
851					j,
852					log_block_len,
853					P::zero()
854				);
855				assert_eq!(b.get(i + j + P::WIDTH / 2), rhs.get(2 * i + j + block_len));
856			}
857		}
858	}
859
860	pub fn check_transpose_all_heights<P: PackedField + WithUnderlier>(
861		lhs: P::Underlier,
862		rhs: P::Underlier,
863	) {
864		for log_block_len in 0..P::LOG_WIDTH {
865			check_unzip::<P>(lhs, rhs, log_block_len);
866		}
867	}
868}
869
870#[cfg(test)]
871mod tests {
872	use std::{iter::repeat_with, ops::Mul, slice};
873
874	use binius_utils::{DeserializeBytes, SerializationMode, SerializeBytes, bytes::BytesMut};
875	use proptest::prelude::*;
876	use rand::{SeedableRng, rngs::StdRng, thread_rng};
877	use test_utils::{check_interleave_all_heights, implements_transformation_factory};
878
879	use super::{
880		test_utils::{
881			define_invert_tests, define_mul_alpha_tests, define_multiply_tests,
882			define_square_tests, define_transformation_tests,
883		},
884		*,
885	};
886	use crate::{
887		Field, PackedField, PackedFieldIndexable,
888		arch::{
889			packed_aes_16::*, packed_aes_32::*, packed_aes_64::*, packed_aes_128::*,
890			packed_aes_256::*, packed_aes_512::*,
891		},
892		arithmetic_traits::MulAlpha,
893		linear_transformation::PackedTransformationFactory,
894		test_utils::check_transpose_all_heights,
895		underlier::{U2, U4},
896	};
897
898	fn test_add_packed<P: PackedField + From<u128>>(a_val: u128, b_val: u128) {
899		let a = P::from(a_val);
900		let b = P::from(b_val);
901		let c = a + b;
902		for i in 0..P::WIDTH {
903			assert_eq!(c.get(i), a.get(i) + b.get(i));
904		}
905	}
906
907	fn test_mul_packed<P: PackedField>(a: P, b: P) {
908		let c = a * b;
909		for i in 0..P::WIDTH {
910			assert_eq!(c.get(i), a.get(i) * b.get(i));
911		}
912	}
913
914	fn test_mul_packed_random<P: PackedField>(mut rng: impl Rng) {
915		test_mul_packed(P::random(&mut rng), P::random(&mut rng))
916	}
917
918	fn test_set_then_get<P: PackedField>() {
919		let mut rng = StdRng::seed_from_u64(0);
920		let mut elem = P::random(&mut rng);
921
922		let scalars = repeat_with(|| Field::random(&mut rng))
923			.take(P::WIDTH)
924			.collect::<Vec<P::Scalar>>();
925
926		for (i, val) in scalars.iter().enumerate() {
927			elem.set(i, *val);
928		}
929		for (i, val) in scalars.iter().enumerate() {
930			assert_eq!(elem.get(i), *val);
931		}
932	}
933
934	fn test_elements_order<P: PackedFieldIndexable>() {
935		let mut rng = StdRng::seed_from_u64(0);
936		let packed = P::random(&mut rng);
937		let scalars = P::unpack_scalars(slice::from_ref(&packed));
938		for (i, val) in scalars.iter().enumerate() {
939			assert_eq!(packed.get(i), *val, "index: {i}");
940		}
941	}
942
943	fn test_serialize_then_deserialize<P: PackedField + DeserializeBytes + SerializeBytes>() {
944		let mode = SerializationMode::Native;
945		let mut buffer = BytesMut::new();
946		let mut rng = StdRng::seed_from_u64(0);
947		let packed = P::random(&mut rng);
948		packed.serialize(&mut buffer, mode).unwrap();
949
950		let mut read_buffer = buffer.freeze();
951
952		assert_eq!(P::deserialize(&mut read_buffer, mode).unwrap(), packed);
953	}
954
955	#[test]
956	fn test_set_then_get_4b() {
957		test_set_then_get::<PackedBinaryField32x4b>();
958		test_set_then_get::<PackedBinaryField64x4b>();
959		test_set_then_get::<PackedBinaryField128x4b>();
960	}
961
962	#[test]
963	fn test_serialize_then_deserialize_4b() {
964		test_serialize_then_deserialize::<PackedBinaryField32x4b>();
965		test_serialize_then_deserialize::<PackedBinaryField64x4b>();
966		test_serialize_then_deserialize::<PackedBinaryField128x4b>();
967		test_serialize_then_deserialize::<PackedBinaryField8x4b>();
968	}
969
970	#[test]
971	fn test_set_then_get_32b() {
972		test_set_then_get::<PackedBinaryField4x32b>();
973		test_set_then_get::<PackedBinaryField8x32b>();
974		test_set_then_get::<PackedBinaryField16x32b>();
975	}
976
977	#[test]
978	fn test_elements_order_32b() {
979		test_elements_order::<PackedBinaryField4x32b>();
980		test_elements_order::<PackedBinaryField8x32b>();
981		test_elements_order::<PackedBinaryField16x32b>();
982	}
983
984	#[test]
985	fn test_serialize_then_deserialize_32b() {
986		test_serialize_then_deserialize::<PackedBinaryField4x32b>();
987		test_serialize_then_deserialize::<PackedBinaryField8x32b>();
988		test_serialize_then_deserialize::<PackedBinaryField16x32b>();
989	}
990
991	#[test]
992	fn test_set_then_get_64b() {
993		test_set_then_get::<PackedBinaryField2x64b>();
994		test_set_then_get::<PackedBinaryField4x64b>();
995		test_set_then_get::<PackedBinaryField8x64b>();
996	}
997
998	#[test]
999	fn test_elements_order_64b() {
1000		test_elements_order::<PackedBinaryField2x64b>();
1001		test_elements_order::<PackedBinaryField4x64b>();
1002		test_elements_order::<PackedBinaryField8x64b>();
1003	}
1004
1005	#[test]
1006	fn test_serialize_then_deserialize_64b() {
1007		test_serialize_then_deserialize::<PackedBinaryField2x64b>();
1008		test_serialize_then_deserialize::<PackedBinaryField4x64b>();
1009		test_serialize_then_deserialize::<PackedBinaryField8x64b>();
1010	}
1011
1012	#[test]
1013	fn test_set_then_get_128b() {
1014		test_set_then_get::<PackedBinaryField1x128b>();
1015		test_set_then_get::<PackedBinaryField2x128b>();
1016		test_set_then_get::<PackedBinaryField4x128b>();
1017	}
1018
1019	#[test]
1020	fn test_elements_order_128b() {
1021		test_elements_order::<PackedBinaryField1x128b>();
1022		test_elements_order::<PackedBinaryField2x128b>();
1023		test_elements_order::<PackedBinaryField4x128b>();
1024	}
1025
1026	#[test]
1027	fn test_serialize_then_deserialize_128b() {
1028		test_serialize_then_deserialize::<PackedBinaryField1x128b>();
1029		test_serialize_then_deserialize::<PackedBinaryField2x128b>();
1030		test_serialize_then_deserialize::<PackedBinaryField4x128b>();
1031	}
1032
1033	#[test]
1034	fn test_serialize_deserialize_different_packing_width() {
1035		let mode = SerializationMode::Native;
1036		let mut rng = StdRng::seed_from_u64(0);
1037
1038		let packed0 = PackedBinaryField1x128b::random(&mut rng);
1039		let packed1 = PackedBinaryField1x128b::random(&mut rng);
1040
1041		let mut buffer = BytesMut::new();
1042		packed0.serialize(&mut buffer, mode).unwrap();
1043		packed1.serialize(&mut buffer, mode).unwrap();
1044
1045		let mut read_buffer = buffer.freeze();
1046		let packed01 = PackedBinaryField2x128b::deserialize(&mut read_buffer, mode).unwrap();
1047
1048		assert!(
1049			packed01
1050				.iter()
1051				.zip([packed0, packed1])
1052				.all(|(x, y)| x == y.get(0))
1053		);
1054	}
1055
1056	// TODO: Generate lots more proptests using macros
1057	proptest! {
1058		#[test]
1059		fn test_add_packed_128x1b(a_val in any::<u128>(), b_val in any::<u128>()) {
1060			test_add_packed::<PackedBinaryField128x1b>(a_val, b_val)
1061		}
1062
1063		#[test]
1064		fn test_add_packed_16x8b(a_val in any::<u128>(), b_val in any::<u128>()) {
1065			test_add_packed::<PackedBinaryField16x8b>(a_val, b_val)
1066		}
1067
1068		#[test]
1069		fn test_add_packed_8x16b(a_val in any::<u128>(), b_val in any::<u128>()) {
1070			test_add_packed::<PackedBinaryField8x16b>(a_val, b_val)
1071		}
1072
1073		#[test]
1074		fn test_add_packed_4x32b(a_val in any::<u128>(), b_val in any::<u128>()) {
1075			test_add_packed::<PackedBinaryField4x32b>(a_val, b_val)
1076		}
1077
1078		#[test]
1079		fn test_add_packed_2x64b(a_val in any::<u128>(), b_val in any::<u128>()) {
1080			test_add_packed::<PackedBinaryField2x64b>(a_val, b_val)
1081		}
1082
1083		#[test]
1084		fn test_add_packed_1x128b(a_val in any::<u128>(), b_val in any::<u128>()) {
1085			test_add_packed::<PackedBinaryField1x128b>(a_val, b_val)
1086		}
1087	}
1088
1089	#[test]
1090	fn test_mul_packed_256x1b() {
1091		test_mul_packed_random::<PackedBinaryField256x1b>(thread_rng())
1092	}
1093
1094	#[test]
1095	fn test_mul_packed_32x8b() {
1096		test_mul_packed_random::<PackedBinaryField32x8b>(thread_rng())
1097	}
1098
1099	#[test]
1100	fn test_mul_packed_16x16b() {
1101		test_mul_packed_random::<PackedBinaryField16x16b>(thread_rng())
1102	}
1103
1104	#[test]
1105	fn test_mul_packed_8x32b() {
1106		test_mul_packed_random::<PackedBinaryField8x32b>(thread_rng())
1107	}
1108
1109	#[test]
1110	fn test_mul_packed_4x64b() {
1111		test_mul_packed_random::<PackedBinaryField4x64b>(thread_rng())
1112	}
1113
1114	#[test]
1115	fn test_mul_packed_2x128b() {
1116		test_mul_packed_random::<PackedBinaryField2x128b>(thread_rng())
1117	}
1118
1119	#[test]
1120	fn test_iter_size_hint() {
1121		assert_valid_iterator_with_exact_size_hint::<crate::BinaryField128b>();
1122		assert_valid_iterator_with_exact_size_hint::<crate::BinaryField32b>();
1123		assert_valid_iterator_with_exact_size_hint::<crate::BinaryField1b>();
1124		assert_valid_iterator_with_exact_size_hint::<PackedBinaryField128x1b>();
1125		assert_valid_iterator_with_exact_size_hint::<PackedBinaryField64x2b>();
1126		assert_valid_iterator_with_exact_size_hint::<PackedBinaryField32x4b>();
1127		assert_valid_iterator_with_exact_size_hint::<PackedBinaryField16x16b>();
1128		assert_valid_iterator_with_exact_size_hint::<PackedBinaryField8x32b>();
1129		assert_valid_iterator_with_exact_size_hint::<PackedBinaryField4x64b>();
1130	}
1131
1132	fn assert_valid_iterator_with_exact_size_hint<P: PackedField>() {
1133		assert_eq!(P::default().iter().size_hint(), (P::WIDTH, Some(P::WIDTH)));
1134		assert_eq!(P::default().into_iter().size_hint(), (P::WIDTH, Some(P::WIDTH)));
1135		assert_eq!(P::default().iter().count(), P::WIDTH);
1136		assert_eq!(P::default().into_iter().count(), P::WIDTH);
1137	}
1138
1139	define_multiply_tests!(Mul::mul, PackedField);
1140
1141	define_square_tests!(PackedField::square, PackedField);
1142
1143	define_invert_tests!(PackedField::invert_or_zero, PackedField);
1144
1145	define_mul_alpha_tests!(MulAlpha::mul_alpha, MulAlpha);
1146
1147	#[allow(unused)]
1148	trait SelfTransformationFactory: PackedTransformationFactory<Self> {}
1149
1150	impl<T: PackedTransformationFactory<T>> SelfTransformationFactory for T {}
1151
1152	define_transformation_tests!(SelfTransformationFactory);
1153
1154	/// Compile-time test to ensure packed fields implement `PackedTransformationFactory`.
1155	#[allow(unused)]
1156	const fn test_implement_transformation_factory() {
1157		// 1 bit packed binary tower
1158		implements_transformation_factory::<PackedBinaryField1x1b, PackedBinaryField1x1b>();
1159
1160		// 2 bit packed binary tower
1161		implements_transformation_factory::<PackedBinaryField2x1b, PackedBinaryField2x1b>();
1162		implements_transformation_factory::<PackedBinaryField1x2b, PackedBinaryField1x2b>();
1163
1164		// 4 bit packed binary tower
1165		implements_transformation_factory::<PackedBinaryField4x1b, PackedBinaryField4x1b>();
1166		implements_transformation_factory::<PackedBinaryField2x2b, PackedBinaryField2x2b>();
1167		implements_transformation_factory::<PackedBinaryField1x4b, PackedBinaryField1x4b>();
1168
1169		// 8 bit packed binary tower
1170		implements_transformation_factory::<PackedBinaryField8x1b, PackedBinaryField8x1b>();
1171		implements_transformation_factory::<PackedBinaryField4x2b, PackedBinaryField4x2b>();
1172		implements_transformation_factory::<PackedBinaryField2x4b, PackedBinaryField2x4b>();
1173		implements_transformation_factory::<PackedBinaryField1x8b, PackedBinaryField1x8b>();
1174
1175		// 16 bit packed binary tower
1176		implements_transformation_factory::<PackedBinaryField16x1b, PackedBinaryField16x1b>();
1177		implements_transformation_factory::<PackedBinaryField8x2b, PackedBinaryField8x2b>();
1178		implements_transformation_factory::<PackedBinaryField4x4b, PackedBinaryField4x4b>();
1179		implements_transformation_factory::<PackedBinaryField2x8b, PackedBinaryField2x8b>();
1180		implements_transformation_factory::<PackedAESBinaryField2x8b, PackedBinaryField2x8b>();
1181		implements_transformation_factory::<PackedBinaryField1x16b, PackedBinaryField1x16b>();
1182		implements_transformation_factory::<PackedAESBinaryField1x16b, PackedBinaryField1x16b>();
1183
1184		// 32 bit packed binary tower
1185		implements_transformation_factory::<PackedBinaryField32x1b, PackedBinaryField32x1b>();
1186		implements_transformation_factory::<PackedBinaryField16x2b, PackedBinaryField16x2b>();
1187		implements_transformation_factory::<PackedBinaryField8x4b, PackedBinaryField8x4b>();
1188		implements_transformation_factory::<PackedBinaryField4x8b, PackedBinaryField4x8b>();
1189		implements_transformation_factory::<PackedAESBinaryField4x8b, PackedBinaryField4x8b>();
1190		implements_transformation_factory::<PackedBinaryField2x16b, PackedBinaryField2x16b>();
1191		implements_transformation_factory::<PackedAESBinaryField2x16b, PackedBinaryField2x16b>();
1192		implements_transformation_factory::<PackedBinaryField1x32b, PackedBinaryField1x32b>();
1193		implements_transformation_factory::<PackedAESBinaryField1x32b, PackedBinaryField1x32b>();
1194
1195		// 64 bit packed binary tower
1196		implements_transformation_factory::<PackedBinaryField64x1b, PackedBinaryField64x1b>();
1197		implements_transformation_factory::<PackedBinaryField32x2b, PackedBinaryField32x2b>();
1198		implements_transformation_factory::<PackedBinaryField16x4b, PackedBinaryField16x4b>();
1199		implements_transformation_factory::<PackedBinaryField8x8b, PackedBinaryField8x8b>();
1200		implements_transformation_factory::<PackedAESBinaryField8x8b, PackedBinaryField8x8b>();
1201		implements_transformation_factory::<PackedBinaryField4x16b, PackedBinaryField4x16b>();
1202		implements_transformation_factory::<PackedAESBinaryField4x16b, PackedBinaryField4x16b>();
1203		implements_transformation_factory::<PackedBinaryField2x32b, PackedBinaryField2x32b>();
1204		implements_transformation_factory::<PackedAESBinaryField2x32b, PackedBinaryField2x32b>();
1205		implements_transformation_factory::<PackedBinaryField1x64b, PackedBinaryField1x64b>();
1206		implements_transformation_factory::<PackedAESBinaryField1x64b, PackedBinaryField1x64b>();
1207
1208		// 128 bit packed binary tower
1209		implements_transformation_factory::<PackedBinaryField128x1b, PackedBinaryField128x1b>();
1210		implements_transformation_factory::<PackedBinaryField64x2b, PackedBinaryField64x2b>();
1211		implements_transformation_factory::<PackedBinaryField32x4b, PackedBinaryField32x4b>();
1212		implements_transformation_factory::<PackedBinaryField16x8b, PackedBinaryField16x8b>();
1213		implements_transformation_factory::<PackedAESBinaryField16x8b, PackedBinaryField16x8b>();
1214		implements_transformation_factory::<PackedBinaryField8x16b, PackedBinaryField8x16b>();
1215		implements_transformation_factory::<PackedAESBinaryField8x16b, PackedBinaryField8x16b>();
1216		implements_transformation_factory::<PackedBinaryField4x32b, PackedBinaryField4x32b>();
1217		implements_transformation_factory::<PackedAESBinaryField4x32b, PackedBinaryField4x32b>();
1218		implements_transformation_factory::<PackedBinaryField2x64b, PackedBinaryField2x64b>();
1219		implements_transformation_factory::<PackedAESBinaryField2x64b, PackedBinaryField2x64b>();
1220		implements_transformation_factory::<PackedBinaryField1x128b, PackedBinaryField1x128b>();
1221		implements_transformation_factory::<PackedAESBinaryField1x128b, PackedBinaryField1x128b>();
1222
1223		// 256 bit packed binary tower
1224		implements_transformation_factory::<PackedBinaryField256x1b, PackedBinaryField256x1b>();
1225		implements_transformation_factory::<PackedBinaryField128x2b, PackedBinaryField128x2b>();
1226		implements_transformation_factory::<PackedBinaryField64x4b, PackedBinaryField64x4b>();
1227		implements_transformation_factory::<PackedBinaryField32x8b, PackedBinaryField32x8b>();
1228		implements_transformation_factory::<PackedAESBinaryField32x8b, PackedBinaryField32x8b>();
1229		implements_transformation_factory::<PackedBinaryField16x16b, PackedBinaryField16x16b>();
1230		implements_transformation_factory::<PackedAESBinaryField16x16b, PackedBinaryField16x16b>();
1231		implements_transformation_factory::<PackedBinaryField8x32b, PackedBinaryField8x32b>();
1232		implements_transformation_factory::<PackedAESBinaryField8x32b, PackedBinaryField8x32b>();
1233		implements_transformation_factory::<PackedBinaryField4x64b, PackedBinaryField4x64b>();
1234		implements_transformation_factory::<PackedAESBinaryField4x64b, PackedBinaryField4x64b>();
1235		implements_transformation_factory::<PackedBinaryField2x128b, PackedBinaryField2x128b>();
1236		implements_transformation_factory::<PackedAESBinaryField2x128b, PackedBinaryField2x128b>();
1237
1238		// 512 bit packed binary tower
1239		implements_transformation_factory::<PackedBinaryField512x1b, PackedBinaryField512x1b>();
1240		implements_transformation_factory::<PackedBinaryField256x2b, PackedBinaryField256x2b>();
1241		implements_transformation_factory::<PackedBinaryField128x4b, PackedBinaryField128x4b>();
1242		implements_transformation_factory::<PackedBinaryField64x8b, PackedBinaryField64x8b>();
1243		implements_transformation_factory::<PackedAESBinaryField64x8b, PackedBinaryField64x8b>();
1244		implements_transformation_factory::<PackedBinaryField32x16b, PackedBinaryField32x16b>();
1245		implements_transformation_factory::<PackedAESBinaryField32x16b, PackedBinaryField32x16b>();
1246		implements_transformation_factory::<PackedBinaryField16x32b, PackedBinaryField16x32b>();
1247		implements_transformation_factory::<PackedAESBinaryField16x32b, PackedBinaryField16x32b>();
1248		implements_transformation_factory::<PackedBinaryField8x64b, PackedBinaryField8x64b>();
1249		implements_transformation_factory::<PackedAESBinaryField8x64b, PackedBinaryField8x64b>();
1250		implements_transformation_factory::<PackedBinaryField4x128b, PackedBinaryField4x128b>();
1251		implements_transformation_factory::<PackedAESBinaryField4x128b, PackedBinaryField4x128b>();
1252	}
1253
1254	proptest! {
1255		#[test]
1256		fn test_interleave_2b(a_val in 0u8..3, b_val in 0u8..3) {
1257			check_interleave_all_heights::<PackedBinaryField2x1b>(U2::new(a_val), U2::new(b_val));
1258			check_interleave_all_heights::<PackedBinaryField1x2b>(U2::new(a_val), U2::new(b_val));
1259		}
1260
1261		#[test]
1262		fn test_interleave_4b(a_val in 0u8..16, b_val in 0u8..16) {
1263			check_interleave_all_heights::<PackedBinaryField4x1b>(U4::new(a_val), U4::new(b_val));
1264			check_interleave_all_heights::<PackedBinaryField2x2b>(U4::new(a_val), U4::new(b_val));
1265			check_interleave_all_heights::<PackedBinaryField1x4b>(U4::new(a_val), U4::new(b_val));
1266		}
1267
1268		#[test]
1269		fn test_interleave_8b(a_val in 0u8.., b_val in 0u8..) {
1270			check_interleave_all_heights::<PackedBinaryField8x1b>(a_val, b_val);
1271			check_interleave_all_heights::<PackedBinaryField4x2b>(a_val, b_val);
1272			check_interleave_all_heights::<PackedBinaryField2x4b>(a_val, b_val);
1273			check_interleave_all_heights::<PackedBinaryField1x8b>(a_val, b_val);
1274		}
1275
1276		#[test]
1277		fn test_interleave_16b(a_val in 0u16.., b_val in 0u16..) {
1278			check_interleave_all_heights::<PackedBinaryField16x1b>(a_val, b_val);
1279			check_interleave_all_heights::<PackedBinaryField8x2b>(a_val, b_val);
1280			check_interleave_all_heights::<PackedBinaryField4x4b>(a_val, b_val);
1281			check_interleave_all_heights::<PackedBinaryField2x8b>(a_val, b_val);
1282			check_interleave_all_heights::<PackedBinaryField1x16b>(a_val, b_val);
1283		}
1284
1285		#[test]
1286		fn test_interleave_32b(a_val in 0u32.., b_val in 0u32..) {
1287			check_interleave_all_heights::<PackedBinaryField32x1b>(a_val, b_val);
1288			check_interleave_all_heights::<PackedBinaryField16x2b>(a_val, b_val);
1289			check_interleave_all_heights::<PackedBinaryField8x4b>(a_val, b_val);
1290			check_interleave_all_heights::<PackedBinaryField4x8b>(a_val, b_val);
1291			check_interleave_all_heights::<PackedBinaryField2x16b>(a_val, b_val);
1292			check_interleave_all_heights::<PackedBinaryField1x32b>(a_val, b_val);
1293		}
1294
1295		#[test]
1296		fn test_interleave_64b(a_val in 0u64.., b_val in 0u64..) {
1297			check_interleave_all_heights::<PackedBinaryField64x1b>(a_val, b_val);
1298			check_interleave_all_heights::<PackedBinaryField32x2b>(a_val, b_val);
1299			check_interleave_all_heights::<PackedBinaryField16x4b>(a_val, b_val);
1300			check_interleave_all_heights::<PackedBinaryField8x8b>(a_val, b_val);
1301			check_interleave_all_heights::<PackedBinaryField4x16b>(a_val, b_val);
1302			check_interleave_all_heights::<PackedBinaryField2x32b>(a_val, b_val);
1303			check_interleave_all_heights::<PackedBinaryField1x64b>(a_val, b_val);
1304		}
1305
1306		#[test]
1307		#[allow(clippy::useless_conversion)] // this warning depends on the target platform
1308		fn test_interleave_128b(a_val in 0u128.., b_val in 0u128..) {
1309			check_interleave_all_heights::<PackedBinaryField128x1b>(a_val.into(), b_val.into());
1310			check_interleave_all_heights::<PackedBinaryField64x2b>(a_val.into(), b_val.into());
1311			check_interleave_all_heights::<PackedBinaryField32x4b>(a_val.into(), b_val.into());
1312			check_interleave_all_heights::<PackedBinaryField16x8b>(a_val.into(), b_val.into());
1313			check_interleave_all_heights::<PackedBinaryField8x16b>(a_val.into(), b_val.into());
1314			check_interleave_all_heights::<PackedBinaryField4x32b>(a_val.into(), b_val.into());
1315			check_interleave_all_heights::<PackedBinaryField2x64b>(a_val.into(), b_val.into());
1316			check_interleave_all_heights::<PackedBinaryField1x128b>(a_val.into(), b_val.into());
1317		}
1318
1319		#[test]
1320		fn test_interleave_256b(a_val in any::<[u128; 2]>(), b_val in any::<[u128; 2]>()) {
1321			check_interleave_all_heights::<PackedBinaryField256x1b>(a_val.into(), b_val.into());
1322			check_interleave_all_heights::<PackedBinaryField128x2b>(a_val.into(), b_val.into());
1323			check_interleave_all_heights::<PackedBinaryField64x4b>(a_val.into(), b_val.into());
1324			check_interleave_all_heights::<PackedBinaryField32x8b>(a_val.into(), b_val.into());
1325			check_interleave_all_heights::<PackedBinaryField16x16b>(a_val.into(), b_val.into());
1326			check_interleave_all_heights::<PackedBinaryField8x32b>(a_val.into(), b_val.into());
1327			check_interleave_all_heights::<PackedBinaryField4x64b>(a_val.into(), b_val.into());
1328			check_interleave_all_heights::<PackedBinaryField2x128b>(a_val.into(), b_val.into());
1329		}
1330
1331		#[test]
1332		fn test_interleave_512b(a_val in any::<[u128; 4]>(), b_val in any::<[u128; 4]>()) {
1333			check_interleave_all_heights::<PackedBinaryField512x1b>(a_val.into(), b_val.into());
1334			check_interleave_all_heights::<PackedBinaryField256x2b>(a_val.into(), b_val.into());
1335			check_interleave_all_heights::<PackedBinaryField128x4b>(a_val.into(), b_val.into());
1336			check_interleave_all_heights::<PackedBinaryField64x8b>(a_val.into(), b_val.into());
1337			check_interleave_all_heights::<PackedBinaryField32x16b>(a_val.into(), b_val.into());
1338			check_interleave_all_heights::<PackedBinaryField16x32b>(a_val.into(), b_val.into());
1339			check_interleave_all_heights::<PackedBinaryField8x64b>(a_val.into(), b_val.into());
1340			check_interleave_all_heights::<PackedBinaryField4x128b>(a_val.into(), b_val.into());
1341		}
1342
1343		#[test]
1344		fn check_transpose_2b(a_val in 0u8..3, b_val in 0u8..3) {
1345			check_transpose_all_heights::<PackedBinaryField2x1b>(U2::new(a_val), U2::new(b_val));
1346			check_transpose_all_heights::<PackedBinaryField1x2b>(U2::new(a_val), U2::new(b_val));
1347		}
1348
1349		#[test]
1350		fn check_transpose_4b(a_val in 0u8..16, b_val in 0u8..16) {
1351			check_transpose_all_heights::<PackedBinaryField4x1b>(U4::new(a_val), U4::new(b_val));
1352			check_transpose_all_heights::<PackedBinaryField2x2b>(U4::new(a_val), U4::new(b_val));
1353			check_transpose_all_heights::<PackedBinaryField1x4b>(U4::new(a_val), U4::new(b_val));
1354		}
1355
1356		#[test]
1357		fn check_transpose_8b(a_val in 0u8.., b_val in 0u8..) {
1358			check_transpose_all_heights::<PackedBinaryField8x1b>(a_val, b_val);
1359			check_transpose_all_heights::<PackedBinaryField4x2b>(a_val, b_val);
1360			check_transpose_all_heights::<PackedBinaryField2x4b>(a_val, b_val);
1361			check_transpose_all_heights::<PackedBinaryField1x8b>(a_val, b_val);
1362		}
1363
1364		#[test]
1365		fn check_transpose_16b(a_val in 0u16.., b_val in 0u16..) {
1366			check_transpose_all_heights::<PackedBinaryField16x1b>(a_val, b_val);
1367			check_transpose_all_heights::<PackedBinaryField8x2b>(a_val, b_val);
1368			check_transpose_all_heights::<PackedBinaryField4x4b>(a_val, b_val);
1369			check_transpose_all_heights::<PackedBinaryField2x8b>(a_val, b_val);
1370			check_transpose_all_heights::<PackedBinaryField1x16b>(a_val, b_val);
1371		}
1372
1373		#[test]
1374		fn check_transpose_32b(a_val in 0u32.., b_val in 0u32..) {
1375			check_transpose_all_heights::<PackedBinaryField32x1b>(a_val, b_val);
1376			check_transpose_all_heights::<PackedBinaryField16x2b>(a_val, b_val);
1377			check_transpose_all_heights::<PackedBinaryField8x4b>(a_val, b_val);
1378			check_transpose_all_heights::<PackedBinaryField4x8b>(a_val, b_val);
1379			check_transpose_all_heights::<PackedBinaryField2x16b>(a_val, b_val);
1380			check_transpose_all_heights::<PackedBinaryField1x32b>(a_val, b_val);
1381		}
1382
1383		#[test]
1384		fn check_transpose_64b(a_val in 0u64.., b_val in 0u64..) {
1385			check_transpose_all_heights::<PackedBinaryField64x1b>(a_val, b_val);
1386			check_transpose_all_heights::<PackedBinaryField32x2b>(a_val, b_val);
1387			check_transpose_all_heights::<PackedBinaryField16x4b>(a_val, b_val);
1388			check_transpose_all_heights::<PackedBinaryField8x8b>(a_val, b_val);
1389			check_transpose_all_heights::<PackedBinaryField4x16b>(a_val, b_val);
1390			check_transpose_all_heights::<PackedBinaryField2x32b>(a_val, b_val);
1391			check_transpose_all_heights::<PackedBinaryField1x64b>(a_val, b_val);
1392		}
1393
1394		#[test]
1395		#[allow(clippy::useless_conversion)] // this warning depends on the target platform
1396		fn check_transpose_128b(a_val in 0u128.., b_val in 0u128..) {
1397			check_transpose_all_heights::<PackedBinaryField128x1b>(a_val.into(), b_val.into());
1398			check_transpose_all_heights::<PackedBinaryField64x2b>(a_val.into(), b_val.into());
1399			check_transpose_all_heights::<PackedBinaryField32x4b>(a_val.into(), b_val.into());
1400			check_transpose_all_heights::<PackedBinaryField16x8b>(a_val.into(), b_val.into());
1401			check_transpose_all_heights::<PackedBinaryField8x16b>(a_val.into(), b_val.into());
1402			check_transpose_all_heights::<PackedBinaryField4x32b>(a_val.into(), b_val.into());
1403			check_transpose_all_heights::<PackedBinaryField2x64b>(a_val.into(), b_val.into());
1404			check_transpose_all_heights::<PackedBinaryField1x128b>(a_val.into(), b_val.into());
1405		}
1406
1407		#[test]
1408		fn check_transpose_256b(a_val in any::<[u128; 2]>(), b_val in any::<[u128; 2]>()) {
1409			check_transpose_all_heights::<PackedBinaryField256x1b>(a_val.into(), b_val.into());
1410			check_transpose_all_heights::<PackedBinaryField128x2b>(a_val.into(), b_val.into());
1411			check_transpose_all_heights::<PackedBinaryField64x4b>(a_val.into(), b_val.into());
1412			check_transpose_all_heights::<PackedBinaryField32x8b>(a_val.into(), b_val.into());
1413			check_transpose_all_heights::<PackedBinaryField16x16b>(a_val.into(), b_val.into());
1414			check_transpose_all_heights::<PackedBinaryField8x32b>(a_val.into(), b_val.into());
1415			check_transpose_all_heights::<PackedBinaryField4x64b>(a_val.into(), b_val.into());
1416			check_transpose_all_heights::<PackedBinaryField2x128b>(a_val.into(), b_val.into());
1417		}
1418
1419		#[test]
1420		fn check_transpose_512b(a_val in any::<[u128; 4]>(), b_val in any::<[u128; 4]>()) {
1421			check_transpose_all_heights::<PackedBinaryField512x1b>(a_val.into(), b_val.into());
1422			check_transpose_all_heights::<PackedBinaryField256x2b>(a_val.into(), b_val.into());
1423			check_transpose_all_heights::<PackedBinaryField128x4b>(a_val.into(), b_val.into());
1424			check_transpose_all_heights::<PackedBinaryField64x8b>(a_val.into(), b_val.into());
1425			check_transpose_all_heights::<PackedBinaryField32x16b>(a_val.into(), b_val.into());
1426			check_transpose_all_heights::<PackedBinaryField16x32b>(a_val.into(), b_val.into());
1427			check_transpose_all_heights::<PackedBinaryField8x64b>(a_val.into(), b_val.into());
1428			check_transpose_all_heights::<PackedBinaryField4x128b>(a_val.into(), b_val.into());
1429		}
1430	}
1431}