Skip to main content

binius_field/
binary_field.rs

1// Copyright 2023-2025 Irreducible Inc.
2// Copyright 2026 The Binius Developers
3
4use std::{
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, FixedSizeSerializeBytes, SerializationError, SerializeBytes,
12	bytes::{Buf, BufMut},
13};
14use bytemuck::Zeroable;
15
16use super::{UnderlierType, WithUnderlier, extension::ExtensionField};
17use crate::{Field, underlier::U1};
18
19/// A finite field with characteristic 2.
20pub trait BinaryField:
21	ExtensionField<BinaryField1b> + WithUnderlier<Underlier: UnderlierType>
22{
23	const N_BITS: usize = Self::ORDER_EXPONENT;
24}
25
26/// Generates a binary field type over an underlier `$typ`.
27///
28/// The default form derives the field's arithmetic from its width-one packing.
29/// The `custom_arithmetic` form omits that, for a field that defines its own arithmetic.
30macro_rules! binary_field {
31	// Default: the field's arithmetic is its width-one packing's arithmetic.
32	($vis:vis $name:ident($typ:ty), $gen:expr) => {
33		binary_field!(@base $vis $name($typ), $gen);
34		binary_field!(@arithmetic_via_packed $name, $typ);
35	};
36	// The field provides its own `Mul`/`Square`/`InvertOrZero`/`WideMul` separately.
37	(custom_arithmetic $vis:vis $name:ident($typ:ty), $gen:expr) => {
38		binary_field!(@base $vis $name($typ), $gen);
39	};
40
41	(@base $vis:vis $name:ident($typ:ty), $gen:expr) => {
42		#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Zeroable, bytemuck::TransparentWrapper)]
43		#[repr(transparent)]
44		$vis struct $name(pub(crate) $typ);
45
46		// NOTE: `new` is intentionally NOT generated here. Each field defines its own `new` so it
47		// can take an ergonomic constructor type independent of the underlier (e.g.
48		// `BinaryField128bGhash::new` takes `u128` even though its underlier is `M128`).
49		impl $name {
50			pub const fn val(self) -> $typ {
51				self.0
52			}
53		}
54
55		unsafe impl $crate::underlier::WithUnderlier for $name {
56			type Underlier = $typ;
57		}
58
59		impl Neg for $name {
60			type Output = Self;
61
62			fn neg(self) -> Self::Output {
63				self
64			}
65		}
66
67		impl Add<Self> for $name {
68			type Output = Self;
69
70			#[allow(clippy::suspicious_arithmetic_impl)]
71			fn add(self, rhs: Self) -> Self::Output {
72				$name(self.0 ^ rhs.0)
73			}
74		}
75
76		impl Add<&Self> for $name {
77			type Output = Self;
78
79			#[allow(clippy::suspicious_arithmetic_impl)]
80			fn add(self, rhs: &Self) -> Self::Output {
81				$name(self.0 ^ rhs.0)
82			}
83		}
84
85		impl Sub<Self> for $name {
86			type Output = Self;
87
88			#[allow(clippy::suspicious_arithmetic_impl)]
89			fn sub(self, rhs: Self) -> Self::Output {
90				$name(self.0 ^ rhs.0)
91			}
92		}
93
94		impl Sub<&Self> for $name {
95			type Output = Self;
96
97			#[allow(clippy::suspicious_arithmetic_impl)]
98			fn sub(self, rhs: &Self) -> Self::Output {
99				$name(self.0 ^ rhs.0)
100			}
101		}
102
103		impl Mul<&Self> for $name {
104			type Output = Self;
105
106			fn mul(self, rhs: &Self) -> Self::Output {
107				self * *rhs
108			}
109		}
110
111		impl AddAssign<Self> for $name {
112			fn add_assign(&mut self, rhs: Self) {
113				*self = *self + rhs;
114			}
115		}
116
117		impl AddAssign<&Self> for $name {
118			fn add_assign(&mut self, rhs: &Self) {
119				*self = *self + *rhs;
120			}
121		}
122
123		impl SubAssign<Self> for $name {
124			fn sub_assign(&mut self, rhs: Self) {
125				*self = *self - rhs;
126			}
127		}
128
129		impl SubAssign<&Self> for $name {
130			fn sub_assign(&mut self, rhs: &Self) {
131				*self = *self - *rhs;
132			}
133		}
134
135		impl MulAssign<Self> for $name {
136			fn mul_assign(&mut self, rhs: Self) {
137				*self = *self * rhs;
138			}
139		}
140
141		impl MulAssign<&Self> for $name {
142			fn mul_assign(&mut self, rhs: &Self) {
143				*self = *self * rhs;
144			}
145		}
146
147		impl Sum<Self> for $name {
148			fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
149				iter.fold(Self::ZERO, |acc, x| acc + x)
150			}
151		}
152
153		impl<'a> Sum<&'a Self> for $name {
154			fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
155				iter.fold(Self::ZERO, |acc, x| acc + x)
156			}
157		}
158
159		impl Product<Self> for $name {
160			fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
161				iter.fold(Self::ONE, |acc, x| acc * x)
162			}
163		}
164
165		impl<'a> Product<&'a Self> for $name {
166			fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
167				iter.fold(Self::ONE, |acc, x| acc * x)
168			}
169		}
170
171
172		impl Field for $name {
173			const ZERO: Self = $name(<$typ as $crate::underlier::UnderlierType>::ZERO);
174			const ONE: Self = $name(<$typ as $crate::underlier::UnderlierType>::ONE);
175			const CHARACTERISTIC: usize = 2;
176			const ORDER_EXPONENT: usize = <$typ as $crate::underlier::UnderlierType>::BITS;
177			const MULTIPLICATIVE_GENERATOR: $name = $name($gen);
178
179			fn double(&self) -> Self {
180				Self::ZERO
181			}
182		}
183
184		// A field element divides into exactly one element of itself. This makes the field a
185		// degenerate packed field of width one (see the `PackedField` impl below).
186		impl $crate::Divisible<$name> for $name {
187			const LOG_N: usize = 0;
188
189			#[inline]
190			fn value_iter(value: Self) -> impl ExactSizeIterator<Item = $name> + Send + Clone {
191				std::iter::once(value)
192			}
193
194			#[inline]
195			fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = $name> + Send + Clone + '_ {
196				std::iter::once(*value)
197			}
198
199			#[inline]
200			fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = $name> + Send + Clone + '_ {
201				slice.iter().copied()
202			}
203
204			#[inline]
205			unsafe fn get_unchecked(&self, _index: usize) -> $name {
206				*self
207			}
208
209			#[inline]
210			unsafe fn set_unchecked(&mut self, _index: usize, val: $name) {
211				*self = val;
212			}
213
214			#[inline]
215			fn broadcast(val: $name) -> Self {
216				val
217			}
218
219			#[inline]
220			fn from_iter(mut iter: impl Iterator<Item = $name>) -> Self {
221				iter.next().unwrap_or(Self::ZERO)
222			}
223		}
224
225		// As a width-one packed field, a field element is masked by its single selector: kept
226		// when selected, otherwise zeroed. Uses the same underlier bitmask strategy as
227		// PackedPrimitiveType so the mask type and AND operation are consistent.
228		impl $crate::Maskable<$name> for $name {
229			type Mask = $typ;
230
231			#[inline]
232			fn make_mask(mut selectors: impl Iterator<Item = bool>) -> $typ {
233				<$typ as $crate::underlier::UnderlierType>::fill_with_bit(
234					u8::from(selectors.next().unwrap_or(false)),
235				)
236			}
237
238			#[inline]
239			fn select(&self, mask: &$typ) -> Self {
240				Self(self.0 & *mask)
241			}
242		}
243
244		impl $crate::PackedField for $name {
245			#[inline]
246			fn iter(&self) -> impl Iterator<Item = Self::Scalar> + Send + Clone + '_ {
247				std::iter::once(*self)
248			}
249
250			#[inline]
251			fn into_iter(self) -> impl Iterator<Item = Self::Scalar> + Send + Clone {
252				std::iter::once(self)
253			}
254
255			#[inline]
256			fn iter_slice(slice: &[Self]) -> impl Iterator<Item = Self::Scalar> + Send + Clone + '_ {
257				slice.iter().copied()
258			}
259
260			fn interleave(self, _other: Self, _log_block_len: usize) -> (Self, Self) {
261				panic!("cannot interleave when WIDTH = 1");
262			}
263
264			fn unzip(self, _other: Self, _log_block_len: usize) -> (Self, Self) {
265				panic!("cannot transpose when WIDTH = 1");
266			}
267
268			#[inline]
269			fn from_fn(mut f: impl FnMut(usize) -> Self::Scalar) -> Self {
270				f(0)
271			}
272
273			#[inline]
274			unsafe fn spread_unchecked(self, _log_block_len: usize, _block_idx: usize) -> Self {
275				self
276			}
277		}
278
279		impl ::rand::distr::Distribution<$name> for ::rand::distr::StandardUniform {
280			fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> $name {
281				$name(::rand::distr::StandardUniform.sample(rng))
282			}
283		}
284
285		impl Display for $name {
286			fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
287				write!(f, "0x{repr:0>width$x}", repr=self.val(), width=Self::N_BITS.max(4) / 4)
288			}
289		}
290
291		impl Debug for $name {
292			fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
293				let structure_name = std::any::type_name::<$name>().split("::").last().expect("exist");
294
295				write!(f, "{}({})",structure_name, self)
296			}
297		}
298
299		impl BinaryField for $name {}
300
301		impl From<$typ> for $name {
302			fn from(val: $typ) -> Self {
303				return Self(val)
304			}
305		}
306
307		impl From<$name> for $typ {
308			fn from(val: $name) -> Self {
309				return val.0
310			}
311		}
312	};
313
314	// Each op lifts the underlier into the width-one packing, runs its arithmetic, and lowers back.
315	(@arithmetic_via_packed $name:ident, $typ:ty) => {
316		impl Mul<Self> for $name {
317			type Output = Self;
318
319			#[inline]
320			fn mul(self, rhs: Self) -> Self {
321				$crate::tracing::trace_multiplication!($name);
322				type P = $crate::arch::PackedPrimitiveType<$typ, $name>;
323				Self((P::from_underlier(self.0) * P::from_underlier(rhs.0)).to_underlier())
324			}
325		}
326
327		impl $crate::arithmetic_traits::Square for $name {
328			#[inline]
329			fn square(self) -> Self {
330				type P = $crate::arch::PackedPrimitiveType<$typ, $name>;
331				Self(
332					$crate::arithmetic_traits::Square::square(P::from_underlier(self.0)).to_underlier(),
333				)
334			}
335		}
336
337		impl $crate::arithmetic_traits::InvertOrZero for $name {
338			#[inline]
339			fn invert_or_zero(self) -> Self {
340				type P = $crate::arch::PackedPrimitiveType<$typ, $name>;
341				Self(
342					$crate::arithmetic_traits::InvertOrZero::invert_or_zero(P::from_underlier(self.0))
343						.to_underlier(),
344				)
345			}
346		}
347
348		impl $crate::arithmetic_traits::WideMul for $name {
349			type Output = <$crate::arch::PackedPrimitiveType<$typ, $name> as $crate::arithmetic_traits::WideMul>::Output;
350
351			#[inline]
352			fn wide_mul(a: Self, b: Self) -> Self::Output {
353				type P = $crate::arch::PackedPrimitiveType<$typ, $name>;
354				<P as $crate::arithmetic_traits::WideMul>::wide_mul(
355					P::from_underlier(a.0),
356					P::from_underlier(b.0),
357				)
358			}
359
360			#[inline]
361			fn reduce(wide: Self::Output) -> Self {
362				type P = $crate::arch::PackedPrimitiveType<$typ, $name>;
363				Self(<P as $crate::arithmetic_traits::WideMul>::reduce(wide).to_underlier())
364			}
365		}
366	};
367}
368
369pub(crate) use binary_field;
370
371macro_rules! mul_by_binary_field_1b {
372	($name:ident) => {
373		impl Mul<BinaryField1b> for $name {
374			type Output = Self;
375
376			#[inline]
377			#[allow(clippy::suspicious_arithmetic_impl)]
378			fn mul(self, rhs: BinaryField1b) -> Self::Output {
379				use $crate::underlier::{UnderlierType, WithUnderlier};
380
381				$crate::tracing::trace_multiplication!(BinaryField128b, BinaryField1b);
382
383				Self(self.0 & <$name as WithUnderlier>::Underlier::fill_with_bit(u8::from(rhs.0)))
384			}
385		}
386	};
387}
388
389pub(crate) use mul_by_binary_field_1b;
390
391macro_rules! impl_field_extension {
392	($subfield_name:ident($subfield_typ:ty) < @$log_degree:expr => $name:ident($typ:ty)) => {
393		impl TryFrom<$name> for $subfield_name {
394			type Error = ();
395
396			#[inline]
397			fn try_from(elem: $name) -> Result<Self, Self::Error> {
398				use $crate::underlier::{Divisible, UnderlierType};
399
400				// `elem` lies in the subfield iff every subfield-underlier limb above the
401				// least-significant one is zero (equivalent to `elem >> N_BITS == 0`).
402				let in_subfield = Divisible::<$subfield_typ>::ref_iter(&elem.0)
403					.skip(1)
404					.all(|limb| limb == <$subfield_typ as UnderlierType>::ZERO);
405				if in_subfield {
406					Ok($subfield_name(Divisible::<$subfield_typ>::get(&elem.0, 0)))
407				} else {
408					Err(())
409				}
410			}
411		}
412
413		impl From<$subfield_name> for $name {
414			#[inline]
415			fn from(elem: $subfield_name) -> Self {
416				$name(<$typ>::from(elem.val()))
417			}
418		}
419
420		impl Add<$subfield_name> for $name {
421			type Output = Self;
422
423			#[inline]
424			fn add(self, rhs: $subfield_name) -> Self::Output {
425				self + Self::from(rhs)
426			}
427		}
428
429		impl Sub<$subfield_name> for $name {
430			type Output = Self;
431
432			#[inline]
433			fn sub(self, rhs: $subfield_name) -> Self::Output {
434				self - Self::from(rhs)
435			}
436		}
437
438		impl AddAssign<$subfield_name> for $name {
439			#[inline]
440			fn add_assign(&mut self, rhs: $subfield_name) {
441				*self = *self + rhs;
442			}
443		}
444
445		impl SubAssign<$subfield_name> for $name {
446			#[inline]
447			fn sub_assign(&mut self, rhs: $subfield_name) {
448				*self = *self - rhs;
449			}
450		}
451
452		impl MulAssign<$subfield_name> for $name {
453			#[inline]
454			fn mul_assign(&mut self, rhs: $subfield_name) {
455				*self = *self * rhs;
456			}
457		}
458
459		impl Add<$name> for $subfield_name {
460			type Output = $name;
461
462			#[inline]
463			fn add(self, rhs: $name) -> Self::Output {
464				rhs + self
465			}
466		}
467
468		impl Sub<$name> for $subfield_name {
469			type Output = $name;
470
471			#[allow(clippy::suspicious_arithmetic_impl)]
472			#[inline]
473			fn sub(self, rhs: $name) -> Self::Output {
474				rhs + self
475			}
476		}
477
478		impl Mul<$name> for $subfield_name {
479			type Output = $name;
480
481			#[inline]
482			fn mul(self, rhs: $name) -> Self::Output {
483				rhs * self
484			}
485		}
486
487		impl ExtensionField<$subfield_name> for $name {
488			const LOG_DEGREE: usize = $log_degree;
489
490			#[inline]
491			fn basis(i: usize) -> Self {
492				use $crate::underlier::{Divisible, UnderlierType};
493
494				assert!(
495					i < 1 << $log_degree,
496					"index {} out of range for degree {}",
497					i,
498					1 << $log_degree
499				);
500				// The `i`-th basis element sets subfield-underlier limb `i` to one, i.e. bit
501				// `i * N_BITS` (equivalent to `ONE << (i * N_BITS)`).
502				let mut underlier = <$typ as UnderlierType>::ZERO;
503				Divisible::<$subfield_typ>::set(
504					&mut underlier,
505					i,
506					<$subfield_typ as UnderlierType>::ONE,
507				);
508				Self(underlier)
509			}
510
511			#[inline]
512			fn from_bases_sparse(
513				base_elems: impl IntoIterator<Item = $subfield_name>,
514				log_stride: usize,
515			) -> Self {
516				use $crate::underlier::{Divisible, UnderlierType};
517
518				debug_assert!($name::N_BITS.is_power_of_two());
519				let shift_step = ($subfield_name::N_BITS << log_stride) & ($name::N_BITS - 1);
520				let mut underlier = <$typ as UnderlierType>::ZERO;
521				let mut shift = 0;
522
523				for elem in base_elems.into_iter() {
524					assert!(shift < $name::N_BITS, "too many base elements for extension degree");
525					// `shift` is a multiple of the subfield width, so it addresses limb
526					// `shift / N_BITS`; OR the element in (matching the previous `|= .. << shift`).
527					let limb = shift / $subfield_name::N_BITS;
528					let acc = Divisible::<$subfield_typ>::get(&underlier, limb) | elem.val();
529					Divisible::<$subfield_typ>::set(&mut underlier, limb, acc);
530					shift += shift_step;
531				}
532
533				Self(underlier)
534			}
535
536			#[inline]
537			fn iter_bases(&self) -> impl Iterator<Item = $subfield_name> {
538				use binius_utils::iter::IterExtensions;
539				use $crate::underlier::{Divisible, WithUnderlier};
540
541				Divisible::<<$subfield_name as WithUnderlier>::Underlier>::ref_iter(&self.0)
542					.map_skippable($subfield_name::from)
543			}
544
545			#[inline]
546			unsafe fn get_base_unchecked(&self, i: usize) -> $subfield_name {
547				use $crate::underlier::{Divisible, WithUnderlier};
548				// Safety: the caller guarantees `i < Self::N` (over subfield elements).
549				unsafe {
550					$subfield_name::from_underlier(Divisible::<
551						<$subfield_name as WithUnderlier>::Underlier,
552					>::get_unchecked(&self.to_underlier(), i))
553				}
554			}
555
556			#[inline]
557			fn square_transpose(values: &mut [Self]) {
558				crate::transpose::square_transforms_extension_field::<$subfield_name, Self>(values)
559			}
560		}
561	};
562}
563
564pub(crate) use impl_field_extension;
565
566binary_field!(pub BinaryField1b(U1), U1::new(0x1));
567
568macro_rules! serialize_deserialize {
569	($bin_type:ty) => {
570		impl SerializeBytes for $bin_type {
571			fn serialize(&self, write_buf: impl BufMut) -> Result<(), SerializationError> {
572				self.0.serialize(write_buf)
573			}
574		}
575
576		impl DeserializeBytes for $bin_type {
577			fn deserialize(read_buf: impl Buf) -> Result<Self, SerializationError> {
578				Ok(Self(DeserializeBytes::deserialize(read_buf)?))
579			}
580		}
581	};
582}
583
584serialize_deserialize!(BinaryField1b);
585
586impl FixedSizeSerializeBytes for BinaryField1b {
587	const BYTE_SIZE: usize = 1;
588}
589
590impl BinaryField1b {
591	pub const fn new(value: U1) -> Self {
592		Self(value)
593	}
594}
595
596impl From<u8> for BinaryField1b {
597	#[inline]
598	fn from(val: u8) -> Self {
599		Self::new(U1::new(val))
600	}
601}
602
603impl From<BinaryField1b> for u8 {
604	#[inline]
605	fn from(value: BinaryField1b) -> Self {
606		value.val().into()
607	}
608}
609
610impl From<bool> for BinaryField1b {
611	#[inline]
612	fn from(value: bool) -> Self {
613		Self::from(U1::new_unchecked(value.into()))
614	}
615}
616
617#[cfg(test)]
618pub(crate) mod tests {
619	use binius_utils::{DeserializeBytes, SerializeBytes, bytes::BytesMut};
620	use proptest::prelude::*;
621
622	use super::BinaryField1b as BF1;
623	use crate::{
624		AESTowerField8b, BinaryField, BinaryField1b, BinaryField128bGhash, ExtensionField, Field,
625		GhashSq256b, arithmetic_traits::InvertOrZero,
626	};
627
628	#[test]
629	fn test_gf2_add() {
630		assert_eq!(BF1::from(0) + BF1::from(0), BF1::from(0));
631		assert_eq!(BF1::from(0) + BF1::from(1), BF1::from(1));
632		assert_eq!(BF1::from(1) + BF1::from(0), BF1::from(1));
633		assert_eq!(BF1::from(1) + BF1::from(1), BF1::from(0));
634	}
635
636	#[test]
637	fn test_gf2_sub() {
638		assert_eq!(BF1::from(0) - BF1::from(0), BF1::from(0));
639		assert_eq!(BF1::from(0) - BF1::from(1), BF1::from(1));
640		assert_eq!(BF1::from(1) - BF1::from(0), BF1::from(1));
641		assert_eq!(BF1::from(1) - BF1::from(1), BF1::from(0));
642	}
643
644	#[test]
645	fn test_gf2_mul() {
646		assert_eq!(BF1::from(0) * BF1::from(0), BF1::from(0));
647		assert_eq!(BF1::from(0) * BF1::from(1), BF1::from(0));
648		assert_eq!(BF1::from(1) * BF1::from(0), BF1::from(0));
649		assert_eq!(BF1::from(1) * BF1::from(1), BF1::from(1));
650	}
651
652	pub(crate) fn is_binary_field_valid_generator<F: BinaryField>() -> bool {
653		// Binary fields should contain a multiplicative subgroup of size 2^n - 1
654		let mut order = if F::N_BITS == 128 {
655			u128::MAX
656		} else {
657			(1 << F::N_BITS) - 1
658		};
659
660		// Naive factorization of group order - represented as a multiset of prime factors
661		let mut factorization = Vec::new();
662
663		let mut prime = 2;
664		while prime * prime <= order {
665			while order.is_multiple_of(prime) {
666				order /= prime;
667				factorization.push(prime);
668			}
669
670			prime += if prime > 2 { 2 } else { 1 };
671		}
672
673		if order > 1 {
674			factorization.push(order);
675		}
676
677		// Iterate over all divisors (some may be tested several times if order is non-square-free)
678		for mask in 0..(1 << factorization.len()) {
679			let mut divisor = 1;
680
681			for (bit_index, &prime) in factorization.iter().enumerate() {
682				if (1 << bit_index) & mask != 0 {
683					divisor *= prime;
684				}
685			}
686
687			// Compute pow(generator, divisor) in log time
688			divisor = divisor.reverse_bits();
689
690			let mut pow_divisor = F::ONE;
691			while divisor > 0 {
692				pow_divisor *= pow_divisor;
693
694				if divisor & 1 != 0 {
695					pow_divisor *= F::MULTIPLICATIVE_GENERATOR;
696				}
697
698				divisor >>= 1;
699			}
700
701			// Generator invariant
702			let is_root_of_unity = pow_divisor == F::ONE;
703			let is_full_group = mask + 1 == 1 << factorization.len();
704
705			if is_root_of_unity && !is_full_group || !is_root_of_unity && is_full_group {
706				return false;
707			}
708		}
709
710		true
711	}
712
713	#[test]
714	fn test_multiplicative_generators() {
715		assert!(is_binary_field_valid_generator::<BinaryField1b>());
716		assert!(is_binary_field_valid_generator::<AESTowerField8b>());
717		assert!(is_binary_field_valid_generator::<BinaryField128bGhash>());
718	}
719
720	#[test]
721	fn test_field_degrees() {
722		assert_eq!(BinaryField1b::N_BITS, 1);
723		assert_eq!(AESTowerField8b::N_BITS, 8);
724		assert_eq!(BinaryField128bGhash::N_BITS, 128);
725	}
726
727	#[test]
728	fn test_field_formatting() {
729		assert_eq!(format!("{}", BinaryField1b::from(1)), "0x1");
730		assert_eq!(format!("{}", AESTowerField8b::from(3)), "0x03");
731		assert_eq!(
732			format!("{}", BinaryField128bGhash::new(5)),
733			"0x00000000000000000000000000000005"
734		);
735	}
736
737	#[test]
738	fn test_inverse_on_zero() {
739		assert!(BinaryField1b::ZERO.invert_or_zero().is_zero());
740		assert!(AESTowerField8b::ZERO.invert_or_zero().is_zero());
741		assert!(BinaryField128bGhash::ZERO.invert_or_zero().is_zero());
742	}
743
744	proptest! {
745		#[test]
746		fn test_inverse_8b(val in 1u8..) {
747			let x = AESTowerField8b::new(val);
748			// Safety: `val` is in `1..`, so `x` is non-zero.
749			let x_inverse = unsafe { x.invert() };
750			assert_eq!(x * x_inverse, AESTowerField8b::ONE);
751		}
752
753		#[test]
754		fn test_inverse_128b(val in 1u128..) {
755			let x = BinaryField128bGhash::from(val);
756			// Safety: `val` is in `1..`, so `x` is non-zero.
757			let x_inverse = unsafe { x.invert() };
758			assert_eq!(x * x_inverse, BinaryField128bGhash::ONE);
759		}
760	}
761
762	/// Checks the `TryFrom` conversion narrowing an extension field element to its subfield:
763	/// elements embedded from the subfield must round-trip, and elements with a nonzero
764	/// coefficient outside the subfield must be rejected.
765	fn assert_subfield_extraction<FSub: Field, F: ExtensionField<FSub>>() {
766		assert_eq!(TryInto::<FSub>::try_into(F::from(FSub::ZERO)).ok(), Some(FSub::ZERO));
767
768		// `BinaryField1b` has a trivial multiplicative group, so for the three pairs with that
769		// subfield this sweeps `ONE` alone, which together with `ZERO` is already the whole field.
770		// Only `BinaryField128bGhash` in `GhashSq256b` walks non-trivial subfield values.
771		let mut elem = FSub::ONE;
772		for _ in 0..4 {
773			assert_eq!(TryInto::<FSub>::try_into(F::from(elem)).ok(), Some(elem));
774			elem *= FSub::MULTIPLICATIVE_GENERATOR;
775		}
776
777		// `basis(i)` for `i > 0` has a zero coefficient of `1` and a nonzero higher coefficient,
778		// so it lies outside the subfield - with or without a subfield part added on.
779		for i in 1..F::DEGREE {
780			assert!(TryInto::<FSub>::try_into(F::basis(i)).is_err());
781			assert!(TryInto::<FSub>::try_into(F::basis(i) + F::ONE).is_err());
782		}
783	}
784
785	#[test]
786	fn test_subfield_extraction() {
787		assert_subfield_extraction::<BinaryField1b, BinaryField128bGhash>();
788		assert_subfield_extraction::<BinaryField1b, AESTowerField8b>();
789		assert_subfield_extraction::<BinaryField128bGhash, GhashSq256b>();
790		assert_subfield_extraction::<BinaryField1b, GhashSq256b>();
791	}
792
793	#[test]
794	fn test_serialization() {
795		let mut buffer = BytesMut::new();
796		let b1 = BinaryField1b::from(0x1);
797		let b8 = AESTowerField8b::new(0x12);
798		let b128 = BinaryField128bGhash::new(0x147AD0369CF258BE8899AABBCCDDEEFF);
799
800		b1.serialize(&mut buffer).unwrap();
801		b8.serialize(&mut buffer).unwrap();
802		b128.serialize(&mut buffer).unwrap();
803
804		let mut read_buffer = buffer.freeze();
805
806		assert_eq!(BinaryField1b::deserialize(&mut read_buffer).unwrap(), b1);
807		assert_eq!(AESTowerField8b::deserialize(&mut read_buffer).unwrap(), b8);
808		assert_eq!(BinaryField128bGhash::deserialize(&mut read_buffer).unwrap(), b128);
809	}
810}