binius_field/
binary_field.rs

1// Copyright 2023-2025 Irreducible Inc.
2
3use std::{
4	fmt::{Debug, Display, Formatter},
5	iter::{Product, Sum},
6	ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
7};
8
9use binius_utils::{
10	DeserializeBytes, SerializationError, SerializeBytes,
11	bytes::{Buf, BufMut},
12};
13use bytemuck::Zeroable;
14
15use super::{
16	UnderlierWithBitOps, WithUnderlier, binary_field_arithmetic::TowerFieldArithmetic,
17	error::Error, extension::ExtensionField,
18};
19use crate::{Field, underlier::U1};
20
21/// A finite field with characteristic 2.
22pub trait BinaryField:
23	ExtensionField<BinaryField1b> + WithUnderlier<Underlier: UnderlierWithBitOps>
24{
25	const N_BITS: usize = Self::DEGREE;
26}
27
28/// A binary field *isomorphic* to a binary tower field.
29///
30/// The canonical binary field tower construction is specified in [DP23], section 2.3. This is a
31/// family of binary fields with extension degree $2^{\iota}$ for any tower height $\iota$. This
32/// trait can be implemented on any binary field *isomorphic* to the canonical tower field.
33///
34/// [DP23]: https://eprint.iacr.org/2023/1784
35pub trait TowerField: BinaryField {
36	/// The level $\iota$ in the tower, where this field is isomorphic to $T_{\iota}$.
37	const TOWER_LEVEL: usize = Self::N_BITS.ilog2() as usize;
38
39	/// Returns the smallest valid `TOWER_LEVEL` in the tower that can fit the same value.
40	///
41	/// Since which `TOWER_LEVEL` values are valid depends on the tower,
42	/// `F::Canonical::from(elem).min_tower_level()` can return a different result
43	/// from `elem.min_tower_level()`.
44	fn min_tower_level(self) -> usize;
45
46	/// Returns the i'th basis element of this field as an extension over the tower subfield with
47	/// level $\iota$.
48	fn basis(iota: usize, i: usize) -> Result<Self, Error> {
49		if iota > Self::TOWER_LEVEL {
50			return Err(Error::ExtensionDegreeTooHigh);
51		}
52		let n_basis_elts = 1 << (Self::TOWER_LEVEL - iota);
53		if i >= n_basis_elts {
54			return Err(Error::IndexOutOfRange {
55				index: i,
56				max: n_basis_elts,
57			});
58		}
59		<Self as ExtensionField<BinaryField1b>>::basis_checked(i << iota)
60	}
61
62	/// Multiplies a field element by the canonical primitive element of the extension $T_{\iota +
63	/// 1} / T_{iota}$.
64	///
65	/// We represent the tower field $T_{\iota + 1}$ as a vector space over $T_{\iota}$ with the
66	/// basis $\{1, \beta^{(\iota)}_1\}$. This operation multiplies the element by
67	/// $\beta^{(\iota)}_1$.
68	///
69	/// ## Throws
70	///
71	/// * `Error::ExtensionDegreeTooHigh` if `iota >= Self::TOWER_LEVEL`
72	fn mul_primitive(self, iota: usize) -> Result<Self, Error> {
73		Ok(self * <Self as ExtensionField<BinaryField1b>>::basis_checked(1 << iota)?)
74	}
75}
76
77/// Returns the i'th basis element of `FExt` as a field extension of `FSub`.
78///
79/// This is an alias function for [`ExtensionField::basis`].
80///
81/// ## Pre-conditions
82///
83/// * `i` must be in the range $[0, d)$, where $d$ is the field extension degree.
84#[inline]
85pub fn ext_basis<FExt, FSub>(i: usize) -> FExt
86where
87	FSub: Field,
88	FExt: ExtensionField<FSub>,
89{
90	<FExt as ExtensionField<FSub>>::basis(i)
91}
92
93pub(super) trait TowerExtensionField:
94	TowerField
95	+ ExtensionField<Self::DirectSubfield>
96	+ From<(Self::DirectSubfield, Self::DirectSubfield)>
97	+ Into<(Self::DirectSubfield, Self::DirectSubfield)>
98{
99	type DirectSubfield: TowerField;
100}
101
102/// Macro to generate an implementation of a BinaryField.
103macro_rules! binary_field {
104	($vis:vis $name:ident($typ:ty), $gen:expr) => {
105		#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Zeroable, bytemuck::TransparentWrapper)]
106		#[repr(transparent)]
107		$vis struct $name(pub(crate) $typ);
108
109		impl $name {
110			pub const fn new(value: $typ) -> Self {
111				Self(value)
112			}
113
114			pub const fn val(self) -> $typ {
115				self.0
116			}
117		}
118
119		unsafe impl $crate::underlier::WithUnderlier for $name {
120			type Underlier = $typ;
121		}
122
123		impl Neg for $name {
124			type Output = Self;
125
126			fn neg(self) -> Self::Output {
127				self
128			}
129		}
130
131		impl Add<Self> for $name {
132			type Output = Self;
133
134			#[allow(clippy::suspicious_arithmetic_impl)]
135			fn add(self, rhs: Self) -> Self::Output {
136				$name(self.0 ^ rhs.0)
137			}
138		}
139
140		impl Add<&Self> for $name {
141			type Output = Self;
142
143			#[allow(clippy::suspicious_arithmetic_impl)]
144			fn add(self, rhs: &Self) -> Self::Output {
145				$name(self.0 ^ rhs.0)
146			}
147		}
148
149		impl Sub<Self> for $name {
150			type Output = Self;
151
152			#[allow(clippy::suspicious_arithmetic_impl)]
153			fn sub(self, rhs: Self) -> Self::Output {
154				$name(self.0 ^ rhs.0)
155			}
156		}
157
158		impl Sub<&Self> for $name {
159			type Output = Self;
160
161			#[allow(clippy::suspicious_arithmetic_impl)]
162			fn sub(self, rhs: &Self) -> Self::Output {
163				$name(self.0 ^ rhs.0)
164			}
165		}
166
167		impl Mul<Self> for $name {
168			type Output = Self;
169
170			fn mul(self, rhs: Self) -> Self::Output {
171				$crate::tracing::trace_multiplication!($name);
172
173				TowerFieldArithmetic::multiply(self, rhs)
174			}
175		}
176
177		impl Mul<&Self> for $name {
178			type Output = Self;
179
180			fn mul(self, rhs: &Self) -> Self::Output {
181				self * *rhs
182			}
183		}
184
185		impl AddAssign<Self> for $name {
186			fn add_assign(&mut self, rhs: Self) {
187				*self = *self + rhs;
188			}
189		}
190
191		impl AddAssign<&Self> for $name {
192			fn add_assign(&mut self, rhs: &Self) {
193				*self = *self + *rhs;
194			}
195		}
196
197		impl SubAssign<Self> for $name {
198			fn sub_assign(&mut self, rhs: Self) {
199				*self = *self - rhs;
200			}
201		}
202
203		impl SubAssign<&Self> for $name {
204			fn sub_assign(&mut self, rhs: &Self) {
205				*self = *self - *rhs;
206			}
207		}
208
209		impl MulAssign<Self> for $name {
210			fn mul_assign(&mut self, rhs: Self) {
211				*self = *self * rhs;
212			}
213		}
214
215		impl MulAssign<&Self> for $name {
216			fn mul_assign(&mut self, rhs: &Self) {
217				*self = *self * rhs;
218			}
219		}
220
221		impl Sum<Self> for $name {
222			fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
223				iter.fold(Self::ZERO, |acc, x| acc + x)
224			}
225		}
226
227		impl<'a> Sum<&'a Self> for $name {
228			fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
229				iter.fold(Self::ZERO, |acc, x| acc + x)
230			}
231		}
232
233		impl Product<Self> for $name {
234			fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
235				iter.fold(Self::ONE, |acc, x| acc * x)
236			}
237		}
238
239		impl<'a> Product<&'a Self> for $name {
240			fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
241				iter.fold(Self::ONE, |acc, x| acc * x)
242			}
243		}
244
245
246		impl crate::arithmetic_traits::Square for $name {
247			fn square(self) -> Self {
248				TowerFieldArithmetic::square(self)
249			}
250		}
251
252		impl Field for $name {
253			const ZERO: Self = $name::new(<$typ as $crate::underlier::UnderlierWithBitOps>::ZERO);
254			const ONE: Self = $name::new(<$typ as $crate::underlier::UnderlierWithBitOps>::ONE);
255			const CHARACTERISTIC: usize = 2;
256			const MULTIPLICATIVE_GENERATOR: $name = $name($gen);
257
258			fn double(&self) -> Self {
259				Self::ZERO
260			}
261		}
262
263		impl ::rand::distr::Distribution<$name> for ::rand::distr::StandardUniform {
264			fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> $name {
265				$name(rng.random())
266			}
267		}
268
269		impl Display for $name {
270			fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
271				write!(f, "0x{repr:0>width$x}", repr=self.val(), width=Self::N_BITS.max(4) / 4)
272			}
273		}
274
275		impl Debug for $name {
276			fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
277				let structure_name = std::any::type_name::<$name>().split("::").last().expect("exist");
278
279				write!(f, "{}({})",structure_name, self)
280			}
281		}
282
283		impl BinaryField for $name {}
284
285		impl From<$typ> for $name {
286			fn from(val: $typ) -> Self {
287				return Self(val)
288			}
289		}
290
291		impl From<$name> for $typ {
292			fn from(val: $name) -> Self {
293				return val.0
294			}
295		}
296	}
297}
298
299pub(crate) use binary_field;
300
301macro_rules! mul_by_binary_field_1b {
302	($name:ident) => {
303		impl Mul<BinaryField1b> for $name {
304			type Output = Self;
305
306			#[inline]
307			#[allow(clippy::suspicious_arithmetic_impl)]
308			fn mul(self, rhs: BinaryField1b) -> Self::Output {
309				use $crate::underlier::{UnderlierWithBitOps, WithUnderlier};
310
311				$crate::tracing::trace_multiplication!(BinaryField128b, BinaryField1b);
312
313				Self(self.0 & <$name as WithUnderlier>::Underlier::fill_with_bit(u8::from(rhs.0)))
314			}
315		}
316	};
317}
318
319pub(crate) use mul_by_binary_field_1b;
320
321macro_rules! impl_field_extension {
322	($subfield_name:ident($subfield_typ:ty) < @$log_degree:expr => $name:ident($typ:ty)) => {
323		impl TryFrom<$name> for $subfield_name {
324			type Error = ();
325
326			#[inline]
327			fn try_from(elem: $name) -> Result<Self, Self::Error> {
328				use $crate::underlier::NumCast;
329
330				if elem.0 >> $subfield_name::N_BITS
331					== <$typ as $crate::underlier::UnderlierWithBitOps>::ZERO
332				{
333					Ok($subfield_name::new(<$subfield_typ>::num_cast_from(elem.val())))
334				} else {
335					Err(())
336				}
337			}
338		}
339
340		impl From<$subfield_name> for $name {
341			#[inline]
342			fn from(elem: $subfield_name) -> Self {
343				$name::new(<$typ>::from(elem.val()))
344			}
345		}
346
347		impl Add<$subfield_name> for $name {
348			type Output = Self;
349
350			#[inline]
351			fn add(self, rhs: $subfield_name) -> Self::Output {
352				self + Self::from(rhs)
353			}
354		}
355
356		impl Sub<$subfield_name> for $name {
357			type Output = Self;
358
359			#[inline]
360			fn sub(self, rhs: $subfield_name) -> Self::Output {
361				self - Self::from(rhs)
362			}
363		}
364
365		impl AddAssign<$subfield_name> for $name {
366			#[inline]
367			fn add_assign(&mut self, rhs: $subfield_name) {
368				*self = *self + rhs;
369			}
370		}
371
372		impl SubAssign<$subfield_name> for $name {
373			#[inline]
374			fn sub_assign(&mut self, rhs: $subfield_name) {
375				*self = *self - rhs;
376			}
377		}
378
379		impl MulAssign<$subfield_name> for $name {
380			#[inline]
381			fn mul_assign(&mut self, rhs: $subfield_name) {
382				*self = *self * rhs;
383			}
384		}
385
386		impl Add<$name> for $subfield_name {
387			type Output = $name;
388
389			#[inline]
390			fn add(self, rhs: $name) -> Self::Output {
391				rhs + self
392			}
393		}
394
395		impl Sub<$name> for $subfield_name {
396			type Output = $name;
397
398			#[allow(clippy::suspicious_arithmetic_impl)]
399			#[inline]
400			fn sub(self, rhs: $name) -> Self::Output {
401				rhs + self
402			}
403		}
404
405		impl Mul<$name> for $subfield_name {
406			type Output = $name;
407
408			#[inline]
409			fn mul(self, rhs: $name) -> Self::Output {
410				rhs * self
411			}
412		}
413
414		impl ExtensionField<$subfield_name> for $name {
415			const LOG_DEGREE: usize = $log_degree;
416
417			#[inline]
418			fn basis_checked(i: usize) -> Result<Self, Error> {
419				use $crate::underlier::UnderlierWithBitOps;
420
421				if i >= 1 << $log_degree {
422					return Err(Error::ExtensionDegreeMismatch);
423				}
424				Ok(Self::new(<$typ>::ONE << (i * $subfield_name::N_BITS)))
425			}
426
427			#[inline]
428			fn from_bases_sparse(
429				base_elems: impl IntoIterator<Item = $subfield_name>,
430				log_stride: usize,
431			) -> Result<Self, Error> {
432				use $crate::underlier::UnderlierWithBitOps;
433
434				debug_assert!($name::N_BITS.is_power_of_two());
435				let shift_step = ($subfield_name::N_BITS << log_stride) & ($name::N_BITS - 1);
436				let mut value = <$typ>::ZERO;
437				let mut shift = 0;
438
439				for elem in base_elems.into_iter() {
440					if shift >= $name::N_BITS {
441						return Err(Error::ExtensionDegreeMismatch);
442					}
443					value |= <$typ>::from(elem.val()) << shift;
444					shift += shift_step;
445				}
446
447				Ok(Self::new(value))
448			}
449
450			#[inline]
451			fn iter_bases(&self) -> impl Iterator<Item = $subfield_name> {
452				use binius_utils::iter::IterExtensions;
453				use $crate::underlier::{Divisible, WithUnderlier};
454
455				Divisible::<<$subfield_name as WithUnderlier>::Underlier>::ref_iter(&self.0)
456					.map_skippable($subfield_name::from)
457			}
458
459			#[inline]
460			fn into_iter_bases(self) -> impl Iterator<Item = $subfield_name> {
461				use binius_utils::iter::IterExtensions;
462				use $crate::underlier::{Divisible, WithUnderlier};
463
464				Divisible::<<$subfield_name as WithUnderlier>::Underlier>::value_iter(self.0)
465					.map_skippable($subfield_name::from)
466			}
467
468			#[inline]
469			unsafe fn get_base_unchecked(&self, i: usize) -> $subfield_name {
470				use $crate::underlier::{UnderlierWithBitOps, WithUnderlier};
471				unsafe { $subfield_name::from_underlier(self.to_underlier().get_subvalue(i)) }
472			}
473
474			#[inline]
475			fn square_transpose(values: &mut [Self]) -> Result<(), Error> {
476				crate::transpose::square_transforms_extension_field::<$subfield_name, Self>(values)
477					.map_err(|_| Error::ExtensionDegreeMismatch)
478			}
479		}
480	};
481}
482
483pub(crate) use impl_field_extension;
484
485binary_field!(pub BinaryField1b(U1), U1::new(0x1));
486
487macro_rules! serialize_deserialize {
488	($bin_type:ty) => {
489		impl SerializeBytes for $bin_type {
490			fn serialize(&self, write_buf: impl BufMut) -> Result<(), SerializationError> {
491				self.0.serialize(write_buf)
492			}
493		}
494
495		impl DeserializeBytes for $bin_type {
496			fn deserialize(read_buf: impl Buf) -> Result<Self, SerializationError> {
497				Ok(Self(DeserializeBytes::deserialize(read_buf)?))
498			}
499		}
500	};
501}
502
503serialize_deserialize!(BinaryField1b);
504
505impl BinaryField1b {
506	/// Creates value without checking that it is within valid range (0 or 1)
507	///
508	/// # Safety
509	/// Value should not exceed 1
510	#[inline]
511	pub unsafe fn new_unchecked(val: u8) -> Self {
512		debug_assert!(val < 2, "val has to be less than 2, but it's {val}");
513
514		Self::new(U1::new_unchecked(val))
515	}
516}
517
518impl From<u8> for BinaryField1b {
519	#[inline]
520	fn from(val: u8) -> Self {
521		Self::new(U1::new(val))
522	}
523}
524
525impl From<BinaryField1b> for u8 {
526	#[inline]
527	fn from(value: BinaryField1b) -> Self {
528		value.val().into()
529	}
530}
531
532impl From<bool> for BinaryField1b {
533	#[inline]
534	fn from(value: bool) -> Self {
535		Self::from(U1::new_unchecked(value.into()))
536	}
537}
538
539#[cfg(test)]
540pub(crate) mod tests {
541	use binius_utils::{DeserializeBytes, SerializeBytes, bytes::BytesMut};
542	use proptest::prelude::*;
543
544	use super::BinaryField1b as BF1;
545	use crate::{AESTowerField8b, BinaryField, BinaryField1b, BinaryField128bGhash, Field};
546
547	#[test]
548	fn test_gf2_add() {
549		assert_eq!(BF1::from(0) + BF1::from(0), BF1::from(0));
550		assert_eq!(BF1::from(0) + BF1::from(1), BF1::from(1));
551		assert_eq!(BF1::from(1) + BF1::from(0), BF1::from(1));
552		assert_eq!(BF1::from(1) + BF1::from(1), BF1::from(0));
553	}
554
555	#[test]
556	fn test_gf2_sub() {
557		assert_eq!(BF1::from(0) - BF1::from(0), BF1::from(0));
558		assert_eq!(BF1::from(0) - BF1::from(1), BF1::from(1));
559		assert_eq!(BF1::from(1) - BF1::from(0), BF1::from(1));
560		assert_eq!(BF1::from(1) - BF1::from(1), BF1::from(0));
561	}
562
563	#[test]
564	fn test_gf2_mul() {
565		assert_eq!(BF1::from(0) * BF1::from(0), BF1::from(0));
566		assert_eq!(BF1::from(0) * BF1::from(1), BF1::from(0));
567		assert_eq!(BF1::from(1) * BF1::from(0), BF1::from(0));
568		assert_eq!(BF1::from(1) * BF1::from(1), BF1::from(1));
569	}
570
571	pub(crate) fn is_binary_field_valid_generator<F: BinaryField>() -> bool {
572		// Binary fields should contain a multiplicative subgroup of size 2^n - 1
573		let mut order = if F::N_BITS == 128 {
574			u128::MAX
575		} else {
576			(1 << F::N_BITS) - 1
577		};
578
579		// Naive factorization of group order - represented as a multiset of prime factors
580		let mut factorization = Vec::new();
581
582		let mut prime = 2;
583		while prime * prime <= order {
584			while order.is_multiple_of(prime) {
585				order /= prime;
586				factorization.push(prime);
587			}
588
589			prime += if prime > 2 { 2 } else { 1 };
590		}
591
592		if order > 1 {
593			factorization.push(order);
594		}
595
596		// Iterate over all divisors (some may be tested several times if order is non-square-free)
597		for mask in 0..(1 << factorization.len()) {
598			let mut divisor = 1;
599
600			for (bit_index, &prime) in factorization.iter().enumerate() {
601				if (1 << bit_index) & mask != 0 {
602					divisor *= prime;
603				}
604			}
605
606			// Compute pow(generator, divisor) in log time
607			divisor = divisor.reverse_bits();
608
609			let mut pow_divisor = F::ONE;
610			while divisor > 0 {
611				pow_divisor *= pow_divisor;
612
613				if divisor & 1 != 0 {
614					pow_divisor *= F::MULTIPLICATIVE_GENERATOR;
615				}
616
617				divisor >>= 1;
618			}
619
620			// Generator invariant
621			let is_root_of_unity = pow_divisor == F::ONE;
622			let is_full_group = mask + 1 == 1 << factorization.len();
623
624			if is_root_of_unity && !is_full_group || !is_root_of_unity && is_full_group {
625				return false;
626			}
627		}
628
629		true
630	}
631
632	#[test]
633	fn test_multiplicative_generators() {
634		assert!(is_binary_field_valid_generator::<BinaryField1b>());
635		assert!(is_binary_field_valid_generator::<AESTowerField8b>());
636		assert!(is_binary_field_valid_generator::<BinaryField128bGhash>());
637	}
638
639	#[test]
640	fn test_field_degrees() {
641		assert_eq!(BinaryField1b::N_BITS, 1);
642		assert_eq!(AESTowerField8b::N_BITS, 8);
643		assert_eq!(BinaryField128bGhash::N_BITS, 128);
644	}
645
646	#[test]
647	fn test_field_formatting() {
648		assert_eq!(format!("{}", BinaryField1b::from(1)), "0x1");
649		assert_eq!(format!("{}", AESTowerField8b::from(3)), "0x03");
650		assert_eq!(
651			format!("{}", BinaryField128bGhash::from(5)),
652			"0x00000000000000000000000000000005"
653		);
654	}
655
656	#[test]
657	fn test_inverse_on_zero() {
658		assert!(BinaryField1b::ZERO.invert().is_none());
659		assert!(AESTowerField8b::ZERO.invert().is_none());
660		assert!(BinaryField128bGhash::ZERO.invert().is_none());
661	}
662
663	proptest! {
664		#[test]
665		fn test_inverse_8b(val in 1u8..) {
666			let x = AESTowerField8b::new(val);
667			let x_inverse = x.invert().unwrap();
668			assert_eq!(x * x_inverse, AESTowerField8b::ONE);
669		}
670
671		#[test]
672		fn test_inverse_128b(val in 1u128..) {
673			let x = BinaryField128bGhash::new(val);
674			let x_inverse = x.invert().unwrap();
675			assert_eq!(x * x_inverse, BinaryField128bGhash::ONE);
676		}
677	}
678
679	#[test]
680	fn test_serialization() {
681		let mut buffer = BytesMut::new();
682		let b1 = BinaryField1b::from(0x1);
683		let b8 = AESTowerField8b::new(0x12);
684		let b128 = BinaryField128bGhash::new(0x147AD0369CF258BE8899AABBCCDDEEFF);
685
686		b1.serialize(&mut buffer).unwrap();
687		b8.serialize(&mut buffer).unwrap();
688		b128.serialize(&mut buffer).unwrap();
689
690		let mut read_buffer = buffer.freeze();
691
692		assert_eq!(BinaryField1b::deserialize(&mut read_buffer).unwrap(), b1);
693		assert_eq!(AESTowerField8b::deserialize(&mut read_buffer).unwrap(), b8);
694		assert_eq!(BinaryField128bGhash::deserialize(&mut read_buffer).unwrap(), b128);
695	}
696
697	#[test]
698	fn test_gf2_new_unchecked() {
699		for i in 0..2 {
700			assert_eq!(unsafe { BF1::new_unchecked(i) }, BF1::from(i));
701		}
702	}
703}