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