binius_field/
binary_field.rs

1// Copyright 2023-2025 Irreducible Inc.
2
3use std::{
4	any::TypeId,
5	fmt::{Debug, Display, Formatter},
6	iter::{Product, Sum},
7	ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
8};
9
10use binius_utils::{
11	bytes::{Buf, BufMut},
12	DeserializeBytes, SerializationError, SerializationMode, SerializeBytes,
13};
14use bytemuck::{Pod, Zeroable};
15use rand::RngCore;
16use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
17
18use super::{
19	binary_field_arithmetic::TowerFieldArithmetic, error::Error, extension::ExtensionField,
20};
21use crate::{
22	underlier::{U1, U2, U4},
23	Field,
24};
25
26/// A finite field with characteristic 2.
27pub trait BinaryField: ExtensionField<BinaryField1b> {
28	const N_BITS: usize = Self::DEGREE;
29	const MULTIPLICATIVE_GENERATOR: Self;
30}
31
32/// A binary field *isomorphic* to a binary tower field.
33///
34/// The canonical binary field tower construction is specified in [DP23], section 2.3. This is a
35/// family of binary fields with extension degree $2^{\iota}$ for any tower height $\iota$. This
36/// trait can be implemented on any binary field *isomorphic* to the canonical tower field.
37///
38/// [DP23]: https://eprint.iacr.org/2023/1784
39pub trait TowerField: BinaryField + From<Self::Canonical>
40where
41	Self::Canonical: From<Self>,
42{
43	/// The level $\iota$ in the tower, where this field is isomorphic to $T_{\iota}$.
44	const TOWER_LEVEL: usize = Self::N_BITS.ilog2() as usize;
45
46	/// The canonical field isomorphic to this tower field.
47	/// Currently for every tower field, the canonical field is Fan-Paar's binary field of the same degree.
48	type Canonical: TowerField + SerializeBytes + DeserializeBytes;
49
50	/// Returns the smallest valid `TOWER_LEVEL` in the tower that can fit the same value.
51	///
52	/// Since which `TOWER_LEVEL` values are valid depends on the tower,
53	/// `F::Canonical::from(elem).min_tower_level()` can return a different result
54	/// from `elem.min_tower_level()`.
55	fn min_tower_level(self) -> usize;
56
57	/// Returns the i'th basis element of this field as an extension over the tower subfield with
58	/// level $\iota$.
59	fn basis(iota: usize, i: usize) -> Result<Self, Error> {
60		if iota > Self::TOWER_LEVEL {
61			return Err(Error::ExtensionDegreeTooHigh);
62		}
63		let n_basis_elts = 1 << (Self::TOWER_LEVEL - iota);
64		if i >= n_basis_elts {
65			return Err(Error::IndexOutOfRange {
66				index: i,
67				max: n_basis_elts,
68			});
69		}
70		<Self as ExtensionField<BinaryField1b>>::basis_checked(i << iota)
71	}
72
73	/// Multiplies a field element by the canonical primitive element of the extension $T_{\iota + 1} / T_{iota}$.
74	///
75	/// We represent the tower field $T_{\iota + 1}$ as a vector space over $T_{\iota}$ with the basis $\{1, \beta^{(\iota)}_1\}$.
76	/// This operation multiplies the element by $\beta^{(\iota)}_1$.
77	///
78	/// ## Throws
79	///
80	/// * `Error::ExtensionDegreeTooHigh` if `iota >= Self::TOWER_LEVEL`
81	fn mul_primitive(self, iota: usize) -> Result<Self, Error> {
82		Ok(self * <Self as ExtensionField<BinaryField1b>>::basis_checked(1 << iota)?)
83	}
84}
85
86/// Returns the i'th basis element of `FExt` as a field extension of `FSub`.
87///
88/// This is an alias function for [`ExtensionField::basis`].
89///
90/// ## Pre-conditions
91///
92/// * `i` must be in the range $[0, d)$, where $d$ is the field extension degree.
93#[inline]
94pub fn ext_basis<FExt, FSub>(i: usize) -> FExt
95where
96	FSub: Field,
97	FExt: ExtensionField<FSub>,
98{
99	<FExt as ExtensionField<FSub>>::basis(i)
100}
101
102pub(super) trait TowerExtensionField:
103	TowerField
104	+ ExtensionField<Self::DirectSubfield>
105	+ From<(Self::DirectSubfield, Self::DirectSubfield)>
106	+ Into<(Self::DirectSubfield, Self::DirectSubfield)>
107{
108	type DirectSubfield: TowerField;
109}
110
111/// Macro to generate an implementation of a BinaryField.
112macro_rules! binary_field {
113	($vis:vis $name:ident($typ:ty), $gen:expr) => {
114		#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Zeroable, bytemuck::TransparentWrapper)]
115		#[repr(transparent)]
116		$vis struct $name(pub(crate) $typ);
117
118		impl $name {
119			pub const fn new(value: $typ) -> Self {
120				Self(value)
121			}
122
123			pub const fn val(self) -> $typ {
124				self.0
125			}
126		}
127
128		unsafe impl $crate::underlier::WithUnderlier for $name {
129			type Underlier = $typ;
130
131			fn to_underlier(self) -> Self::Underlier {
132				::bytemuck::TransparentWrapper::peel(self)
133			}
134
135			fn to_underlier_ref(&self) -> &Self::Underlier {
136				::bytemuck::TransparentWrapper::peel_ref(self)
137			}
138
139			fn to_underlier_ref_mut(&mut self) -> &mut Self::Underlier {
140				::bytemuck::TransparentWrapper::peel_mut(self)
141			}
142
143			fn to_underliers_ref(val: &[Self]) -> &[Self::Underlier] {
144				::bytemuck::TransparentWrapper::peel_slice(val)
145			}
146
147			fn to_underliers_ref_mut(val: &mut [Self]) -> &mut [Self::Underlier] {
148				::bytemuck::TransparentWrapper::peel_slice_mut(val)
149			}
150
151			fn from_underlier(val: Self::Underlier) -> Self {
152				::bytemuck::TransparentWrapper::wrap(val)
153			}
154
155			fn from_underlier_ref(val: &Self::Underlier) -> &Self {
156				::bytemuck::TransparentWrapper::wrap_ref(val)
157			}
158
159			fn from_underlier_ref_mut(val: &mut Self::Underlier) -> &mut Self {
160				::bytemuck::TransparentWrapper::wrap_mut(val)
161			}
162
163			fn from_underliers_ref(val: &[Self::Underlier]) -> &[Self] {
164				::bytemuck::TransparentWrapper::wrap_slice(val)
165			}
166
167			fn from_underliers_ref_mut(val: &mut [Self::Underlier]) -> &mut [Self] {
168				::bytemuck::TransparentWrapper::wrap_slice_mut(val)
169			}
170		}
171
172		impl Neg for $name {
173			type Output = Self;
174
175			fn neg(self) -> Self::Output {
176				self
177			}
178		}
179
180		impl Add<Self> for $name {
181			type Output = Self;
182
183			#[allow(clippy::suspicious_arithmetic_impl)]
184			fn add(self, rhs: Self) -> Self::Output {
185				$name(self.0 ^ rhs.0)
186			}
187		}
188
189		impl Add<&Self> for $name {
190			type Output = Self;
191
192			#[allow(clippy::suspicious_arithmetic_impl)]
193			fn add(self, rhs: &Self) -> Self::Output {
194				$name(self.0 ^ rhs.0)
195			}
196		}
197
198		impl Sub<Self> for $name {
199			type Output = Self;
200
201			#[allow(clippy::suspicious_arithmetic_impl)]
202			fn sub(self, rhs: Self) -> Self::Output {
203				$name(self.0 ^ rhs.0)
204			}
205		}
206
207		impl Sub<&Self> for $name {
208			type Output = Self;
209
210			#[allow(clippy::suspicious_arithmetic_impl)]
211			fn sub(self, rhs: &Self) -> Self::Output {
212				$name(self.0 ^ rhs.0)
213			}
214		}
215
216		impl Mul<Self> for $name {
217			type Output = Self;
218
219			fn mul(self, rhs: Self) -> Self::Output {
220				$crate::tracing::trace_multiplication!($name);
221
222				TowerFieldArithmetic::multiply(self, rhs)
223			}
224		}
225
226		impl Mul<&Self> for $name {
227			type Output = Self;
228
229			fn mul(self, rhs: &Self) -> Self::Output {
230				self * *rhs
231			}
232		}
233
234		impl AddAssign<Self> for $name {
235			fn add_assign(&mut self, rhs: Self) {
236				*self = *self + rhs;
237			}
238		}
239
240		impl AddAssign<&Self> for $name {
241			fn add_assign(&mut self, rhs: &Self) {
242				*self = *self + *rhs;
243			}
244		}
245
246		impl SubAssign<Self> for $name {
247			fn sub_assign(&mut self, rhs: Self) {
248				*self = *self - rhs;
249			}
250		}
251
252		impl SubAssign<&Self> for $name {
253			fn sub_assign(&mut self, rhs: &Self) {
254				*self = *self - *rhs;
255			}
256		}
257
258		impl MulAssign<Self> for $name {
259			fn mul_assign(&mut self, rhs: Self) {
260				*self = *self * rhs;
261			}
262		}
263
264		impl MulAssign<&Self> for $name {
265			fn mul_assign(&mut self, rhs: &Self) {
266				*self = *self * rhs;
267			}
268		}
269
270		impl Sum<Self> for $name {
271			fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
272				iter.fold(Self::ZERO, |acc, x| acc + x)
273			}
274		}
275
276		impl<'a> Sum<&'a Self> for $name {
277			fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
278				iter.fold(Self::ZERO, |acc, x| acc + x)
279			}
280		}
281
282		impl Product<Self> for $name {
283			fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
284				iter.fold(Self::ONE, |acc, x| acc * x)
285			}
286		}
287
288		impl<'a> Product<&'a Self> for $name {
289			fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
290				iter.fold(Self::ONE, |acc, x| acc * x)
291			}
292		}
293
294		impl ConstantTimeEq for $name {
295			fn ct_eq(&self, other: &Self) -> Choice {
296				self.0.ct_eq(&other.0)
297			}
298		}
299
300		impl ConditionallySelectable for $name {
301			fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
302				Self(ConditionallySelectable::conditional_select(&a.0, &b.0, choice))
303			}
304		}
305
306		impl crate::arithmetic_traits::Square for $name {
307			fn square(self) -> Self {
308				TowerFieldArithmetic::square(self)
309			}
310		}
311
312		impl Field for $name {
313			const ZERO: Self = $name::new(<$typ as $crate::underlier::UnderlierWithBitOps>::ZERO);
314			const ONE: Self = $name::new(<$typ as $crate::underlier::UnderlierWithBitOps>::ONE);
315			const CHARACTERISTIC: usize = 2;
316
317			fn random(mut rng: impl RngCore) -> Self {
318				Self(<$typ as $crate::underlier::Random>::random(&mut rng))
319			}
320
321			fn double(&self) -> Self {
322				Self::ZERO
323			}
324		}
325
326		impl Display for $name {
327			fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
328				write!(f, "0x{repr:0>width$x}", repr=self.val(), width=Self::N_BITS.max(4) / 4)
329			}
330		}
331
332		impl Debug for $name {
333			fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
334				let structure_name = std::any::type_name::<$name>().split("::").last().expect("exist");
335
336				write!(f, "{}({})",structure_name, self)
337			}
338		}
339
340		impl BinaryField for $name {
341			const MULTIPLICATIVE_GENERATOR: $name = $name($gen);
342		}
343
344		impl From<$typ> for $name {
345			fn from(val: $typ) -> Self {
346				return Self(val)
347			}
348		}
349
350		impl From<$name> for $typ {
351			fn from(val: $name) -> Self {
352				return val.0
353			}
354		}
355	}
356}
357
358pub(crate) use binary_field;
359
360macro_rules! binary_subfield_mul_packed_128b {
361	($subfield_name:ident, $field_name:ident, $subfield_packed:ident) => {
362		cfg_if::cfg_if! {
363			// HACK: Carve-out for accelerated packed field arithmetic. This is temporary until the
364			// portable packed128b implementation is refactored to not rely on BinaryField mul.
365			if #[cfg(all(target_arch = "x86_64", target_feature = "gfni", target_feature = "sse2"))] {
366				impl Mul<$subfield_name> for $field_name {
367					type Output = Self;
368
369					fn mul(self, rhs: $subfield_name) -> Self::Output {
370						use bytemuck::must_cast;
371						use crate::$subfield_packed;
372
373						let a = must_cast::<_, $subfield_packed>(self);
374						must_cast(a * rhs)
375					}
376				}
377			} else {
378				impl Mul<$subfield_name> for $field_name {
379					type Output = Self;
380
381					fn mul(self, rhs: $subfield_name) -> Self::Output {
382						$crate::tracing::trace_multiplication!($field_name, $subfield_name);
383
384						let (a, b) = self.into();
385						(a * rhs, b * rhs).into()
386					}
387				}
388			}
389		}
390	};
391}
392
393pub(crate) use binary_subfield_mul_packed_128b;
394
395macro_rules! mul_by_binary_field_1b {
396	($name:ident) => {
397		impl Mul<BinaryField1b> for $name {
398			type Output = Self;
399
400			#[inline]
401			#[allow(clippy::suspicious_arithmetic_impl)]
402			fn mul(self, rhs: BinaryField1b) -> Self::Output {
403				use $crate::underlier::{UnderlierWithBitOps, WithUnderlier};
404
405				$crate::tracing::trace_multiplication!(BinaryField128b, BinaryField1b);
406
407				Self(self.0 & <$name as WithUnderlier>::Underlier::fill_with_bit(u8::from(rhs.0)))
408			}
409		}
410	};
411}
412
413pub(crate) use mul_by_binary_field_1b;
414
415macro_rules! binary_tower_subfield_mul {
416	// HACK: Special case when the subfield is GF(2)
417	(BinaryField1b, $name:ident) => {
418		mul_by_binary_field_1b!($name);
419	};
420	// HACK: Special case when the field is GF(2^128)
421	(BinaryField8b, BinaryField128b) => {
422		$crate::binary_field::binary_subfield_mul_packed_128b!(
423			BinaryField8b,
424			BinaryField128b,
425			PackedBinaryField16x8b
426		);
427	};
428	// HACK: Special case when the field is GF(2^128)
429	(BinaryField16b, BinaryField128b) => {
430		$crate::binary_field::binary_subfield_mul_packed_128b!(
431			BinaryField16b,
432			BinaryField128b,
433			PackedBinaryField8x16b
434		);
435	};
436	// HACK: Special case when the field is GF(2^128)
437	(BinaryField32b, BinaryField128b) => {
438		$crate::binary_field::binary_subfield_mul_packed_128b!(
439			BinaryField32b,
440			BinaryField128b,
441			PackedBinaryField4x32b
442		);
443	};
444	// HACK: Special case when the field is GF(2^128)
445	(BinaryField64b, BinaryField128b) => {
446		$crate::binary_field::binary_subfield_mul_packed_128b!(
447			BinaryField64b,
448			BinaryField128b,
449			PackedBinaryField2x64b
450		);
451	};
452	// HACK: Special case when the field is GF(2^128)
453	(AESTowerField8b, AESTowerField128b) => {
454		$crate::binary_field::binary_subfield_mul_packed_128b!(
455			AESTowerField8b,
456			AESTowerField128b,
457			PackedAESBinaryField16x8b
458		);
459	};
460	// HACK: Special case when the field is GF(2^128)
461	(BinaryField16b, AESTowerField128b) => {
462		$crate::binary_field::binary_subfield_mul_packed_128b!(
463			AESTowerField16b,
464			AESTowerField128b,
465			PackedAESBinaryField8x16b
466		);
467	};
468	// HACK: Special case when the field is GF(2^128)
469	(BinaryField32b, AESTowerField128b) => {
470		$crate::binary_field::binary_subfield_mul_packed_128b!(
471			AESTowerField32b,
472			AESTowerField128b,
473			PackedAESBinaryField4x32b
474		);
475	};
476	// HACK: Special case when the field is GF(2^128)
477	(BinaryField64b, AESTowerField128b) => {
478		$crate::binary_field::binary_subfield_mul_packed_128b!(
479			AESTowerField64b,
480			AESTowerField128b,
481			PackedAESBinaryField2x64b
482		);
483	};
484	($subfield_name:ident, $name:ident) => {
485		impl Mul<$subfield_name> for $name {
486			type Output = Self;
487
488			fn mul(self, rhs: $subfield_name) -> Self::Output {
489				$crate::tracing::trace_multiplication!($name, $subfield_name);
490
491				let (a, b) = self.into();
492				(a * rhs, b * rhs).into()
493			}
494		}
495	};
496}
497
498pub(crate) use binary_tower_subfield_mul;
499
500macro_rules! impl_field_extension {
501	($subfield_name:ident($subfield_typ:ty) < @$log_degree:expr => $name:ident($typ:ty)) => {
502		impl TryFrom<$name> for $subfield_name {
503			type Error = ();
504
505			#[inline]
506			fn try_from(elem: $name) -> Result<Self, Self::Error> {
507				use $crate::underlier::NumCast;
508
509				if elem.0 >> $subfield_name::N_BITS
510					== <$typ as $crate::underlier::UnderlierWithBitOps>::ZERO
511				{
512					Ok($subfield_name::new(<$subfield_typ>::num_cast_from(elem.val())))
513				} else {
514					Err(())
515				}
516			}
517		}
518
519		impl From<$subfield_name> for $name {
520			#[inline]
521			fn from(elem: $subfield_name) -> Self {
522				$name::new(<$typ>::from(elem.val()))
523			}
524		}
525
526		impl Add<$subfield_name> for $name {
527			type Output = Self;
528
529			#[inline]
530			fn add(self, rhs: $subfield_name) -> Self::Output {
531				self + Self::from(rhs)
532			}
533		}
534
535		impl Sub<$subfield_name> for $name {
536			type Output = Self;
537
538			#[inline]
539			fn sub(self, rhs: $subfield_name) -> Self::Output {
540				self - Self::from(rhs)
541			}
542		}
543
544		impl AddAssign<$subfield_name> for $name {
545			#[inline]
546			fn add_assign(&mut self, rhs: $subfield_name) {
547				*self = *self + rhs;
548			}
549		}
550
551		impl SubAssign<$subfield_name> for $name {
552			#[inline]
553			fn sub_assign(&mut self, rhs: $subfield_name) {
554				*self = *self - rhs;
555			}
556		}
557
558		impl MulAssign<$subfield_name> for $name {
559			#[inline]
560			fn mul_assign(&mut self, rhs: $subfield_name) {
561				*self = *self * rhs;
562			}
563		}
564
565		impl Add<$name> for $subfield_name {
566			type Output = $name;
567
568			#[inline]
569			fn add(self, rhs: $name) -> Self::Output {
570				rhs + self
571			}
572		}
573
574		impl Sub<$name> for $subfield_name {
575			type Output = $name;
576
577			#[allow(clippy::suspicious_arithmetic_impl)]
578			#[inline]
579			fn sub(self, rhs: $name) -> Self::Output {
580				rhs + self
581			}
582		}
583
584		impl Mul<$name> for $subfield_name {
585			type Output = $name;
586
587			#[inline]
588			fn mul(self, rhs: $name) -> Self::Output {
589				rhs * self
590			}
591		}
592
593		impl ExtensionField<$subfield_name> for $name {
594			const LOG_DEGREE: usize = $log_degree;
595
596			#[inline]
597			fn basis_checked(i: usize) -> Result<Self, Error> {
598				use $crate::underlier::UnderlierWithBitOps;
599
600				if i >= 1 << $log_degree {
601					return Err(Error::ExtensionDegreeMismatch);
602				}
603				Ok(Self::new(<$typ>::ONE << (i * $subfield_name::N_BITS)))
604			}
605
606			#[inline]
607			fn from_bases_sparse(
608				base_elems: impl IntoIterator<Item = $subfield_name>,
609				log_stride: usize,
610			) -> Result<Self, Error> {
611				use $crate::underlier::UnderlierWithBitOps;
612
613				debug_assert!($name::N_BITS.is_power_of_two());
614				let shift_step = ($subfield_name::N_BITS << log_stride) & ($name::N_BITS - 1);
615				let mut value = <$typ>::ZERO;
616				let mut shift = 0;
617
618				for elem in base_elems.into_iter() {
619					if shift >= $name::N_BITS {
620						return Err(Error::ExtensionDegreeMismatch);
621					}
622					value |= <$typ>::from(elem.val()) << shift;
623					shift += shift_step;
624				}
625
626				Ok(Self::new(value))
627			}
628
629			#[inline]
630			fn iter_bases(&self) -> impl Iterator<Item = $subfield_name> {
631				use $crate::underlier::{WithUnderlier, IterationMethods, IterationStrategy};
632				use binius_utils::iter::IterExtensions;
633
634				IterationMethods::<<$subfield_name as WithUnderlier>::Underlier, Self::Underlier>::ref_iter(&self.0)
635					.map_skippable($subfield_name::from)
636			}
637
638			#[inline]
639			fn into_iter_bases(self) -> impl Iterator<Item = $subfield_name> {
640				use $crate::underlier::{WithUnderlier, IterationMethods, IterationStrategy};
641				use binius_utils::iter::IterExtensions;
642
643				IterationMethods::<<$subfield_name as WithUnderlier>::Underlier, Self::Underlier>::value_iter(self.0)
644					.map_skippable($subfield_name::from)
645			}
646
647			#[inline]
648			unsafe fn get_base_unchecked(&self, i: usize) -> $subfield_name {
649				use $crate::underlier::{WithUnderlier, UnderlierWithBitOps};
650
651				$subfield_name::from_underlier(self.to_underlier().get_subvalue(i))
652			}
653		}
654	};
655}
656
657pub(crate) use impl_field_extension;
658
659/// Internal trait to implement multiply by primitive
660/// for the specific tower,
661pub(super) trait MulPrimitive: Sized {
662	fn mul_primitive(self, iota: usize) -> Result<Self, Error>;
663}
664
665#[macro_export]
666macro_rules! binary_tower {
667	(BinaryField1b($subfield_typ:ty $(, $canonical_subfield:ident)?) < $name:ident($typ:ty $(, $canonical:ident)?) $(< $extfield_name:ident($extfield_typ:ty $(, $canonical_ext:ident)?))+) => {
668		binary_tower!([BinaryField1b::TOWER_LEVEL]; BinaryField1b($subfield_typ $(, $canonical_subfield)?) < $name($typ $(, $canonical)?) $(< $extfield_name($extfield_typ $(, $canonical_ext)?))+);
669	};
670	($subfield_name:ident($subfield_typ:ty $(, $canonical_subfield:ident)?) < $name:ident($typ:ty $(, $canonical:ident)?) $(< $extfield_name:ident($extfield_typ:ty $(, $canonical_ext:ident)?))+) => {
671		binary_tower!([BinaryField1b::TOWER_LEVEL, $subfield_name::TOWER_LEVEL]; $subfield_name($subfield_typ $(, $canonical_subfield)?) < $name($typ $(, $canonical)?) $(< $extfield_name($extfield_typ $(, $canonical_ext)?))+);
672	};
673	([$($valid_tower_levels:tt)*]; $subfield_name:ident($subfield_typ:ty $(, $canonical_subfield:ident)?) < $name:ident($typ:ty)) => {
674		binary_tower!([$($valid_tower_levels)*]; $subfield_name($subfield_typ $(, $canonical_subfield)?) < $name($typ, $name));
675	};
676	([$($valid_tower_levels:tt)*]; $subfield_name:ident($subfield_typ:ty $(, $canonical_subfield:ident)?) < $name:ident($typ:ty, $canonical:ident)) => {
677		impl From<$name> for ($subfield_name, $subfield_name) {
678			#[inline]
679			fn from(src: $name) -> ($subfield_name, $subfield_name) {
680				use $crate::underlier::NumCast;
681
682				let lo = <$subfield_typ>::num_cast_from(src.0);
683				let hi = <$subfield_typ>::num_cast_from(src.0 >> $subfield_name::N_BITS);
684				($subfield_name::new(lo), $subfield_name::new(hi))
685			}
686		}
687
688		impl From<($subfield_name, $subfield_name)> for $name {
689			#[inline]
690			fn from((a, b): ($subfield_name, $subfield_name)) -> Self {
691				$name(<$typ>::from(a.val()) | (<$typ>::from(b.val()) << $subfield_name::N_BITS))
692			}
693		}
694
695		impl TowerField for $name {
696			const TOWER_LEVEL: usize = { $subfield_name::TOWER_LEVEL + 1 };
697
698			type Canonical = $canonical;
699
700			fn min_tower_level(self) -> usize {
701				let zero = <$typ as $crate::underlier::UnderlierWithBitOps>::ZERO;
702				for level in [$($valid_tower_levels)*] {
703					if self.0 >> (1 << level) == zero {
704						return level;
705					}
706				}
707				Self::TOWER_LEVEL
708			}
709
710			fn mul_primitive(self, iota: usize) -> Result<Self, Error> {
711				<Self as $crate::binary_field::MulPrimitive>::mul_primitive(self, iota)
712			}
713		}
714
715		impl $crate::TowerExtensionField for $name {
716			type DirectSubfield = $subfield_name;
717		}
718
719		binary_tower!($subfield_name($subfield_typ) < @1 => $name($typ));
720	};
721	([$($valid_tower_levels:tt)*]; $subfield_name:ident($subfield_typ:ty $(, $canonical_subfield:ident)?) < $name:ident($typ:ty $(, $canonical:ident)?) $(< $extfield_name:ident($extfield_typ:ty $(, $canonical_ext:ident)?))+) => {
722		binary_tower!([$($valid_tower_levels)*]; $subfield_name($subfield_typ $(, $canonical_subfield)?) < $name($typ $(, $canonical)?));
723		binary_tower!([$($valid_tower_levels)*, $name::TOWER_LEVEL]; $name($typ $(, $canonical)?) $(< $extfield_name($extfield_typ $(, $canonical_ext)?))+);
724		binary_tower!($subfield_name($subfield_typ) < @2 => $($extfield_name($extfield_typ))<+);
725	};
726	($subfield_name:ident($subfield_typ:ty) < @$log_degree:expr => $name:ident($typ:ty)) => {
727		$crate::binary_field::impl_field_extension!($subfield_name($subfield_typ) < @$log_degree => $name($typ));
728		$crate::binary_field::binary_tower_subfield_mul!($subfield_name, $name);
729	};
730	($subfield_name:ident($subfield_typ:ty) < @$log_degree:expr => $name:ident($typ:ty) $(< $extfield_name:ident($extfield_typ:ty))+) => {
731		binary_tower!($subfield_name($subfield_typ) < @$log_degree => $name($typ));
732		binary_tower!($subfield_name($subfield_typ) < @$log_degree+1 => $($extfield_name($extfield_typ))<+);
733	};
734}
735
736binary_field!(pub BinaryField1b(U1), U1::new(0x1));
737binary_field!(pub BinaryField2b(U2), U2::new(0x2));
738binary_field!(pub BinaryField4b(U4), U4::new(0x5));
739binary_field!(pub BinaryField8b(u8), 0x2D);
740binary_field!(pub BinaryField16b(u16), 0xE2DE);
741binary_field!(pub BinaryField32b(u32), 0x03E21CEA);
742binary_field!(pub BinaryField64b(u64), 0x070F870DCD9C1D88);
743binary_field!(pub BinaryField128b(u128), 0x2E895399AF449ACE499596F6E5FCCAFAu128);
744
745unsafe impl Pod for BinaryField8b {}
746unsafe impl Pod for BinaryField16b {}
747unsafe impl Pod for BinaryField32b {}
748unsafe impl Pod for BinaryField64b {}
749unsafe impl Pod for BinaryField128b {}
750
751binary_tower!(
752	BinaryField1b(U1)
753	< BinaryField2b(U2)
754	< BinaryField4b(U4)
755	< BinaryField8b(u8)
756	< BinaryField16b(u16)
757	< BinaryField32b(u32)
758	< BinaryField64b(u64)
759	< BinaryField128b(u128)
760);
761
762#[inline(always)]
763pub fn is_canonical_tower<F: TowerField>() -> bool {
764	TypeId::of::<F::Canonical>() == TypeId::of::<F>()
765}
766
767macro_rules! serialize_deserialize {
768	($bin_type:ty) => {
769		impl SerializeBytes for $bin_type {
770			fn serialize(
771				&self,
772				write_buf: impl BufMut,
773				mode: SerializationMode,
774			) -> Result<(), SerializationError> {
775				self.0.serialize(write_buf, mode)
776			}
777		}
778
779		impl DeserializeBytes for $bin_type {
780			fn deserialize(
781				read_buf: impl Buf,
782				mode: SerializationMode,
783			) -> Result<Self, SerializationError> {
784				Ok(Self(DeserializeBytes::deserialize(read_buf, mode)?))
785			}
786		}
787	};
788}
789
790serialize_deserialize!(BinaryField1b);
791serialize_deserialize!(BinaryField2b);
792serialize_deserialize!(BinaryField4b);
793serialize_deserialize!(BinaryField8b);
794serialize_deserialize!(BinaryField16b);
795serialize_deserialize!(BinaryField32b);
796serialize_deserialize!(BinaryField64b);
797serialize_deserialize!(BinaryField128b);
798
799impl From<BinaryField1b> for Choice {
800	fn from(val: BinaryField1b) -> Self {
801		Self::from(val.val().val())
802	}
803}
804
805impl BinaryField1b {
806	/// Creates value without checking that it is within valid range (0 or 1)
807	///
808	/// # Safety
809	/// Value should not exceed 1
810	#[inline]
811	pub unsafe fn new_unchecked(val: u8) -> Self {
812		debug_assert!(val < 2);
813
814		Self::new(U1::new_unchecked(val))
815	}
816}
817
818impl From<u8> for BinaryField1b {
819	#[inline]
820	fn from(val: u8) -> Self {
821		Self::new(U1::new(val))
822	}
823}
824
825impl From<BinaryField1b> for u8 {
826	#[inline]
827	fn from(value: BinaryField1b) -> Self {
828		value.val().into()
829	}
830}
831
832impl From<bool> for BinaryField1b {
833	#[inline]
834	fn from(value: bool) -> Self {
835		Self::from(U1::new_unchecked(value.into()))
836	}
837}
838
839impl BinaryField2b {
840	/// Creates value without checking that it is within valid range (0 to 3)
841	///
842	/// # Safety
843	/// Value should not exceed 3
844	#[inline]
845	pub unsafe fn new_unchecked(val: u8) -> Self {
846		debug_assert!(val < 4);
847
848		Self::new(U2::new_unchecked(val))
849	}
850}
851
852impl From<u8> for BinaryField2b {
853	#[inline]
854	fn from(val: u8) -> Self {
855		Self::new(U2::new(val))
856	}
857}
858
859impl From<BinaryField2b> for u8 {
860	#[inline]
861	fn from(value: BinaryField2b) -> Self {
862		value.val().into()
863	}
864}
865
866impl BinaryField4b {
867	/// Creates value without checking that it is within valid range (0 to 15)
868	///
869	/// # Safety
870	/// Value should not exceed 15
871	#[inline]
872	pub unsafe fn new_unchecked(val: u8) -> Self {
873		debug_assert!(val < 16);
874
875		Self::new(U4::new_unchecked(val))
876	}
877}
878
879impl From<u8> for BinaryField4b {
880	#[inline]
881	fn from(val: u8) -> Self {
882		Self::new(U4::new(val))
883	}
884}
885
886impl From<BinaryField4b> for u8 {
887	#[inline]
888	fn from(value: BinaryField4b) -> Self {
889		value.val().into()
890	}
891}
892
893#[cfg(test)]
894pub(crate) mod tests {
895	use binius_utils::{bytes::BytesMut, SerializationMode};
896	use proptest::prelude::*;
897
898	use super::{
899		BinaryField16b as BF16, BinaryField1b as BF1, BinaryField2b as BF2, BinaryField4b as BF4,
900		BinaryField64b as BF64, BinaryField8b as BF8, *,
901	};
902
903	#[test]
904	fn test_gf2_add() {
905		assert_eq!(BF1::from(0) + BF1::from(0), BF1::from(0));
906		assert_eq!(BF1::from(0) + BF1::from(1), BF1::from(1));
907		assert_eq!(BF1::from(1) + BF1::from(0), BF1::from(1));
908		assert_eq!(BF1::from(1) + BF1::from(1), BF1::from(0));
909	}
910
911	#[test]
912	fn test_gf2_sub() {
913		assert_eq!(BF1::from(0) - BF1::from(0), BF1::from(0));
914		assert_eq!(BF1::from(0) - BF1::from(1), BF1::from(1));
915		assert_eq!(BF1::from(1) - BF1::from(0), BF1::from(1));
916		assert_eq!(BF1::from(1) - BF1::from(1), BF1::from(0));
917	}
918
919	#[test]
920	fn test_gf2_mul() {
921		assert_eq!(BF1::from(0) * BF1::from(0), BF1::from(0));
922		assert_eq!(BF1::from(0) * BF1::from(1), BF1::from(0));
923		assert_eq!(BF1::from(1) * BF1::from(0), BF1::from(0));
924		assert_eq!(BF1::from(1) * BF1::from(1), BF1::from(1));
925	}
926
927	#[test]
928	fn test_bin2b_mul() {
929		assert_eq!(BF2::from(0x1) * BF2::from(0x0), BF2::from(0x0));
930		assert_eq!(BF2::from(0x1) * BF2::from(0x1), BF2::from(0x1));
931		assert_eq!(BF2::from(0x0) * BF2::from(0x3), BF2::from(0x0));
932		assert_eq!(BF2::from(0x1) * BF2::from(0x2), BF2::from(0x2));
933		assert_eq!(BF2::from(0x0) * BF2::from(0x1), BF2::from(0x0));
934		assert_eq!(BF2::from(0x0) * BF2::from(0x2), BF2::from(0x0));
935		assert_eq!(BF2::from(0x1) * BF2::from(0x3), BF2::from(0x3));
936		assert_eq!(BF2::from(0x3) * BF2::from(0x0), BF2::from(0x0));
937		assert_eq!(BF2::from(0x2) * BF2::from(0x0), BF2::from(0x0));
938		assert_eq!(BF2::from(0x2) * BF2::from(0x2), BF2::from(0x3));
939	}
940
941	#[test]
942	fn test_bin4b_mul() {
943		assert_eq!(BF4::from(0x0) * BF4::from(0x0), BF4::from(0x0));
944		assert_eq!(BF4::from(0x9) * BF4::from(0x0), BF4::from(0x0));
945		assert_eq!(BF4::from(0x9) * BF4::from(0x4), BF4::from(0xa));
946		assert_eq!(BF4::from(0x6) * BF4::from(0x0), BF4::from(0x0));
947		assert_eq!(BF4::from(0x6) * BF4::from(0x7), BF4::from(0xc));
948		assert_eq!(BF4::from(0x2) * BF4::from(0x0), BF4::from(0x0));
949		assert_eq!(BF4::from(0x2) * BF4::from(0xa), BF4::from(0xf));
950		assert_eq!(BF4::from(0x1) * BF4::from(0x0), BF4::from(0x0));
951		assert_eq!(BF4::from(0x1) * BF4::from(0x8), BF4::from(0x8));
952		assert_eq!(BF4::from(0x9) * BF4::from(0xb), BF4::from(0x8));
953	}
954
955	#[test]
956	fn test_bin8b_mul() {
957		assert_eq!(BF8::new(0x00) * BF8::new(0x00), BF8::new(0x00));
958		assert_eq!(BF8::new(0x1b) * BF8::new(0xa8), BF8::new(0x09));
959		assert_eq!(BF8::new(0x00) * BF8::new(0x00), BF8::new(0x00));
960		assert_eq!(BF8::new(0x76) * BF8::new(0x51), BF8::new(0x84));
961		assert_eq!(BF8::new(0x00) * BF8::new(0x00), BF8::new(0x00));
962		assert_eq!(BF8::new(0xe4) * BF8::new(0x8f), BF8::new(0x0e));
963		assert_eq!(BF8::new(0x00) * BF8::new(0x00), BF8::new(0x00));
964		assert_eq!(BF8::new(0x42) * BF8::new(0x66), BF8::new(0xea));
965		assert_eq!(BF8::new(0x00) * BF8::new(0x00), BF8::new(0x00));
966		assert_eq!(BF8::new(0x68) * BF8::new(0xd0), BF8::new(0xc5));
967	}
968
969	#[test]
970	fn test_bin16b_mul() {
971		assert_eq!(BF16::new(0x0000) * BF16::new(0x0000), BF16::new(0x0000));
972		assert_eq!(BF16::new(0x48a8) * BF16::new(0xf8a4), BF16::new(0x3656));
973		assert_eq!(BF16::new(0xf8a4) * BF16::new(0xf8a4), BF16::new(0xe7e6));
974		assert_eq!(BF16::new(0xf8a4) * BF16::new(0xf8a4), BF16::new(0xe7e6));
975		assert_eq!(BF16::new(0x448b) * BF16::new(0x0585), BF16::new(0x47d3));
976		assert_eq!(BF16::new(0x0585) * BF16::new(0x0585), BF16::new(0x8057));
977		assert_eq!(BF16::new(0x0001) * BF16::new(0x6a57), BF16::new(0x6a57));
978		assert_eq!(BF16::new(0x0001) * BF16::new(0x0001), BF16::new(0x0001));
979		assert_eq!(BF16::new(0xf62c) * BF16::new(0x0dbd), BF16::new(0xa9da));
980		assert_eq!(BF16::new(0xf62c) * BF16::new(0xf62c), BF16::new(0x37bb));
981	}
982
983	#[test]
984	fn test_bin64b_mul() {
985		assert_eq!(
986			BF64::new(0x0000000000000000) * BF64::new(0x0000000000000000),
987			BF64::new(0x0000000000000000)
988		);
989		assert_eq!(
990			BF64::new(0xc84d619110831cef) * BF64::new(0x000000000000a14f),
991			BF64::new(0x3565086d6b9ef595)
992		);
993		assert_eq!(
994			BF64::new(0xa14f580107030300) * BF64::new(0x000000000000f404),
995			BF64::new(0x83e7239eb819a6ac)
996		);
997		assert_eq!(
998			BF64::new(0xf404210706070403) * BF64::new(0x0000000000006b44),
999			BF64::new(0x790541c54ffa2ede)
1000		);
1001		assert_eq!(
1002			BF64::new(0x6b44000404006b44) * BF64::new(0x0000000000000013),
1003			BF64::new(0x7018004c4c007018)
1004		);
1005		assert_eq!(
1006			BF64::new(0x6b44000404006b44) * BF64::new(0x0000000000000013),
1007			BF64::new(0x7018004c4c007018)
1008		);
1009		assert_eq!(
1010			BF64::new(0x6b44000404006b44) * BF64::new(0x6b44000404006b44),
1011			BF64::new(0xc59751e6f1769000)
1012		);
1013		assert_eq!(
1014			BF64::new(0x6b44000404006b44) * BF64::new(0x6b44000404006b44),
1015			BF64::new(0xc59751e6f1769000)
1016		);
1017		assert_eq!(
1018			BF64::new(0x00000000000000eb) * BF64::new(0x000000000000fba1),
1019			BF64::new(0x0000000000007689)
1020		);
1021		assert_eq!(
1022			BF64::new(0x00000000000000eb) * BF64::new(0x000000000000fba1),
1023			BF64::new(0x0000000000007689)
1024		);
1025	}
1026
1027	pub(crate) fn is_binary_field_valid_generator<F: BinaryField>() -> bool {
1028		// Binary fields should contain a multiplicative subgroup of size 2^n - 1
1029		let mut order = if F::N_BITS == 128 {
1030			u128::MAX
1031		} else {
1032			(1 << F::N_BITS) - 1
1033		};
1034
1035		// Naive factorization of group order - represented as a multiset of prime factors
1036		let mut factorization = Vec::new();
1037
1038		let mut prime = 2;
1039		while prime * prime <= order {
1040			while order % prime == 0 {
1041				order /= prime;
1042				factorization.push(prime);
1043			}
1044
1045			prime += if prime > 2 { 2 } else { 1 };
1046		}
1047
1048		if order > 1 {
1049			factorization.push(order);
1050		}
1051
1052		// Iterate over all divisors (some may be tested several times if order is non-square-free)
1053		for mask in 0..(1 << factorization.len()) {
1054			let mut divisor = 1;
1055
1056			for (bit_index, &prime) in factorization.iter().enumerate() {
1057				if (1 << bit_index) & mask != 0 {
1058					divisor *= prime;
1059				}
1060			}
1061
1062			// Compute pow(generator, divisor) in log time
1063			divisor = divisor.reverse_bits();
1064
1065			let mut pow_divisor = F::ONE;
1066			while divisor > 0 {
1067				pow_divisor *= pow_divisor;
1068
1069				if divisor & 1 != 0 {
1070					pow_divisor *= F::MULTIPLICATIVE_GENERATOR;
1071				}
1072
1073				divisor >>= 1;
1074			}
1075
1076			// Generator invariant
1077			let is_root_of_unity = pow_divisor == F::ONE;
1078			let is_full_group = mask + 1 == 1 << factorization.len();
1079
1080			if is_root_of_unity && !is_full_group || !is_root_of_unity && is_full_group {
1081				return false;
1082			}
1083		}
1084
1085		true
1086	}
1087
1088	#[test]
1089	fn test_multiplicative_generators() {
1090		assert!(is_binary_field_valid_generator::<BF1>());
1091		assert!(is_binary_field_valid_generator::<BF2>());
1092		assert!(is_binary_field_valid_generator::<BF4>());
1093		assert!(is_binary_field_valid_generator::<BF8>());
1094		assert!(is_binary_field_valid_generator::<BF16>());
1095		assert!(is_binary_field_valid_generator::<BinaryField32b>());
1096		assert!(is_binary_field_valid_generator::<BF64>());
1097		assert!(is_binary_field_valid_generator::<BinaryField128b>());
1098	}
1099
1100	proptest! {
1101		#[test]
1102		fn test_add_sub_subfields_is_commutative(a_val in any::<u8>(), b_val in any::<u64>()) {
1103			let (a, b) = (BinaryField8b::new(a_val), BinaryField16b::new(b_val as u16));
1104			assert_eq!(a + b, b + a);
1105			assert_eq!(a - b, -(b - a));
1106
1107			let (a, b) = (BinaryField8b::new(a_val), BinaryField64b::new(b_val));
1108			assert_eq!(a + b, b + a);
1109			assert_eq!(a - b, -(b - a));
1110		}
1111
1112		#[test]
1113		fn test_mul_subfields_is_commutative(a_val in any::<u8>(), b_val in any::<u64>()) {
1114			let (a, b) = (BinaryField8b::new(a_val), BinaryField16b::new(b_val as u16));
1115			assert_eq!(a * b, b * a);
1116
1117			let (a, b) = (BinaryField8b::new(a_val), BinaryField64b::new(b_val));
1118			assert_eq!(a * b, b * a);
1119		}
1120
1121		#[test]
1122		fn test_square_equals_mul(a_val in any::<u64>()) {
1123			let a = BinaryField64b::new(a_val);
1124			assert_eq!(a.square(), a * a);
1125		}
1126	}
1127
1128	#[test]
1129	fn test_field_degrees() {
1130		assert_eq!(BinaryField1b::N_BITS, 1);
1131		assert_eq!(BinaryField2b::N_BITS, 2);
1132		assert_eq!(BinaryField4b::N_BITS, 4);
1133		assert_eq!(<BinaryField4b as ExtensionField<BinaryField2b>>::DEGREE, 2);
1134		assert_eq!(BinaryField8b::N_BITS, 8);
1135		assert_eq!(BinaryField128b::N_BITS, 128);
1136
1137		assert_eq!(<BinaryField8b as ExtensionField<BinaryField2b>>::DEGREE, 4);
1138		assert_eq!(<BinaryField128b as ExtensionField<BinaryField2b>>::DEGREE, 64);
1139		assert_eq!(<BinaryField128b as ExtensionField<BinaryField8b>>::DEGREE, 16);
1140	}
1141
1142	#[test]
1143	fn test_field_formatting() {
1144		assert_eq!(format!("{}", BinaryField4b::from(3)), "0x3");
1145		assert_eq!(format!("{}", BinaryField8b::from(3)), "0x03");
1146		assert_eq!(format!("{}", BinaryField32b::from(5)), "0x00000005");
1147		assert_eq!(format!("{}", BinaryField64b::from(5)), "0x0000000000000005");
1148	}
1149
1150	#[test]
1151	fn test_extension_from_bases() {
1152		let a = BinaryField8b(0x01);
1153		let b = BinaryField8b(0x02);
1154		let c = BinaryField8b(0x03);
1155		let d = BinaryField8b(0x04);
1156		assert_eq!(
1157			<BinaryField32b as ExtensionField<BinaryField8b>>::from_bases([]).unwrap(),
1158			BinaryField32b(0)
1159		);
1160		assert_eq!(BinaryField32b::from_bases([a]).unwrap(), BinaryField32b(0x00000001));
1161		assert_eq!(BinaryField32b::from_bases([a, b]).unwrap(), BinaryField32b(0x00000201));
1162		assert_eq!(BinaryField32b::from_bases([a, b, c]).unwrap(), BinaryField32b(0x00030201));
1163		assert_eq!(BinaryField32b::from_bases([a, b, c, d]).unwrap(), BinaryField32b(0x04030201));
1164		assert!(BinaryField32b::from_bases([a, b, c, d, d]).is_err());
1165	}
1166
1167	#[test]
1168	fn test_inverse_on_zero() {
1169		assert!(BinaryField1b::ZERO.invert().is_none());
1170		assert!(BinaryField2b::ZERO.invert().is_none());
1171		assert!(BinaryField4b::ZERO.invert().is_none());
1172		assert!(BinaryField8b::ZERO.invert().is_none());
1173		assert!(BinaryField16b::ZERO.invert().is_none());
1174		assert!(BinaryField32b::ZERO.invert().is_none());
1175		assert!(BinaryField64b::ZERO.invert().is_none());
1176		assert!(BinaryField128b::ZERO.invert().is_none());
1177	}
1178
1179	proptest! {
1180		#[test]
1181		fn test_inverse_8b(val in 1u8..) {
1182			let x = BinaryField8b(val);
1183			let x_inverse = x.invert().unwrap();
1184			assert_eq!(x * x_inverse, BinaryField8b::ONE);
1185		}
1186
1187		#[test]
1188		fn test_inverse_32b(val in 1u32..) {
1189			let x = BinaryField32b(val);
1190			let x_inverse = x.invert().unwrap();
1191			assert_eq!(x * x_inverse, BinaryField32b::ONE);
1192		}
1193
1194		#[test]
1195		fn test_inverse_128b(val in 1u128..) {
1196			let x = BinaryField128b(val);
1197			let x_inverse = x.invert().unwrap();
1198			assert_eq!(x * x_inverse, BinaryField128b::ONE);
1199		}
1200	}
1201
1202	fn test_mul_primitive<F: TowerField>(val: F, iota: usize) {
1203		let result = val.mul_primitive(iota);
1204		let expected =
1205			<F as ExtensionField<BinaryField1b>>::basis_checked(1 << iota).map(|b| val * b);
1206		assert_eq!(result.is_ok(), expected.is_ok());
1207		if result.is_ok() {
1208			assert_eq!(result.unwrap(), expected.unwrap());
1209		} else {
1210			assert!(matches!(result.unwrap_err(), Error::ExtensionDegreeMismatch));
1211		}
1212	}
1213
1214	proptest! {
1215		#[test]
1216		fn test_mul_primitive_1b(val in 0u8..2u8, iota in 0usize..8) {
1217			test_mul_primitive::<BinaryField1b>(val.into(), iota)
1218		}
1219
1220		#[test]
1221		fn test_mul_primitive_2b(val in 0u8..4u8, iota in 0usize..8) {
1222			test_mul_primitive::<BinaryField2b>(val.into(), iota)
1223		}
1224
1225		#[test]
1226		fn test_mul_primitive_4b(val in 0u8..16u8, iota in 0usize..8) {
1227			test_mul_primitive::<BinaryField4b>(val.into(), iota)
1228		}
1229
1230		#[test]
1231		fn test_mul_primitive_8b(val in 0u8.., iota in 0usize..8) {
1232			test_mul_primitive::<BinaryField8b>(val.into(), iota)
1233		}
1234
1235		#[test]
1236		fn test_mul_primitive_16b(val in 0u16.., iota in 0usize..8) {
1237			test_mul_primitive::<BinaryField16b>(val.into(), iota)
1238		}
1239
1240		#[test]
1241		fn test_mul_primitive_32b(val in 0u32.., iota in 0usize..8) {
1242			test_mul_primitive::<BinaryField32b>(val.into(), iota)
1243		}
1244
1245		#[test]
1246		fn test_mul_primitive_64b(val in 0u64.., iota in 0usize..8) {
1247			test_mul_primitive::<BinaryField64b>(val.into(), iota)
1248		}
1249
1250		#[test]
1251		fn test_mul_primitive_128b(val in 0u128.., iota in 0usize..8) {
1252			test_mul_primitive::<BinaryField128b>(val.into(), iota)
1253		}
1254	}
1255
1256	#[test]
1257	fn test_1b_to_choice() {
1258		for i in 0..2 {
1259			assert_eq!(Choice::from(BinaryField1b::from(i)).unwrap_u8(), i);
1260		}
1261	}
1262
1263	#[test]
1264	fn test_serialization() {
1265		let mode = SerializationMode::CanonicalTower;
1266		let mut buffer = BytesMut::new();
1267		let b1 = BinaryField1b::from(0x1);
1268		let b8 = BinaryField8b::new(0x12);
1269		let b2 = BinaryField2b::from(0x2);
1270		let b16 = BinaryField16b::new(0x3456);
1271		let b32 = BinaryField32b::new(0x789ABCDE);
1272		let b4 = BinaryField4b::from(0xa);
1273		let b64 = BinaryField64b::new(0x13579BDF02468ACE);
1274		let b128 = BinaryField128b::new(0x147AD0369CF258BE8899AABBCCDDEEFF);
1275
1276		b1.serialize(&mut buffer, mode).unwrap();
1277		b8.serialize(&mut buffer, mode).unwrap();
1278		b2.serialize(&mut buffer, mode).unwrap();
1279		b16.serialize(&mut buffer, mode).unwrap();
1280		b32.serialize(&mut buffer, mode).unwrap();
1281		b4.serialize(&mut buffer, mode).unwrap();
1282		b64.serialize(&mut buffer, mode).unwrap();
1283		b128.serialize(&mut buffer, mode).unwrap();
1284
1285		let mut read_buffer = buffer.freeze();
1286
1287		assert_eq!(BinaryField1b::deserialize(&mut read_buffer, mode).unwrap(), b1);
1288		assert_eq!(BinaryField8b::deserialize(&mut read_buffer, mode).unwrap(), b8);
1289		assert_eq!(BinaryField2b::deserialize(&mut read_buffer, mode).unwrap(), b2);
1290		assert_eq!(BinaryField16b::deserialize(&mut read_buffer, mode).unwrap(), b16);
1291		assert_eq!(BinaryField32b::deserialize(&mut read_buffer, mode).unwrap(), b32);
1292		assert_eq!(BinaryField4b::deserialize(&mut read_buffer, mode).unwrap(), b4);
1293		assert_eq!(BinaryField64b::deserialize(&mut read_buffer, mode).unwrap(), b64);
1294		assert_eq!(BinaryField128b::deserialize(&mut read_buffer, mode).unwrap(), b128);
1295	}
1296
1297	#[test]
1298	fn test_gf2_new_unchecked() {
1299		for i in 0..2 {
1300			assert_eq!(unsafe { BF1::new_unchecked(i) }, BF1::from(i));
1301		}
1302		// Assert a panic for higher values
1303		let result = std::panic::catch_unwind(|| unsafe { BF1::new_unchecked(2) });
1304		assert!(result.is_err(), "Expected a panic for value > 1, but no panic occurred");
1305	}
1306
1307	#[test]
1308	fn test_bin2b_new_unchecked() {
1309		for i in 0..4 {
1310			assert_eq!(unsafe { BF2::new_unchecked(i) }, BF2::from(i));
1311		}
1312		// Assert a panic for higher values
1313		let result = std::panic::catch_unwind(|| unsafe { BF2::new_unchecked(4) });
1314		assert!(result.is_err(), "Expected a panic for value > 3, but no panic occurred");
1315	}
1316
1317	#[test]
1318	fn test_bin4b_new_unchecked() {
1319		for i in 0..16 {
1320			assert_eq!(unsafe { BF4::new_unchecked(i) }, BF4::from(i));
1321		}
1322		// Assert a panic for higher values
1323		let result = std::panic::catch_unwind(|| unsafe { BF4::new_unchecked(16) });
1324		assert!(result.is_err(), "Expected a panic for value > 15, but no panic occurred");
1325	}
1326}