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