Skip to main content

p3_binary_field/
tower.rs

1//! The Wiedemann tower `GF(2) ⊂ GF(4) ⊂ GF(2^4) ⊂ … ⊂ GF(2^128)`.
2//!
3//! Writing `T_k` for `GF(2^(2^k))`, the tower is defined recursively by `T_0 = GF(2)` and
4//!
5//! ```text
6//! T_{k+1} = T_k[X_k] / (X_k² + X_{k−1}·X_k + 1),      X_{−1} = 1.
7//! ```
8//!
9//! An element of `T_{k+1}` is stored in the low `2^{k+1}` bits of an unsigned integer: the low
10//! half holds the `T_k`-coefficient of `1`, the high half the `T_k`-coefficient of `X_k`, and
11//! the splitting repeats down to the individual bits of `GF(2)`.
12
13use alloc::vec::Vec;
14use core::fmt::{self, Debug, Display, Formatter};
15use core::iter::{Product, Sum};
16use core::mem::ManuallyDrop;
17use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
18
19use num_bigint::BigUint;
20use p3_field::op_assign_macros::{
21    impl_add_assign, impl_add_base_field, impl_div_methods, impl_mul_methods, impl_sub_assign,
22    impl_sub_base_field, ring_sum,
23};
24use p3_field::{Algebra, Field, Packable, PrimeCharacteristicRing, RawDataSerializable};
25use rand::Rng;
26use rand::distr::{Distribution, StandardUniform};
27use serde::de::Error;
28use serde::{Deserialize, Deserializer, Serialize};
29
30use crate::clmul::{HAS_HARDWARE_CLMUL, mul_64, mul_128};
31use crate::gf2::characteristic_two_methods;
32use crate::{Gf2, tables};
33
34/// Seals [`TowerLevel`] against implementation outside this crate.
35///
36/// `domain_point`, `AdditiveNtt` and every identity `p3-binary-dft` builds on assume
37/// `cantor_basis` is *the* Cantor basis — `v_0 = 1` and `v_i² + v_i = v_{i−1}` — not merely some
38/// `F_2`-linearly independent sequence. An external implementation satisfying none of that would
39/// fail silently, with wrong evaluations rather than a compile error, wherever those assume it.
40pub(crate) mod private {
41    pub trait Sealed {}
42}
43
44/// One level of the Wiedemann tower, `GF(2^(2^k))`, in whichever basis carries it.
45///
46/// The tower fixes each level as an abstract field, not as a set of bit patterns.
47///
48/// An implementation may hold its elements in any `F_2`-basis of that field.
49/// What it may not do is report a Cantor basis other than the image of the tower's own.
50///
51/// That is what makes every transform agree whichever representation runs it.
52pub trait TowerLevel: Field + private::Sealed {
53    /// The backing integer of an element.
54    type Repr: Copy;
55
56    /// The `k` in `GF(2^(2^k))`.
57    const LOG_BITS: usize;
58    /// Build an element from a bit pattern, discarding the bits above `2^LOG_BITS`.
59    fn from_repr(r: Self::Repr) -> Self;
60    /// The bit pattern of this element, zero above `2^LOG_BITS`.
61    fn to_repr(self) -> Self::Repr;
62    /// Multiply by the tower's generator `X_{k−1}` of this level over the one below.
63    fn mul_alpha(self) -> Self;
64    /// Build an element from the next [`RawDataSerializable::NUM_BYTES`] bytes of a
65    /// little-endian byte stream, discarding the bits above `2^LOG_BITS`.
66    ///
67    /// # Panics
68    /// Panics if the stream ends before a whole element has been read.
69    fn from_le_byte_iter(bytes: impl Iterator<Item = u8>) -> Self;
70    /// The `i`-th vector of the Cantor basis of this level.
71    ///
72    /// # Panics
73    /// Panics if `i` is at least the bit width `2^LOG_BITS` of this level.
74    fn cantor_basis(i: usize) -> Self;
75}
76
77/// The panic message shared by every [`TowerLevel::from_le_byte_iter`] implementation.
78const BYTE_STREAM_ENDED: &str = "byte stream ended before a whole element was read";
79
80impl private::Sealed for Gf2 {}
81
82impl TowerLevel for Gf2 {
83    type Repr = u8;
84
85    const LOG_BITS: usize = 0;
86
87    #[inline]
88    fn from_repr(r: Self::Repr) -> Self {
89        Self::from_bool((r & 1) == 1)
90    }
91
92    #[inline]
93    fn to_repr(self) -> Self::Repr {
94        u8::from(self.is_one())
95    }
96
97    /// `X_{−1} = 1`, so at the base of the tower this is the identity.
98    #[inline]
99    fn mul_alpha(self) -> Self {
100        self
101    }
102
103    #[inline]
104    fn from_le_byte_iter(mut bytes: impl Iterator<Item = u8>) -> Self {
105        Self::from_le_bytes([bytes.next().expect(BYTE_STREAM_ENDED)])
106    }
107
108    /// `GF(2)` holds only `v_0 = 1`.
109    #[inline]
110    fn cantor_basis(i: usize) -> Self {
111        assert!(i < 1, "Cantor basis index out of range");
112        Self::ONE
113    }
114}
115
116/// Define one level of the tower as a quadratic extension of the level below.
117///
118/// The parameters are the name of the level, its bit width, its backing integer, the level
119/// below with that level's backing integer, the bit pattern of a multiplicative generator, and
120/// the methods `Mul`, `square` and `try_inverse` forward to.
121macro_rules! binary_tower_level {
122    ($name:ident, $bits:literal, $repr:ty, $lower:ty, $lower_repr:ty, $generator:literal, $mul:ident, $square:ident, $try_inverse:ident) => {
123        #[doc = concat!("The binary tower field `GF(2^", stringify!($bits), ")`.")]
124        ///
125        #[doc = concat!("A quadratic extension of [`", stringify!($lower), "`] generated by a root `X` of")]
126        /// `X² + αX + 1`, where `α` is the generator of the level below over the one beneath it.
127        /// The low half of the backing integer holds the coefficient of `1`, the high half the
128        /// coefficient of `X`.
129        ///
130        /// The serde encoding is canonical: every field element has exactly one valid byte
131        /// representation (see the manual [`Deserialize`] impl below). `#[serde(transparent)]`
132        /// makes the derived [`Serialize`] emit the backing integer itself, which is what that
133        /// impl reads back.
134        #[derive(Copy, Clone, Default, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize)]
135        #[serde(transparent)]
136        #[repr(transparent)]
137        #[must_use]
138        pub struct $name($repr);
139
140        impl $name {
141            /// The number of bits of an element.
142            pub(crate) const BITS: usize = $bits;
143
144            /// Selects the bits of a canonical representative.
145            const MASK: $repr = <$repr>::MAX >> (<$repr>::BITS as usize - $bits);
146
147            /// The number of bits of each coefficient over the level below.
148            const HALF_BITS: usize = $bits / 2;
149
150            /// Selects the bits of a canonical representative of the level below.
151            const HALF_MASK: $repr = Self::MASK >> Self::HALF_BITS;
152
153            /// The coefficients `(a0, a1)` of `self = a0 + a1·X`.
154            #[inline]
155            pub(crate) fn split(self) -> ($lower, $lower) {
156                let a0 = (self.0 & Self::HALF_MASK) as $lower_repr;
157                let a1 = (self.0 >> Self::HALF_BITS) as $lower_repr;
158                (<$lower>::from_repr(a0), <$lower>::from_repr(a1))
159            }
160
161            /// The element `a0 + a1·X`.
162            #[inline]
163            pub(crate) fn join(a0: $lower, a1: $lower) -> Self {
164                Self((a0.to_repr() as $repr) | ((a1.to_repr() as $repr) << Self::HALF_BITS))
165            }
166
167            /// Karatsuba multiplication modulo `X² = αX + 1`.
168            ///
169            /// With `z0 = a0·b0`, `z2 = a1·b1` and `z1 = a0·b1 + a1·b0`,
170            /// `a·b = (z0 + z2) + (z1 + α·z2)·X`.
171            ///
172            /// The coefficient products recurse through the level below's `reference_mul`
173            /// rather than its `Mul`, so this stays a self-contained definition of the tower
174            /// product even at the levels whose `Mul` dispatches to a hardware fast path.
175            #[doc(hidden)]
176            #[inline]
177            pub fn reference_mul(self, rhs: Self) -> Self {
178                let (a0, a1) = self.split();
179                let (b0, b1) = rhs.split();
180                let z0 = a0.reference_mul(b0);
181                let z2 = a1.reference_mul(b1);
182                let z1 = (a0 + a1).reference_mul(b0 + b1) + z0 + z2;
183                Self::join(z0 + z2, z1 + z2.mul_alpha())
184            }
185
186            /// Squaring modulo `X² = αX + 1`.
187            ///
188            /// The cross term `2·a0·a1·X` vanishes in characteristic 2, leaving
189            /// `a² = (a0² + a1²) + α·a1²·X`.
190            // The independent definition of squaring, kept at every level and compared
191            // against in the tests even where `square` takes a faster route.
192            #[allow(dead_code)]
193            #[inline]
194            fn reference_square(self) -> Self {
195                let (a0, a1) = self.split();
196                let a0_sq = a0.square();
197                let a1_sq = a1.square();
198                Self::join(a0_sq + a1_sq, a1_sq.mul_alpha())
199            }
200
201            /// Inversion through the norm to the level below.
202            ///
203            /// The conjugate of `a` over the level below is `(a0 + α·a1) + a1·X`, and the
204            /// product of the two, `N = a0² + α·a0·a1 + a1²`, has no `X` component. Hence
205            /// `a⁻¹ = ((a0 + α·a1) + a1·X)·N⁻¹`.
206            // The independent definition of inversion, kept at every level and compared
207            // against in the tests even where `Field::try_inverse` takes a faster route.
208            #[allow(dead_code)]
209            #[inline]
210            fn reference_try_inverse(self) -> Option<Self> {
211                if self.0 == 0 {
212                    return None;
213                }
214                let (a0, a1) = self.split();
215                let norm = a0.square() + (a0 * a1).mul_alpha() + a1.square();
216                let norm_inv = norm
217                    .try_inverse()
218                    .expect("the norm of a nonzero element is nonzero");
219                if HAS_HARDWARE_CLMUL && Self::BITS == 128 {
220                    let (lo, hi) = crate::clmul::mul_pair_64(
221                        (a0 + a1.mul_alpha()).to_repr() as u64,
222                        a1.to_repr() as u64,
223                        norm_inv.to_repr() as u64,
224                    );
225                    return Some(Self::from_repr(lo as $repr | ((hi as $repr) << (Self::BITS / 2))));
226                }
227                Some(Self::join((a0 + a1.mul_alpha()) * norm_inv, a1 * norm_inv))
228            }
229
230            /// Construct a field element from its little-endian byte representation.
231            ///
232            /// Every byte string of the right length is a valid input: `from_repr` masks
233            /// any bits above the canonical range.
234            #[inline]
235            pub fn from_le_bytes(bytes: [u8; core::mem::size_of::<$repr>()]) -> Self {
236                <Self as TowerLevel>::from_repr(<$repr>::from_le_bytes(bytes))
237            }
238        }
239
240        impl private::Sealed for $name {}
241
242        impl TowerLevel for $name {
243            type Repr = $repr;
244
245            const LOG_BITS: usize = Self::BITS.trailing_zeros() as usize;
246
247            #[inline]
248            fn from_repr(r: Self::Repr) -> Self {
249                Self(r & Self::MASK)
250            }
251
252            #[inline]
253            fn to_repr(self) -> Self::Repr {
254                self.0
255            }
256
257            /// `X·(c0 + c1·X) = c1 + (c0 + α·c1)·X`, using `X² = αX + 1`.
258            #[inline]
259            fn mul_alpha(self) -> Self {
260                let (c0, c1) = self.split();
261                Self::join(c1, c0 + c1.mul_alpha())
262            }
263
264            #[inline]
265            fn from_le_byte_iter(mut bytes: impl Iterator<Item = u8>) -> Self {
266                let mut buffer = [0u8; core::mem::size_of::<$repr>()];
267                for byte in &mut buffer {
268                    *byte = bytes.next().expect(BYTE_STREAM_ENDED);
269                }
270                Self::from_le_bytes(buffer)
271            }
272
273            #[inline]
274            fn cantor_basis(i: usize) -> Self {
275                assert!(i < $bits, "Cantor basis index out of range");
276                // `v_i < 2^(2^k)` for `i < 2^k`, so the cast is exact at every level.
277                Self::from_repr(crate::cantor::CANTOR_BASIS_128[i] as $repr)
278            }
279        }
280
281        impl<'de> Deserialize<'de> for $name {
282            fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
283                let val = <$repr>::deserialize(d)?;
284                // Reject non-canonical encodings so a proof cannot be re-encoded without the
285                // witness. Only the low `BITS` bits of the backing integer may be set.
286                if val <= Self::MASK {
287                    Ok(Self(val))
288                } else {
289                    Err(D::Error::custom("Value is out of range"))
290                }
291            }
292        }
293
294        impl Packable for $name {}
295
296        impl Display for $name {
297            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
298                Display::fmt(&self.0, f)
299            }
300        }
301
302        impl Debug for $name {
303            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
304                Debug::fmt(&self.0, f)
305            }
306        }
307
308        impl Distribution<$name> for StandardUniform {
309            #[inline]
310            fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $name {
311                let mut bytes = [0u8; core::mem::size_of::<$repr>()];
312                rng.fill_bytes(&mut bytes);
313                <$name>::from_repr(<$repr>::from_le_bytes(bytes))
314            }
315        }
316
317        impl PrimeCharacteristicRing for $name {
318            type PrimeSubfield = Gf2;
319
320            const ZERO: Self = Self(0);
321            const ONE: Self = Self(1);
322            // The characteristic is 2, so `TWO = ONE + ONE = ZERO`.
323            const TWO: Self = Self(0);
324            // The characteristic is 2, so `NEG_ONE = ONE`.
325            const NEG_ONE: Self = Self(1);
326
327            #[inline]
328            fn from_prime_subfield(f: Self::PrimeSubfield) -> Self {
329                Self::from_bool(f.is_one())
330            }
331
332            #[inline]
333            fn from_bool(b: bool) -> Self {
334                Self(<$repr>::from(b))
335            }
336
337            characteristic_two_methods!();
338
339            #[inline]
340            fn square(&self) -> Self {
341                if Self::BITS >= 16 {
342                    Self::from_repr(match Self::BITS {
343                        16 => crate::linear::square_16(self.0 as u16) as $repr,
344                        32 => BinaryField32::from_repr(self.0 as u32).byte_square().to_repr() as $repr,
345                        64 => crate::linear::square_64(self.0 as u64) as $repr,
346                        128 => crate::linear::square_128(self.0 as u128) as $repr,
347                        _ => unreachable!(),
348                    })
349                } else {
350                    self.$square()
351                }
352            }
353
354            #[inline]
355            fn exp_power_of_2(&self, power_log: usize) -> Self {
356                let mut power = power_log % Self::BITS;
357                let mut value = *self;
358                // The nontrivial quadratic automorphism is X -> X + alpha.
359                if power >= Self::BITS / 2 {
360                    let (lo, hi) = value.split();
361                    value = Self::join(lo + hi.mul_alpha(), hi);
362                    power -= Self::BITS / 2;
363                }
364                if power == 1 {
365                    return value.square();
366                }
367                if Self::BITS >= 16 {
368                    Self::from_repr(match Self::BITS {
369                        16 => crate::linear::frobenius_16(value.0 as u16, power) as $repr,
370                        32 => crate::linear::frobenius_32(value.0 as u32, power) as $repr,
371                        64 => crate::linear::frobenius_64(value.0 as u64, power) as $repr,
372                        128 => crate::linear::frobenius_128(value.0 as u128, power) as $repr,
373                        _ => unreachable!(),
374                    })
375                } else {
376                    for _ in 0..power { value = value.square(); }
377                    value
378                }
379            }
380
381            #[inline]
382            fn dot_product<const N: usize>(u: &[Self; N], v: &[Self; N]) -> Self {
383                if N == 0 { return Self::ZERO; }
384                if N == 1 { return u[0] * v[0]; }
385                if HAS_HARDWARE_CLMUL && Self::BITS == 32 {
386                    Self::from_repr(crate::clmul::dot_product_32(
387                        u.iter().zip(v).map(|(a, b)| (a.0 as u32, b.0 as u32)),
388                    ) as $repr)
389                } else if HAS_HARDWARE_CLMUL && Self::BITS == 64 {
390                    Self::from_repr(crate::clmul::dot_product_64(
391                        u.iter().zip(v).map(|(a, b)| (a.0 as u64, b.0 as u64)),
392                    ) as $repr)
393                } else if HAS_HARDWARE_CLMUL && Self::BITS == 128 {
394                    Self::from_repr(crate::clmul::dot_product_128(
395                        u.iter().zip(v).map(|(a, b)| (a.0 as u128, b.0 as u128)),
396                    ) as $repr)
397                } else {
398                    u.iter().zip(v).map(|(&a, &b)| a * b).sum()
399                }
400            }
401
402            #[inline]
403            fn zero_vec(len: usize) -> Vec<Self> {
404                let mut values = ManuallyDrop::new(alloc::vec![0 as $repr; len]);
405                // SAFETY: the transparent wrapper has exactly the integer's layout, and
406                // zero is canonical. The allocation retains its original size and alignment.
407                unsafe {
408                    Vec::from_raw_parts(values.as_mut_ptr().cast(), values.len(), values.capacity())
409                }
410            }
411
412            /// `x·(x - 1) = x² - x = x² + x` in characteristic 2, and squaring is a linear
413            /// map here, so this avoids the tower/polynomial basis changes a general product
414            /// pays for.
415            #[inline]
416            fn bool_check(&self) -> Self {
417                self.square() + *self
418            }
419        }
420
421        impl Field for $name {
422            type Packing = Self;
423
424            const GENERATOR: Self = Self($generator);
425
426            #[inline]
427            fn try_inverse(&self) -> Option<Self> {
428                self.$try_inverse()
429            }
430
431            #[inline]
432            fn try_sqrt(&self) -> Option<Self> {
433                // Squaring is the Frobenius, of order `BITS`, so `a^(2^(BITS - 1))` squares to `a`.
434                if Self::BITS >= 16 {
435                    Some(Self::from_repr(match Self::BITS {
436                        16 => crate::linear::sqrt_16(self.0 as u16) as $repr,
437                        32 => crate::linear::sqrt_32(self.0 as u32) as $repr,
438                        64 => crate::linear::sqrt_64(self.0 as u64) as $repr,
439                        128 => crate::linear::sqrt_128(self.0 as u128) as $repr,
440                        _ => unreachable!(),
441                    }))
442                } else {
443                    Some(self.exp_power_of_2(Self::BITS - 1))
444                }
445            }
446
447            #[inline]
448            fn order() -> BigUint {
449                BigUint::from(1u8) << (1usize << <Self as TowerLevel>::LOG_BITS)
450            }
451
452            /// The enumeration by bit pattern: `interpolation_node(i)` is the element whose
453            /// coefficients over `GF(2)` are the bits of `i`. It is injective for `i < 2^BITS`.
454            ///
455            /// # Panics
456            /// Panics if `i >= 2^BITS`. `from_repr` masks, so an out-of-range index would
457            /// otherwise alias an earlier node in release builds and break an interpolation
458            /// argument silently; the check is paid once per node at setup, never in a loop.
459            #[inline]
460            fn interpolation_node(i: usize) -> Self {
461                assert!(
462                    usize::BITS as usize <= Self::BITS || i < (1usize << Self::BITS),
463                    "interpolation node index out of range"
464                );
465                Self::from_repr(i as $repr)
466            }
467
468            /// An element of `GF(2^n)` is exactly `n` bits wide.
469            #[inline]
470            fn bits() -> usize {
471                Self::BITS
472            }
473        }
474
475        impl RawDataSerializable for $name {
476            const NUM_BYTES: usize = core::mem::size_of::<$repr>();
477
478            #[allow(refining_impl_trait)]
479            #[inline]
480            fn into_bytes(self) -> [u8; core::mem::size_of::<$repr>()] {
481                self.0.to_le_bytes()
482            }
483
484            #[inline]
485            fn into_parallel_byte_streams<const N: usize>(
486                input: impl IntoIterator<Item = [Self; N]>,
487            ) -> impl IntoIterator<Item = [u8; N]> {
488                input.into_iter().flat_map(|vector| {
489                    let bytes = vector.map(Self::into_bytes);
490                    (0..Self::NUM_BYTES).map(move |i| core::array::from_fn(|j| bytes[j][i]))
491                })
492            }
493
494            #[inline]
495            fn into_u64_stream(input: impl IntoIterator<Item = Self>) -> impl IntoIterator<Item = u64> {
496                Self::into_parallel_u64_streams(input.into_iter().map(|elem| [elem]))
497                    .into_iter()
498                    .map(|[word]| word)
499            }
500
501            #[inline]
502            fn into_parallel_u64_streams<const N: usize>(
503                input: impl IntoIterator<Item = [Self; N]>,
504            ) -> impl IntoIterator<Item = [u64; N]> {
505                // A backing integer of at least 64 bits fills one or two whole words, low word
506                // first. Narrower backing integers pack little-endian into one word, zero-padded
507                // at the end.
508                let mut input = input.into_iter();
509                let mut high: Option<[u64; N]> = None;
510                core::iter::from_fn(move || {
511                    if let Some(word) = high.take() {
512                        return Some(word);
513                    }
514                    let first = input.next()?;
515                    if Self::NUM_BYTES >= 8 {
516                        let wide = first.map(|elem| elem.0 as u128);
517                        if Self::NUM_BYTES == 16 {
518                            high = Some(wide.map(|value| (value >> 64) as u64));
519                        }
520                        return Some(wide.map(|value| value as u64));
521                    }
522                    let bits = 8 * Self::NUM_BYTES;
523                    let mut word = first.map(|elem| elem.0 as u64);
524                    let mut shift = bits;
525                    while shift < 64 {
526                        let Some(next) = input.next() else { break };
527                        for (lane, elem) in word.iter_mut().zip(next) {
528                            *lane |= (elem.0 as u64) << shift;
529                        }
530                        shift += bits;
531                    }
532                    Some(word)
533                })
534            }
535        }
536
537        impl Add for $name {
538            type Output = Self;
539
540            #[inline]
541            #[allow(clippy::suspicious_arithmetic_impl)]
542            fn add(self, rhs: Self) -> Self {
543                // Addition in characteristic 2 is `XOR`.
544                Self(self.0 ^ rhs.0)
545            }
546        }
547
548        impl Sub for $name {
549            type Output = Self;
550
551            #[inline]
552            #[allow(clippy::suspicious_arithmetic_impl)]
553            fn sub(self, rhs: Self) -> Self {
554                // Subtraction coincides with addition in characteristic 2.
555                self + rhs
556            }
557        }
558
559        impl Neg for $name {
560            type Output = Self;
561
562            #[inline]
563            fn neg(self) -> Self::Output {
564                // `-x = x` in characteristic 2.
565                self
566            }
567        }
568
569        impl Mul for $name {
570            type Output = Self;
571
572            #[inline]
573            fn mul(self, rhs: Self) -> Self {
574                self.$mul(rhs)
575            }
576        }
577
578        impl_add_assign!($name);
579        impl_sub_assign!($name);
580        impl_mul_methods!($name);
581        impl_div_methods!($name, $name);
582        ring_sum!($name);
583
584        impl From<Gf2> for $name {
585            /// `GF(2)` is the prime subfield of every level, embedded as `{ZERO, ONE}`.
586            #[inline]
587            fn from(x: Gf2) -> Self {
588                Self::from_prime_subfield(x)
589            }
590        }
591
592        impl_add_base_field!($name, Gf2);
593        impl_sub_base_field!($name, Gf2);
594        impl Mul<Gf2> for $name {
595            type Output = Self;
596
597            #[inline]
598            #[allow(clippy::suspicious_arithmetic_impl)]
599            fn mul(self, rhs: Gf2) -> Self {
600                Self(self.0 & (0 as $repr).wrapping_sub(rhs.to_repr() as $repr))
601            }
602        }
603
604        impl Mul<$name> for Gf2 {
605            type Output = $name;
606
607            #[inline]
608            fn mul(self, rhs: $name) -> $name {
609                rhs * self
610            }
611        }
612
613        impl Algebra<Gf2> for $name {}
614    };
615}
616
617binary_tower_level!(
618    BinaryField2,
619    2,
620    u8,
621    Gf2,
622    u8,
623    2,
624    reference_mul,
625    reference_square,
626    reference_try_inverse
627);
628binary_tower_level!(
629    BinaryField4,
630    4,
631    u8,
632    BinaryField2,
633    u8,
634    5,
635    reference_mul,
636    reference_square,
637    reference_try_inverse
638);
639binary_tower_level!(
640    BinaryField8,
641    8,
642    u8,
643    BinaryField4,
644    u8,
645    19,
646    table_mul,
647    table_square,
648    table_try_inverse
649);
650binary_tower_level!(
651    BinaryField16,
652    16,
653    u16,
654    BinaryField8,
655    u8,
656    258,
657    karatsuba_mul,
658    reference_square,
659    reference_try_inverse
660);
661binary_tower_level!(
662    BinaryField32,
663    32,
664    u32,
665    BinaryField16,
666    u16,
667    65541,
668    karatsuba_mul,
669    reference_square,
670    reference_try_inverse
671);
672binary_tower_level!(
673    BinaryField64,
674    64,
675    u64,
676    BinaryField32,
677    u32,
678    4294967300,
679    dispatched_mul,
680    table_square,
681    reference_try_inverse
682);
683binary_tower_level!(
684    BinaryField128,
685    128,
686    u128,
687    BinaryField64,
688    u64,
689    18446744073709551621,
690    dispatched_mul,
691    table_square,
692    reference_try_inverse
693);
694
695impl BinaryField8 {
696    /// Multiplication through the `GF(2^8)` log and exponential tables.
697    #[inline]
698    const fn table_mul(self, rhs: Self) -> Self {
699        Self(tables::mul(self.0, rhs.0))
700    }
701
702    /// Squaring through the direct `GF(2^8)` table.
703    #[inline]
704    const fn table_square(self) -> Self {
705        Self(tables::square(self.0))
706    }
707
708    /// Inversion through the direct `GF(2^8)` table.
709    #[inline]
710    const fn table_try_inverse(self) -> Option<Self> {
711        match tables::try_inverse(self.0) {
712            Some(inverse) => Some(Self(inverse)),
713            None => None,
714        }
715    }
716}
717
718impl BinaryField32 {
719    /// Square the two quadratic levels above GF256 using its compact byte table.
720    #[inline]
721    fn byte_square(self) -> Self {
722        let (a0, a1) = self.split();
723        let a0_sq = a0.reference_square();
724        let a1_sq = a1.reference_square();
725        Self::join(a0_sq + a1_sq, a1_sq.mul_alpha())
726    }
727}
728
729/// Give a level Karatsuba multiplication over the `Mul` of the level below.
730///
731/// The recurrence is the one [`binary_tower_level`] documents on `reference_mul`, but the
732/// coefficient products go through the level below's operator, so the recursion stops as soon
733/// as it reaches a level with a fast path instead of running to the bottom of the tower.
734macro_rules! karatsuba_over_the_level_below {
735    ($name:ident) => {
736        impl $name {
737            /// Karatsuba multiplication modulo `X² = αX + 1`.
738            ///
739            /// With `z0 = a0·b0`, `z2 = a1·b1` and `z1 = a0·b1 + a1·b0`,
740            /// `a·b = (z0 + z2) + (z1 + α·z2)·X`.
741            #[inline]
742            fn karatsuba_mul(self, rhs: Self) -> Self {
743                let (a0, a1) = self.split();
744                let (b0, b1) = rhs.split();
745                let z0 = a0 * b0;
746                let z2 = a1 * b1;
747                let z1 = (a0 + a1) * (b0 + b1) + z0 + z2;
748                Self::join(z0 + z2, z1 + z2.mul_alpha())
749            }
750        }
751    };
752}
753
754karatsuba_over_the_level_below!(BinaryField16);
755karatsuba_over_the_level_below!(BinaryField32);
756karatsuba_over_the_level_below!(BinaryField64);
757karatsuba_over_the_level_below!(BinaryField128);
758
759impl BinaryField64 {
760    /// The carryless-multiply fast path where the target has the instruction for it, and the
761    /// recursive tower multiplication otherwise.
762    ///
763    /// [`HAS_HARDWARE_CLMUL`] is a constant, so only the chosen arm survives compilation.
764    #[inline]
765    fn dispatched_mul(self, rhs: Self) -> Self {
766        if HAS_HARDWARE_CLMUL {
767            Self(mul_64(self.0, rhs.0))
768        } else {
769            self.karatsuba_mul(rhs)
770        }
771    }
772
773    /// Squaring through the tower-basis matrix, which is a lookup table on every target.
774    #[inline]
775    fn table_square(self) -> Self {
776        Self(crate::clmul::square_64(self.0))
777    }
778}
779
780impl BinaryField128 {
781    /// The carryless-multiply fast path where the target has the instruction for it, and the
782    /// recursive tower multiplication otherwise.
783    ///
784    /// [`HAS_HARDWARE_CLMUL`] is a constant, so only the chosen arm survives compilation.
785    #[inline]
786    fn dispatched_mul(self, rhs: Self) -> Self {
787        if HAS_HARDWARE_CLMUL {
788            Self(mul_128(self.0, rhs.0))
789        } else {
790            self.karatsuba_mul(rhs)
791        }
792    }
793
794    /// Squaring through the tower-basis matrix, which is a lookup table on every target.
795    #[inline]
796    fn table_square(self) -> Self {
797        Self(crate::clmul::square_128(self.0))
798    }
799}
800
801#[cfg(test)]
802mod tests {
803    extern crate std;
804
805    use std::println;
806    use std::vec::Vec;
807
808    use p3_field::{Field, PrimeCharacteristicRing, RawDataSerializable};
809    use proptest::prelude::*;
810
811    use super::*;
812
813    #[test]
814    fn zero_vectors_preserve_layout_and_support_growth() {
815        macro_rules! check {
816            ($field:ty) => {
817                for len in [0, 1, 33, 1024] {
818                    let mut values = <$field>::zero_vec(len);
819                    assert_eq!(values.len(), len);
820                    assert!(values.iter().all(|x| *x == <$field>::ZERO));
821                    values.push(<$field>::ONE);
822                    values.reserve(100);
823                    assert_eq!(values.pop(), Some(<$field>::ONE));
824                }
825            };
826        }
827        check!(BinaryField2);
828        check!(BinaryField4);
829        check!(BinaryField8);
830        check!(BinaryField16);
831        check!(BinaryField32);
832        check!(BinaryField64);
833        check!(BinaryField128);
834    }
835
836    #[test]
837    fn fused_dot_products_match_reference_for_arbitrary_lengths() {
838        fn check<const N: usize>() {
839            let u: [BinaryField128; N] = core::array::from_fn(|i| {
840                BinaryField128::from_repr(
841                    (i as u128 + 1).wrapping_mul(0xfeed_dead_beef_9876_0123_4567_cafe_dcba),
842                )
843            });
844            let v = core::array::from_fn(|i| u[N - 1 - i] + BinaryField128::ONE);
845            let expected = u
846                .iter()
847                .zip(&v)
848                .map(|(&a, &b)| a.reference_mul(b))
849                .sum::<BinaryField128>();
850            assert_eq!(BinaryField128::dot_product(&u, &v), expected);
851            let u32 = u.map(|x| BinaryField32::from_repr(x.to_repr() as u32));
852            let v32 = v.map(|x| BinaryField32::from_repr(x.to_repr() as u32));
853            assert_eq!(
854                BinaryField32::dot_product(&u32, &v32),
855                u32.iter()
856                    .zip(&v32)
857                    .map(|(&a, &b)| a.reference_mul(b))
858                    .sum()
859            );
860            let u = u.map(|x| BinaryField64::from_repr(x.to_repr() as u64));
861            let v = v.map(|x| BinaryField64::from_repr(x.to_repr() as u64));
862            assert_eq!(
863                BinaryField64::dot_product(&u, &v),
864                u.iter().zip(&v).map(|(&a, &b)| a.reference_mul(b)).sum()
865            );
866        }
867        check::<0>();
868        check::<1>();
869        check::<2>();
870        check::<3>();
871        check::<7>();
872        check::<16>();
873        check::<33>();
874        check::<128>();
875    }
876
877    #[test]
878    fn prime_subfield_scaling_is_selection() {
879        macro_rules! check {
880            ($field:ty, $value:expr) => {{
881                let x = <$field>::from_repr($value);
882                assert_eq!(x * Gf2::ZERO, <$field>::ZERO);
883                assert_eq!(Gf2::ZERO * x, <$field>::ZERO);
884                assert_eq!(x * Gf2::ONE, x);
885                assert_eq!(Gf2::ONE * x, x);
886            }};
887        }
888        check!(BinaryField2, 3);
889        check!(BinaryField4, 15);
890        check!(BinaryField8, 255);
891        check!(BinaryField16, 0xdead);
892        check!(BinaryField32, 0xdead_beef);
893        check!(BinaryField64, 0xdead_beef_cafe_8765);
894        check!(BinaryField128, 0xdead_beef_cafe_8765_0123_4567_89ab_cdef);
895    }
896
897    /// The prime factors of `2^n − 1` for each level `n` of the tower.
898    const FACTORS_2: [u128; 1] = [3];
899    const FACTORS_4: [u128; 2] = [3, 5];
900    const FACTORS_8: [u128; 3] = [3, 5, 17];
901    const FACTORS_16: [u128; 4] = [3, 5, 17, 257];
902    const FACTORS_32: [u128; 5] = [3, 5, 17, 257, 65537];
903    const FACTORS_64: [u128; 7] = [3, 5, 17, 257, 641, 65537, 6700417];
904    const FACTORS_128: [u128; 9] = [3, 5, 17, 257, 641, 65537, 274177, 6700417, 67280421310721];
905
906    /// The order `2^bits − 1` of the multiplicative group of `GF(2^bits)`.
907    const fn group_order(bits: u32) -> u128 {
908        if bits == 128 {
909            u128::MAX
910        } else {
911            (1u128 << bits) - 1
912        }
913    }
914
915    /// `base^exp`, with an exponent too large for [`PrimeCharacteristicRing::exp_u64`].
916    fn pow_u128<F: Field>(base: F, mut exp: u128) -> F {
917        let mut acc = F::ONE;
918        let mut cur = base;
919        while exp != 0 {
920            if exp & 1 == 1 {
921                acc *= cur;
922            }
923            cur = cur.square();
924            exp >>= 1;
925        }
926        acc
927    }
928
929    /// Whether `g` generates the whole multiplicative group of `GF(2^bits)`.
930    ///
931    /// `g` has full order exactly when `g^((2^bits − 1)/q) != 1` for every prime `q`
932    /// dividing `2^bits − 1`.
933    fn has_full_order<F: Field>(g: F, bits: u32, factors: &[u128]) -> bool {
934        let order = group_order(bits);
935        factors.iter().all(|&q| pow_u128(g, order / q) != F::ONE)
936    }
937
938    macro_rules! assert_full_order {
939        ($t:ty, $bits:expr, $factors:expr) => {
940            assert!(
941                has_full_order(<$t>::GENERATOR, $bits, &$factors),
942                concat!(
943                    stringify!($t),
944                    "::GENERATOR does not generate the multiplicative group"
945                )
946            );
947        };
948    }
949
950    macro_rules! assert_defining_relation {
951        ($t:ty, $repr:ty, $bits:expr) => {{
952            // `X` is the generator of this level over the one below (bit `bits/2`) and
953            // `alpha` the generator of the level below over the one beneath it (bit `bits/4`),
954            // which is `1` at the bottom of the tower.
955            let x = <$t>::from_repr((1 as $repr) << ($bits / 2));
956            let alpha = <$t>::from_repr((1 as $repr) << ($bits / 4));
957            assert_eq!(
958                x.square(),
959                alpha * x + <$t>::ONE,
960                concat!(stringify!($t), " does not satisfy X^2 = alpha*X + 1")
961            );
962        }};
963    }
964
965    macro_rules! search_generator {
966        ($t:ty, $repr:ty, $bits:expr, $factors:expr) => {{
967            // A bit pattern below `2^(bits/2)` has a zero coefficient on `X` and so lies in the
968            // proper subfield `GF(2^(bits/2))`; the smallest generator is above that.
969            let start = 1u128 << ($bits / 2);
970            let found = (start..start + 1024)
971                .map(|cand| (cand, <$t>::from_repr(cand as $repr)))
972                .find(|&(_, g)| has_full_order(g, $bits, &$factors));
973            println!(
974                "{}: GENERATOR = {:?}",
975                stringify!($t),
976                found.map(|(cand, _)| cand)
977            );
978        }};
979    }
980
981    #[test]
982    fn gf4_multiplication_table() {
983        // Elements of GF(4) = GF(2)[X]/(X^2 + X + 1) as bit patterns: 0, 1, X = 2, X + 1 = 3.
984        let x = BinaryField2::from_repr(2);
985        assert_eq!(x * x, x + BinaryField2::ONE); // X^2 = X + 1
986        assert_eq!(x * (x + BinaryField2::ONE), BinaryField2::ONE); // X(X + 1) = 1
987        assert_eq!(x.inverse(), x + BinaryField2::ONE);
988    }
989
990    #[test]
991    fn frobenius_fixes_every_element_of_each_level() {
992        for r in 0..=u8::MAX {
993            let a = BinaryField8::from_repr(r);
994            assert_eq!(a.exp_power_of_2(8), a); // a^(2^8) = a
995        }
996        for r in 0..=u8::MAX {
997            let a = BinaryField4::from_repr(r & 0x0f);
998            assert_eq!(a.exp_power_of_2(4), a); // a^(2^4) = a
999        }
1000    }
1001
1002    /// The table squaring at `GF(2^8)` must reproduce the recursion that runs to the bottom of
1003    /// the tower.
1004    #[test]
1005    fn the_table_square_agrees_with_the_recursive_squaring_on_gf256() {
1006        for r in 0..=u8::MAX {
1007            let a = BinaryField8::from_repr(r);
1008            assert_eq!(a.table_square(), a.reference_square(), "square({r})");
1009        }
1010    }
1011
1012    /// The table inversion at `GF(2^8)` must reproduce the recursion through the norm, which
1013    /// is the definition of the inverse in this tower.
1014    #[test]
1015    fn the_table_inverse_agrees_with_the_recursive_inverse_on_gf256() {
1016        for r in 0..=u8::MAX {
1017            let a = BinaryField8::from_repr(r);
1018            assert_eq!(
1019                a.table_try_inverse(),
1020                a.reference_try_inverse(),
1021                "inverse({r})"
1022            );
1023        }
1024    }
1025
1026    /// Karatsuba over the level below's operator must reproduce the recursion that runs to the
1027    /// bottom of the tower, over every `GF(2^16)` left operand.
1028    #[test]
1029    fn karatsuba_agrees_with_the_recursive_product_over_every_gf16_operand() {
1030        let others = [0u16, 1, 2, 0x00ff, 0x0100, 0x1234, 0xfffe, 0xffff];
1031        for r in 0..=u16::MAX {
1032            let a = BinaryField16::from_repr(r);
1033            for other in others {
1034                let b = BinaryField16::from_repr(other);
1035                assert_eq!(a.karatsuba_mul(b), a.reference_mul(b), "mul({r}, {other})");
1036            }
1037        }
1038    }
1039
1040    #[test]
1041    fn inverse_agrees_with_fermat_on_gf256() {
1042        for r in 1..=u8::MAX {
1043            let a = BinaryField8::from_repr(r);
1044            assert_eq!(a.inverse(), a.exp_u64(254));
1045            assert_eq!(a * a.inverse(), BinaryField8::ONE);
1046        }
1047    }
1048
1049    #[test]
1050    fn square_roots_square_back_to_the_input() {
1051        for r in 0..=u8::MAX {
1052            let a = BinaryField8::from_repr(r);
1053            assert_eq!(a.try_sqrt().unwrap().square(), a);
1054        }
1055        let a = BinaryField128::from_repr(0x0123_4567_89ab_cdef_fedc_ba98_7654_3210);
1056        assert_eq!(a.try_sqrt().unwrap().square(), a);
1057    }
1058
1059    /// The sub-byte levels store fewer bits than their backing integer holds, so a decoder that
1060    /// accepted any byte could build an element whose high bits are set. Such a value compares
1061    /// and hashes differently from the canonical representative of the same field element.
1062    #[test]
1063    fn serde_round_trip_rejects_non_canonical_encodings() {
1064        assert_eq!(
1065            serde_json::to_string(&BinaryField4::from_repr(9)).unwrap(),
1066            "9"
1067        );
1068        assert_eq!(
1069            serde_json::from_str::<BinaryField4>("9").unwrap(),
1070            BinaryField4::from_repr(9)
1071        );
1072
1073        // `GF(4)` uses 2 bits and `GF(16)` 4 bits of their `u8`; the rest must be rejected,
1074        // not silently truncated into range.
1075        assert!(serde_json::from_str::<BinaryField2>("3").is_ok());
1076        assert!(serde_json::from_str::<BinaryField2>("4").is_err());
1077        assert!(serde_json::from_str::<BinaryField4>("15").is_ok());
1078        assert!(serde_json::from_str::<BinaryField4>("16").is_err());
1079
1080        // The levels that fill their backing integer accept every value of it.
1081        assert!(serde_json::from_str::<BinaryField8>("255").is_ok());
1082        assert!(serde_json::from_str::<BinaryField8>("256").is_err());
1083    }
1084
1085    #[test]
1086    fn bytes_round_trip_and_postcard() {
1087        let a = BinaryField128::from_repr(0x8000_0000_0000_0000_0000_0000_0000_0001);
1088        let bytes: Vec<u8> = a.into_bytes().into_iter().collect();
1089        assert_eq!(bytes.len(), 16);
1090        assert_eq!(BinaryField128::from_le_bytes(bytes.try_into().unwrap()), a);
1091
1092        let encoded = postcard::to_allocvec(&a).unwrap();
1093        assert_eq!(postcard::from_bytes::<BinaryField128>(&encoded).unwrap(), a);
1094    }
1095
1096    /// Every byte string of the right length round-trips to a field element for every level,
1097    /// since [`RawDataSerializable::into_bytes`] and `from_le_bytes` are inverses on the full
1098    /// `NUM_BYTES`-byte space, not just on canonical representatives.
1099    #[test]
1100    fn from_le_bytes_round_trips_every_level() {
1101        macro_rules! assert_bytes_round_trip {
1102            ($t:ty, $repr:ty, $val:expr) => {{
1103                let a = <$t>::from_repr($val as $repr);
1104                let bytes: Vec<u8> = a.into_bytes().into_iter().collect();
1105                assert_eq!(bytes.len(), core::mem::size_of::<$repr>());
1106                assert_eq!(<$t>::from_le_bytes(bytes.try_into().unwrap()), a);
1107            }};
1108        }
1109
1110        assert_bytes_round_trip!(BinaryField2, u8, 0b11);
1111        assert_bytes_round_trip!(BinaryField4, u8, 0b1001);
1112        assert_bytes_round_trip!(BinaryField8, u8, 0xab);
1113        assert_bytes_round_trip!(BinaryField16, u16, 0x1234);
1114        assert_bytes_round_trip!(BinaryField32, u32, 0x1234_5678);
1115        assert_bytes_round_trip!(BinaryField64, u64, 0x0123_4567_89ab_cdef);
1116        assert_bytes_round_trip!(
1117            BinaryField128,
1118            u128,
1119            0x8000_0000_0000_0000_0000_0000_0000_0001
1120        );
1121    }
1122
1123    /// `from_le_bytes` must be total: every byte string of the right length is a valid
1124    /// element, not just the ones a masked-already `from_repr` call would ever feed it. The
1125    /// sub-byte levels store fewer bits than their `u8` backing integer holds, so a decoder
1126    /// that skipped masking could construct a value whose high bits are set and diverge from
1127    /// the canonical representative of the same field element.
1128    #[test]
1129    fn from_le_bytes_masks_out_of_range_high_bits() {
1130        assert_eq!(
1131            BinaryField2::from_le_bytes([0xff]),
1132            BinaryField2::from_repr(0b11)
1133        );
1134        assert_eq!(
1135            BinaryField2::from_le_bytes([0b1010_0110]),
1136            BinaryField2::from_repr(0b10)
1137        );
1138        assert_eq!(
1139            BinaryField4::from_le_bytes([0xff]),
1140            BinaryField4::from_repr(0b1111)
1141        );
1142        assert_eq!(
1143            BinaryField4::from_le_bytes([0b1010_0111]),
1144            BinaryField4::from_repr(0b0111)
1145        );
1146    }
1147
1148    /// `from_le_byte_iter` reads exactly `NUM_BYTES` bytes off the front of the stream and
1149    /// agrees with `from_le_bytes` on them, leaving the rest for the next element.
1150    #[test]
1151    fn from_le_byte_iter_consumes_one_element_worth_of_bytes() {
1152        macro_rules! assert_reads_one_element {
1153            ($t:ty, $repr:ty) => {{
1154                let width = core::mem::size_of::<$repr>();
1155                let stream: Vec<u8> = (0..2 * width as u8).map(|i| i.wrapping_mul(37)).collect();
1156
1157                let mut iter = stream.iter().copied();
1158                let first = <$t as TowerLevel>::from_le_byte_iter(&mut iter);
1159                let second = <$t as TowerLevel>::from_le_byte_iter(&mut iter);
1160
1161                assert_eq!(iter.next(), None, "the stream must be fully consumed");
1162                assert_eq!(
1163                    first,
1164                    <$t>::from_le_bytes(stream[..width].try_into().unwrap())
1165                );
1166                assert_eq!(
1167                    second,
1168                    <$t>::from_le_bytes(stream[width..].try_into().unwrap())
1169                );
1170            }};
1171        }
1172
1173        assert_reads_one_element!(Gf2, u8);
1174        assert_reads_one_element!(BinaryField2, u8);
1175        assert_reads_one_element!(BinaryField4, u8);
1176        assert_reads_one_element!(BinaryField8, u8);
1177        assert_reads_one_element!(BinaryField16, u16);
1178        assert_reads_one_element!(BinaryField32, u32);
1179        assert_reads_one_element!(BinaryField64, u64);
1180        assert_reads_one_element!(BinaryField128, u128);
1181    }
1182
1183    #[test]
1184    #[should_panic = "byte stream ended before a whole element was read"]
1185    fn from_le_byte_iter_rejects_a_truncated_stream() {
1186        let truncated = [0u8; 15];
1187        let _ = BinaryField128::from_le_byte_iter(truncated.into_iter());
1188    }
1189
1190    #[test]
1191    fn field_testing_into_stream_matches_every_level() {
1192        p3_field_testing::test_into_stream::<BinaryField2>();
1193        p3_field_testing::test_into_stream::<BinaryField4>();
1194        p3_field_testing::test_into_stream::<BinaryField8>();
1195        p3_field_testing::test_into_stream::<BinaryField16>();
1196        p3_field_testing::test_into_stream::<BinaryField32>();
1197        p3_field_testing::test_into_stream::<BinaryField64>();
1198        p3_field_testing::test_into_stream::<BinaryField128>();
1199    }
1200
1201    #[test]
1202    fn word_streams_zero_pad_a_partial_final_word_at_every_level() {
1203        // Reference: the little-endian byte stream, cut into words and zero-padded.
1204        fn words_of(bytes: &[u8]) -> Vec<u64> {
1205            bytes
1206                .chunks(8)
1207                .map(|chunk| {
1208                    let mut word = [0u8; 8];
1209                    word[..chunk.len()].copy_from_slice(chunk);
1210                    u64::from_le_bytes(word)
1211                })
1212                .collect()
1213        }
1214
1215        macro_rules! check {
1216            ($field:ty) => {
1217                for len in 0..=17 {
1218                    let lanes: Vec<[$field; 3]> = (0..len)
1219                        .map(|i| {
1220                            core::array::from_fn(|lane| {
1221                                <$field>::from_le_bytes(core::array::from_fn(|byte| {
1222                                    (i * 31 + lane * 7 + byte * 13 + 1) as u8
1223                                }))
1224                            })
1225                        })
1226                        .collect();
1227
1228                    let lane_words: [Vec<u64>; 3] = core::array::from_fn(|lane| {
1229                        let bytes: Vec<u8> = lanes
1230                            .iter()
1231                            .flat_map(|vector| vector[lane].into_bytes())
1232                            .collect();
1233                        words_of(&bytes)
1234                    });
1235
1236                    let scalar: Vec<u64> =
1237                        <$field>::into_u64_stream(lanes.iter().map(|vector| vector[0]))
1238                            .into_iter()
1239                            .collect();
1240                    assert_eq!(
1241                        scalar,
1242                        lane_words[0],
1243                        "{} scalar, len {len}",
1244                        stringify!($field)
1245                    );
1246
1247                    let parallel: Vec<[u64; 3]> =
1248                        <$field>::into_parallel_u64_streams(lanes.iter().copied())
1249                            .into_iter()
1250                            .collect();
1251                    let expected: Vec<[u64; 3]> = (0..lane_words[0].len())
1252                        .map(|word| core::array::from_fn(|lane| lane_words[lane][word]))
1253                        .collect();
1254                    assert_eq!(
1255                        parallel,
1256                        expected,
1257                        "{} parallel, len {len}",
1258                        stringify!($field)
1259                    );
1260                }
1261            };
1262        }
1263
1264        check!(BinaryField2);
1265        check!(BinaryField4);
1266        check!(BinaryField8);
1267        check!(BinaryField16);
1268        check!(BinaryField32);
1269        check!(BinaryField64);
1270        check!(BinaryField128);
1271    }
1272
1273    #[test]
1274    fn order_counts_the_elements_of_each_level() {
1275        assert_eq!(BinaryField2::order(), BigUint::from(4u32));
1276        assert_eq!(BinaryField4::order(), BigUint::from(16u32));
1277        assert_eq!(BinaryField8::order(), BigUint::from(256u32));
1278        assert_eq!(BinaryField16::order(), BigUint::from(65536u32));
1279        assert_eq!(BinaryField32::order(), BigUint::from(1u64 << 32));
1280        assert_eq!(BinaryField64::order(), BigUint::from(1u128 << 64));
1281        assert_eq!(BinaryField128::order(), BigUint::from(1u8) << 128usize);
1282    }
1283
1284    #[test]
1285    fn interpolation_nodes_are_basis_expansion() {
1286        assert_eq!(BinaryField128::interpolation_node(0), BinaryField128::ZERO);
1287        assert_eq!(BinaryField128::interpolation_node(1), BinaryField128::ONE);
1288        assert_eq!(
1289            BinaryField128::interpolation_node(2),
1290            BinaryField128::from_repr(2)
1291        );
1292        assert_eq!(
1293            BinaryField128::interpolation_node(5),
1294            BinaryField128::from_repr(5)
1295        );
1296    }
1297
1298    /// The last index a level can enumerate is `2^BITS - 1`; anything above it would be masked
1299    /// back onto an earlier node.
1300    #[test]
1301    fn interpolation_nodes_cover_the_whole_level() {
1302        assert_eq!(
1303            BinaryField4::interpolation_node(15),
1304            BinaryField4::from_repr(15)
1305        );
1306        assert_eq!(
1307            BinaryField8::interpolation_node(255),
1308            BinaryField8::from_repr(255)
1309        );
1310    }
1311
1312    #[test]
1313    #[should_panic = "interpolation node index out of range"]
1314    fn interpolation_node_rejects_an_index_beyond_the_level() {
1315        let _node = BinaryField8::interpolation_node(256);
1316    }
1317
1318    #[test]
1319    fn each_level_satisfies_the_tower_defining_relation() {
1320        assert_defining_relation!(BinaryField2, u8, 2);
1321        assert_defining_relation!(BinaryField4, u8, 4);
1322        assert_defining_relation!(BinaryField8, u8, 8);
1323        assert_defining_relation!(BinaryField16, u16, 16);
1324        assert_defining_relation!(BinaryField32, u32, 32);
1325        assert_defining_relation!(BinaryField64, u64, 64);
1326        assert_defining_relation!(BinaryField128, u128, 128);
1327    }
1328
1329    /// `GF(2)` is the prime subfield of the whole tower, so every level is a `GF(2)`-algebra:
1330    /// the embedding is a ring homomorphism and each mixed operator agrees with embedding first.
1331    #[test]
1332    fn every_level_is_an_algebra_over_gf2() {
1333        /// Statically require the full `Algebra<Gf2>` bound, not merely the operators.
1334        const fn assert_algebra_over_gf2<T: Algebra<Gf2>>() {}
1335
1336        macro_rules! assert_gf2_algebra {
1337            ($t:ty) => {{
1338                assert_algebra_over_gf2::<$t>();
1339
1340                assert_eq!(<$t>::from(Gf2::ZERO), <$t>::ZERO);
1341                assert_eq!(<$t>::from(Gf2::ONE), <$t>::ONE);
1342
1343                for x in [Gf2::ZERO, Gf2::ONE] {
1344                    for y in [Gf2::ZERO, Gf2::ONE] {
1345                        assert_eq!(<$t>::from(x + y), <$t>::from(x) + <$t>::from(y));
1346                        assert_eq!(<$t>::from(x * y), <$t>::from(x) * <$t>::from(y));
1347                    }
1348                }
1349
1350                for a in [
1351                    <$t>::ZERO,
1352                    <$t>::ONE,
1353                    <$t>::GENERATOR,
1354                    <$t>::GENERATOR.square(),
1355                ] {
1356                    for bit in [Gf2::ZERO, Gf2::ONE] {
1357                        let embedded = <$t>::from(bit);
1358
1359                        assert_eq!(a + bit, a + embedded);
1360                        assert_eq!(a - bit, a - embedded);
1361                        assert_eq!(a * bit, a * embedded);
1362                        assert_eq!(bit + a, embedded + a);
1363                        assert_eq!(bit - a, embedded - a);
1364                        assert_eq!(bit * a, embedded * a);
1365
1366                        let mut acc = a;
1367                        acc += bit;
1368                        assert_eq!(acc, a + embedded);
1369                        let mut acc = a;
1370                        acc -= bit;
1371                        assert_eq!(acc, a - embedded);
1372                        let mut acc = a;
1373                        acc *= bit;
1374                        assert_eq!(acc, a * embedded);
1375                    }
1376                }
1377            }};
1378        }
1379
1380        assert_gf2_algebra!(BinaryField2);
1381        assert_gf2_algebra!(BinaryField4);
1382        assert_gf2_algebra!(BinaryField8);
1383        assert_gf2_algebra!(BinaryField16);
1384        assert_gf2_algebra!(BinaryField32);
1385        assert_gf2_algebra!(BinaryField64);
1386        assert_gf2_algebra!(BinaryField128);
1387    }
1388
1389    #[test]
1390    fn generators_generate_the_multiplicative_group() {
1391        assert_full_order!(BinaryField2, 2, FACTORS_2);
1392        assert_full_order!(BinaryField4, 4, FACTORS_4);
1393        assert_full_order!(BinaryField8, 8, FACTORS_8);
1394        assert_full_order!(BinaryField16, 16, FACTORS_16);
1395        assert_full_order!(BinaryField32, 32, FACTORS_32);
1396        assert_full_order!(BinaryField64, 64, FACTORS_64);
1397        assert_full_order!(BinaryField128, 128, FACTORS_128);
1398    }
1399
1400    /// Scans for the smallest bit pattern generating each level's multiplicative group.
1401    ///
1402    /// The values it reports are pinned as the `GENERATOR` constants; run with
1403    /// `cargo test -p p3-binary-field --release -- --ignored --nocapture`.
1404    #[test]
1405    #[ignore = "one-off search used to pin the GENERATOR constants"]
1406    fn search_generators() {
1407        search_generator!(BinaryField2, u8, 2, FACTORS_2);
1408        search_generator!(BinaryField4, u8, 4, FACTORS_4);
1409        search_generator!(BinaryField8, u8, 8, FACTORS_8);
1410        search_generator!(BinaryField16, u16, 16, FACTORS_16);
1411        search_generator!(BinaryField32, u32, 32, FACTORS_32);
1412        search_generator!(BinaryField64, u64, 64, FACTORS_64);
1413        search_generator!(BinaryField128, u128, 128, FACTORS_128);
1414    }
1415
1416    fn bf128() -> impl Strategy<Value = BinaryField128> {
1417        any::<u128>().prop_map(BinaryField128::from_repr)
1418    }
1419
1420    fn bf64() -> impl Strategy<Value = BinaryField64> {
1421        any::<u64>().prop_map(BinaryField64::from_repr)
1422    }
1423
1424    fn bf32() -> impl Strategy<Value = BinaryField32> {
1425        any::<u32>().prop_map(BinaryField32::from_repr)
1426    }
1427
1428    fn bf16() -> impl Strategy<Value = BinaryField16> {
1429        any::<u16>().prop_map(BinaryField16::from_repr)
1430    }
1431
1432    fn bf8() -> impl Strategy<Value = BinaryField8> {
1433        any::<u8>().prop_map(BinaryField8::from_repr)
1434    }
1435
1436    fn bf4() -> impl Strategy<Value = BinaryField4> {
1437        any::<u8>().prop_map(BinaryField4::from_repr)
1438    }
1439
1440    fn bf2() -> impl Strategy<Value = BinaryField2> {
1441        any::<u8>().prop_map(BinaryField2::from_repr)
1442    }
1443
1444    #[test]
1445    fn bool_check_matches_the_vanishing_polynomial_at_zero_and_one() {
1446        macro_rules! check {
1447            ($field:ty) => {
1448                for x in [<$field>::ZERO, <$field>::ONE] {
1449                    assert_eq!(x.bool_check(), x * (x - <$field>::ONE));
1450                }
1451            };
1452        }
1453        check!(BinaryField2);
1454        check!(BinaryField4);
1455        check!(BinaryField8);
1456        check!(BinaryField16);
1457        check!(BinaryField32);
1458        check!(BinaryField64);
1459        check!(BinaryField128);
1460    }
1461
1462    proptest! {
1463        #![proptest_config(ProptestConfig::with_cases(1000))]
1464
1465        #[test]
1466        fn mul_is_commutative(a in bf128(), b in bf128()) {
1467            prop_assert_eq!(a * b, b * a);
1468        }
1469
1470        #[test]
1471        fn mul_is_associative(a in bf128(), b in bf128(), c in bf128()) {
1472            prop_assert_eq!((a * b) * c, a * (b * c));
1473        }
1474
1475        #[test]
1476        fn mul_distributes_over_addition(a in bf128(), b in bf128(), c in bf128()) {
1477            prop_assert_eq!(a * (b + c), a * b + a * c);
1478        }
1479
1480        #[test]
1481        fn nonzero_times_its_inverse_is_one(a in bf128()) {
1482            prop_assume!(a != BinaryField128::ZERO);
1483            prop_assert_eq!(a * a.inverse(), BinaryField128::ONE);
1484        }
1485
1486        /// The levels whose `square` dispatches must agree with the recursive definition.
1487        #[test]
1488        fn square_agrees_with_the_reference_squaring(a in bf128(), b in bf64()) {
1489            prop_assert_eq!(a.square(), a.reference_square());
1490            prop_assert_eq!(b.square(), b.reference_square());
1491        }
1492
1493        /// `reference_mul` recurses to the bottom of the tower without dispatching, so squaring
1494        /// through it is independent of every fast path.
1495        #[test]
1496        fn square_agrees_with_the_reference_product(a in bf128(), b in bf64(), c in any::<u32>()) {
1497            prop_assert_eq!(a.square(), a.reference_mul(a));
1498            prop_assert_eq!(b.square(), b.reference_mul(b));
1499            let c = BinaryField32::from_repr(c);
1500            prop_assert_eq!(c.square(), c.reference_mul(c));
1501        }
1502
1503        #[test]
1504        fn square_agrees_with_self_multiplication(a in bf128(), b in bf64()) {
1505            prop_assert_eq!(a.square(), a * a);
1506            prop_assert_eq!(b.square(), b * b);
1507        }
1508
1509        /// The levels whose `Mul` recurses through the level below's operator must agree with
1510        /// the recursion that runs to the bottom of the tower. At 64 and 128 bits that operator
1511        /// is only reached where there is no carryless-multiply instruction, so it is checked
1512        /// here on every target rather than only on the ones that dispatch to it.
1513        #[test]
1514        fn karatsuba_agrees_with_the_recursive_product(
1515            a in bf32(),
1516            b in bf32(),
1517            c in bf16(),
1518            d in bf16(),
1519            e in bf64(),
1520            f in bf64(),
1521            g in bf128(),
1522            h in bf128(),
1523        ) {
1524            prop_assert_eq!(a.karatsuba_mul(b), a.reference_mul(b));
1525            prop_assert_eq!(c.karatsuba_mul(d), c.reference_mul(d));
1526            prop_assert_eq!(e.karatsuba_mul(f), e.reference_mul(f));
1527            prop_assert_eq!(g.karatsuba_mul(h), g.reference_mul(h));
1528        }
1529
1530        /// `bool_check` must agree with the vanishing polynomial `x * (x - 1)` at every level,
1531        /// computed here through the ordinary `Mul` and `Sub` operators rather than the
1532        /// squaring shortcut `bool_check` itself takes.
1533        #[test]
1534        fn bool_check_agrees_with_the_vanishing_polynomial(
1535            a2 in bf2(),
1536            a4 in bf4(),
1537            a8 in bf8(),
1538            a16 in bf16(),
1539            a32 in bf32(),
1540            a64 in bf64(),
1541            a128 in bf128(),
1542        ) {
1543            prop_assert_eq!(a2.bool_check(), a2 * (a2 - BinaryField2::ONE));
1544            prop_assert_eq!(a4.bool_check(), a4 * (a4 - BinaryField4::ONE));
1545            prop_assert_eq!(a8.bool_check(), a8 * (a8 - BinaryField8::ONE));
1546            prop_assert_eq!(a16.bool_check(), a16 * (a16 - BinaryField16::ONE));
1547            prop_assert_eq!(a32.bool_check(), a32 * (a32 - BinaryField32::ONE));
1548            prop_assert_eq!(a64.bool_check(), a64 * (a64 - BinaryField64::ONE));
1549            prop_assert_eq!(a128.bool_check(), a128 * (a128 - BinaryField128::ONE));
1550        }
1551    }
1552}