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