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 core::fmt::{self, Debug, Display, Formatter};
14use core::iter::{Product, Sum};
15use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
16
17use num_bigint::BigUint;
18use p3_field::op_assign_macros::{
19    impl_add_assign, impl_add_base_field, impl_div_methods, impl_mul_base_field, impl_mul_methods,
20    impl_sub_assign, impl_sub_base_field, ring_sum,
21};
22use p3_field::{Algebra, Field, Packable, PrimeCharacteristicRing, RawDataSerializable};
23use rand::Rng;
24use rand::distr::{Distribution, StandardUniform};
25use serde::de::Error;
26use serde::{Deserialize, Deserializer, Serialize};
27
28use crate::clmul::{HAS_HARDWARE_CLMUL, mul_64, mul_128, square_64, square_128};
29use crate::{Gf2, tables};
30
31/// Seals [`TowerLevel`] against implementation outside this crate.
32///
33/// `domain_point`, `AdditiveNtt` and every identity `p3-binary-dft` builds on assume
34/// `cantor_basis` is *the* Cantor basis — `v_0 = 1` and `v_i² + v_i = v_{i−1}` — not merely some
35/// `F_2`-linearly independent sequence. An external implementation satisfying none of that would
36/// fail silently, with wrong evaluations rather than a compile error, wherever those assume it.
37mod private {
38    pub trait Sealed {}
39}
40
41/// One level of the Wiedemann tower. `Repr` is the backing integer; `LOG_BITS` is `k` for `GF(2^(2^k))`.
42pub trait TowerLevel: Field + private::Sealed {
43    type Repr: Copy;
44    const LOG_BITS: usize;
45    /// Build an element from a bit pattern, discarding the bits above `2^LOG_BITS`.
46    fn from_repr(r: Self::Repr) -> Self;
47    /// The bit pattern of this element, zero above `2^LOG_BITS`.
48    fn to_repr(self) -> Self::Repr;
49    /// Multiply by the generator `X_{k−1}` of this level over the one below.
50    fn mul_alpha(self) -> Self;
51    /// Build an element from the next [`RawDataSerializable::NUM_BYTES`] bytes of a
52    /// little-endian byte stream, discarding the bits above `2^LOG_BITS`.
53    ///
54    /// # Panics
55    /// Panics if the stream ends before a whole element has been read.
56    fn from_le_byte_iter(bytes: impl Iterator<Item = u8>) -> Self;
57    /// The `i`-th vector of the Cantor basis of this level.
58    ///
59    /// # Panics
60    /// Panics if `i` is at least the bit width `2^LOG_BITS` of this level.
61    fn cantor_basis(i: usize) -> Self;
62}
63
64/// The panic message shared by every [`TowerLevel::from_le_byte_iter`] implementation.
65const BYTE_STREAM_ENDED: &str = "byte stream ended before a whole element was read";
66
67impl private::Sealed for Gf2 {}
68
69impl TowerLevel for Gf2 {
70    type Repr = u8;
71
72    const LOG_BITS: usize = 0;
73
74    #[inline]
75    fn from_repr(r: Self::Repr) -> Self {
76        Self::from_bool((r & 1) == 1)
77    }
78
79    #[inline]
80    fn to_repr(self) -> Self::Repr {
81        u8::from(self.is_one())
82    }
83
84    /// `X_{−1} = 1`, so at the base of the tower this is the identity.
85    #[inline]
86    fn mul_alpha(self) -> Self {
87        self
88    }
89
90    #[inline]
91    fn from_le_byte_iter(mut bytes: impl Iterator<Item = u8>) -> Self {
92        Self::from_le_bytes([bytes.next().expect(BYTE_STREAM_ENDED)])
93    }
94
95    /// `GF(2)` holds only `v_0 = 1`.
96    #[inline]
97    fn cantor_basis(i: usize) -> Self {
98        assert!(i < 1, "Cantor basis index out of range");
99        Self::ONE
100    }
101}
102
103/// Define one level of the tower as a quadratic extension of the level below.
104///
105/// The parameters are the name of the level, its bit width, its backing integer, the level
106/// below with that level's backing integer, the bit pattern of a multiplicative generator, and
107/// the methods `Mul`, `square` and `try_inverse` forward to.
108macro_rules! binary_tower_level {
109    ($name:ident, $bits:literal, $repr:ty, $lower:ty, $lower_repr:ty, $generator:literal, $mul:ident, $square:ident, $try_inverse:ident) => {
110        #[doc = concat!("The binary tower field `GF(2^", stringify!($bits), ")`.")]
111        ///
112        #[doc = concat!("A quadratic extension of [`", stringify!($lower), "`] generated by a root `X` of")]
113        /// `X² + αX + 1`, where `α` is the generator of the level below over the one beneath it.
114        /// The low half of the backing integer holds the coefficient of `1`, the high half the
115        /// coefficient of `X`.
116        ///
117        /// The serde encoding is canonical: every field element has exactly one valid byte
118        /// representation (see the manual [`Deserialize`] impl below). `#[serde(transparent)]`
119        /// makes the derived [`Serialize`] emit the backing integer itself, which is what that
120        /// impl reads back.
121        #[derive(Copy, Clone, Default, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize)]
122        #[serde(transparent)]
123        #[repr(transparent)]
124        #[must_use]
125        pub struct $name($repr);
126
127        impl $name {
128            /// The number of bits of an element.
129            pub(crate) const BITS: usize = $bits;
130
131            /// Selects the bits of a canonical representative.
132            const MASK: $repr = <$repr>::MAX >> (<$repr>::BITS as usize - $bits);
133
134            /// The number of bits of each coefficient over the level below.
135            const HALF_BITS: usize = $bits / 2;
136
137            /// Selects the bits of a canonical representative of the level below.
138            const HALF_MASK: $repr = Self::MASK >> Self::HALF_BITS;
139
140            /// The coefficients `(a0, a1)` of `self = a0 + a1·X`.
141            #[inline]
142            fn split(self) -> ($lower, $lower) {
143                let a0 = (self.0 & Self::HALF_MASK) as $lower_repr;
144                let a1 = (self.0 >> Self::HALF_BITS) as $lower_repr;
145                (<$lower>::from_repr(a0), <$lower>::from_repr(a1))
146            }
147
148            /// The element `a0 + a1·X`.
149            #[inline]
150            fn join(a0: $lower, a1: $lower) -> Self {
151                Self((a0.to_repr() as $repr) | ((a1.to_repr() as $repr) << Self::HALF_BITS))
152            }
153
154            /// Karatsuba multiplication modulo `X² = αX + 1`.
155            ///
156            /// With `z0 = a0·b0`, `z2 = a1·b1` and `z1 = a0·b1 + a1·b0`,
157            /// `a·b = (z0 + z2) + (z1 + α·z2)·X`.
158            ///
159            /// The coefficient products recurse through the level below's `reference_mul`
160            /// rather than its `Mul`, so this stays a self-contained definition of the tower
161            /// product even at the levels whose `Mul` dispatches to a hardware fast path.
162            #[doc(hidden)]
163            #[inline]
164            pub fn reference_mul(self, rhs: Self) -> Self {
165                let (a0, a1) = self.split();
166                let (b0, b1) = rhs.split();
167                let z0 = a0.reference_mul(b0);
168                let z2 = a1.reference_mul(b1);
169                let z1 = (a0 + a1).reference_mul(b0 + b1) + z0 + z2;
170                Self::join(z0 + z2, z1 + z2.mul_alpha())
171            }
172
173            /// Squaring modulo `X² = αX + 1`.
174            ///
175            /// The cross term `2·a0·a1·X` vanishes in characteristic 2, leaving
176            /// `a² = (a0² + a1²) + α·a1²·X`.
177            // The independent definition of squaring, kept at every level and compared
178            // against in the tests even where `square` takes a faster route.
179            #[allow(dead_code)]
180            #[inline]
181            fn reference_square(self) -> Self {
182                let (a0, a1) = self.split();
183                let a0_sq = a0.square();
184                let a1_sq = a1.square();
185                Self::join(a0_sq + a1_sq, a1_sq.mul_alpha())
186            }
187
188            /// Inversion through the norm to the level below.
189            ///
190            /// The conjugate of `a` over the level below is `(a0 + α·a1) + a1·X`, and the
191            /// product of the two, `N = a0² + α·a0·a1 + a1²`, has no `X` component. Hence
192            /// `a⁻¹ = ((a0 + α·a1) + a1·X)·N⁻¹`.
193            // The independent definition of inversion, kept at every level and compared
194            // against in the tests even where `Field::try_inverse` takes a faster route.
195            #[allow(dead_code)]
196            #[inline]
197            fn reference_try_inverse(self) -> Option<Self> {
198                if self.0 == 0 {
199                    return None;
200                }
201                let (a0, a1) = self.split();
202                let norm = a0.square() + (a0 * a1).mul_alpha() + a1.square();
203                let norm_inv = norm
204                    .try_inverse()
205                    .expect("the norm of a nonzero element is nonzero");
206                Some(Self::join((a0 + a1.mul_alpha()) * norm_inv, a1 * norm_inv))
207            }
208
209            /// Construct a field element from its little-endian byte representation.
210            ///
211            /// Every byte string of the right length is a valid input: `from_repr` masks
212            /// any bits above the canonical range.
213            #[inline]
214            pub fn from_le_bytes(bytes: [u8; core::mem::size_of::<$repr>()]) -> Self {
215                <Self as TowerLevel>::from_repr(<$repr>::from_le_bytes(bytes))
216            }
217        }
218
219        impl private::Sealed for $name {}
220
221        impl TowerLevel for $name {
222            type Repr = $repr;
223
224            const LOG_BITS: usize = Self::BITS.trailing_zeros() as usize;
225
226            #[inline]
227            fn from_repr(r: Self::Repr) -> Self {
228                Self(r & Self::MASK)
229            }
230
231            #[inline]
232            fn to_repr(self) -> Self::Repr {
233                self.0
234            }
235
236            /// `X·(c0 + c1·X) = c1 + (c0 + α·c1)·X`, using `X² = αX + 1`.
237            #[inline]
238            fn mul_alpha(self) -> Self {
239                let (c0, c1) = self.split();
240                Self::join(c1, c0 + c1.mul_alpha())
241            }
242
243            #[inline]
244            fn from_le_byte_iter(mut bytes: impl Iterator<Item = u8>) -> Self {
245                let mut buffer = [0u8; core::mem::size_of::<$repr>()];
246                for byte in &mut buffer {
247                    *byte = bytes.next().expect(BYTE_STREAM_ENDED);
248                }
249                Self::from_le_bytes(buffer)
250            }
251
252            #[inline]
253            fn cantor_basis(i: usize) -> Self {
254                assert!(i < $bits, "Cantor basis index out of range");
255                // `v_i < 2^(2^k)` for `i < 2^k`, so the cast is exact at every level.
256                Self::from_repr(crate::cantor::CANTOR_BASIS_128[i] as $repr)
257            }
258        }
259
260        impl<'de> Deserialize<'de> for $name {
261            fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
262                let val = <$repr>::deserialize(d)?;
263                // Reject non-canonical encodings so a proof cannot be re-encoded without the
264                // witness. Only the low `BITS` bits of the backing integer may be set.
265                if val <= Self::MASK {
266                    Ok(Self(val))
267                } else {
268                    Err(D::Error::custom("Value is out of range"))
269                }
270            }
271        }
272
273        impl Packable for $name {}
274
275        impl Display for $name {
276            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
277                Display::fmt(&self.0, f)
278            }
279        }
280
281        impl Debug for $name {
282            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
283                Debug::fmt(&self.0, f)
284            }
285        }
286
287        impl Distribution<$name> for StandardUniform {
288            #[inline]
289            fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $name {
290                let mut bytes = [0u8; core::mem::size_of::<$repr>()];
291                rng.fill_bytes(&mut bytes);
292                <$name>::from_repr(<$repr>::from_le_bytes(bytes))
293            }
294        }
295
296        impl PrimeCharacteristicRing for $name {
297            type PrimeSubfield = Gf2;
298
299            const ZERO: Self = Self(0);
300            const ONE: Self = Self(1);
301            // The characteristic is 2, so `TWO = ONE + ONE = ZERO`.
302            const TWO: Self = Self(0);
303            // The characteristic is 2, so `NEG_ONE = ONE`.
304            const NEG_ONE: Self = Self(1);
305
306            #[inline]
307            fn from_prime_subfield(f: Self::PrimeSubfield) -> Self {
308                Self::from_bool(f.is_one())
309            }
310
311            #[inline]
312            fn from_bool(b: bool) -> Self {
313                Self(<$repr>::from(b))
314            }
315
316            #[inline]
317            fn double(&self) -> Self {
318                // `a + a = 0` in characteristic 2.
319                Self::ZERO
320            }
321
322            /// # Panics
323            /// Always panics: `2` is not invertible in characteristic 2.
324            #[inline]
325            fn halve(&self) -> Self {
326                panic!("halve is undefined in characteristic 2")
327            }
328
329            #[inline]
330            fn square(&self) -> Self {
331                self.$square()
332            }
333
334            #[inline]
335            fn xor(&self, y: &Self) -> Self {
336                *self + *y
337            }
338
339            #[inline]
340            fn mul_2exp_u64(&self, exp: u64) -> Self {
341                if exp == 0 { *self } else { Self::ZERO }
342            }
343
344            /// # Panics
345            /// Always panics: `2` is not invertible in characteristic 2.
346            #[inline]
347            fn div_2exp_u64(&self, _exp: u64) -> Self {
348                panic!("div_2exp_u64 is undefined in characteristic 2")
349            }
350        }
351
352        impl Field for $name {
353            type Packing = Self;
354
355            const GENERATOR: Self = Self($generator);
356
357            #[inline]
358            fn try_inverse(&self) -> Option<Self> {
359                self.$try_inverse()
360            }
361
362            #[inline]
363            fn try_sqrt(&self) -> Option<Self> {
364                // Squaring is the Frobenius, of order `BITS`, so `a^(2^(BITS - 1))` squares to `a`.
365                Some(self.exp_power_of_2(Self::BITS - 1))
366            }
367
368            #[inline]
369            fn order() -> BigUint {
370                BigUint::from(1u8) << (1usize << <Self as TowerLevel>::LOG_BITS)
371            }
372
373            /// The enumeration by bit pattern: `interpolation_node(i)` is the element whose
374            /// coefficients over `GF(2)` are the bits of `i`. It is injective for `i < 2^BITS`.
375            ///
376            /// # Panics
377            /// Panics if `i >= 2^BITS`. `from_repr` masks, so an out-of-range index would
378            /// otherwise alias an earlier node in release builds and break an interpolation
379            /// argument silently; the check is paid once per node at setup, never in a loop.
380            #[inline]
381            fn interpolation_node(i: usize) -> Self {
382                assert!(
383                    usize::BITS as usize <= Self::BITS || i < (1usize << Self::BITS),
384                    "interpolation node index out of range"
385                );
386                Self::from_repr(i as $repr)
387            }
388
389            /// An element of `GF(2^n)` is exactly `n` bits wide.
390            #[inline]
391            fn bits() -> usize {
392                Self::BITS
393            }
394        }
395
396        impl RawDataSerializable for $name {
397            const NUM_BYTES: usize = core::mem::size_of::<$repr>();
398
399            #[inline]
400            fn into_bytes(self) -> impl IntoIterator<Item = u8> {
401                self.0.to_le_bytes()
402            }
403        }
404
405        impl Add for $name {
406            type Output = Self;
407
408            #[inline]
409            #[allow(clippy::suspicious_arithmetic_impl)]
410            fn add(self, rhs: Self) -> Self {
411                // Addition in characteristic 2 is `XOR`.
412                Self(self.0 ^ rhs.0)
413            }
414        }
415
416        impl Sub for $name {
417            type Output = Self;
418
419            #[inline]
420            #[allow(clippy::suspicious_arithmetic_impl)]
421            fn sub(self, rhs: Self) -> Self {
422                // Subtraction coincides with addition in characteristic 2.
423                self + rhs
424            }
425        }
426
427        impl Neg for $name {
428            type Output = Self;
429
430            #[inline]
431            fn neg(self) -> Self::Output {
432                // `-x = x` in characteristic 2.
433                self
434            }
435        }
436
437        impl Mul for $name {
438            type Output = Self;
439
440            #[inline]
441            fn mul(self, rhs: Self) -> Self {
442                self.$mul(rhs)
443            }
444        }
445
446        impl_add_assign!($name);
447        impl_sub_assign!($name);
448        impl_mul_methods!($name);
449        impl_div_methods!($name, $name);
450        ring_sum!($name);
451
452        impl From<Gf2> for $name {
453            /// `GF(2)` is the prime subfield of every level, embedded as `{ZERO, ONE}`.
454            #[inline]
455            fn from(x: Gf2) -> Self {
456                Self::from_prime_subfield(x)
457            }
458        }
459
460        impl_add_base_field!($name, Gf2);
461        impl_sub_base_field!($name, Gf2);
462        impl_mul_base_field!($name, Gf2);
463
464        impl Algebra<Gf2> for $name {}
465    };
466}
467
468binary_tower_level!(
469    BinaryField2,
470    2,
471    u8,
472    Gf2,
473    u8,
474    2,
475    reference_mul,
476    reference_square,
477    reference_try_inverse
478);
479binary_tower_level!(
480    BinaryField4,
481    4,
482    u8,
483    BinaryField2,
484    u8,
485    5,
486    reference_mul,
487    reference_square,
488    reference_try_inverse
489);
490binary_tower_level!(
491    BinaryField8,
492    8,
493    u8,
494    BinaryField4,
495    u8,
496    19,
497    table_mul,
498    table_square,
499    table_try_inverse
500);
501binary_tower_level!(
502    BinaryField16,
503    16,
504    u16,
505    BinaryField8,
506    u8,
507    258,
508    karatsuba_mul,
509    reference_square,
510    reference_try_inverse
511);
512binary_tower_level!(
513    BinaryField32,
514    32,
515    u32,
516    BinaryField16,
517    u16,
518    65541,
519    karatsuba_mul,
520    reference_square,
521    reference_try_inverse
522);
523binary_tower_level!(
524    BinaryField64,
525    64,
526    u64,
527    BinaryField32,
528    u32,
529    4294967300,
530    dispatched_mul,
531    dispatched_square,
532    reference_try_inverse
533);
534binary_tower_level!(
535    BinaryField128,
536    128,
537    u128,
538    BinaryField64,
539    u64,
540    18446744073709551621,
541    dispatched_mul,
542    dispatched_square,
543    reference_try_inverse
544);
545
546impl BinaryField8 {
547    /// Multiplication through the `GF(2^8)` log and exponential tables.
548    #[inline]
549    const fn table_mul(self, rhs: Self) -> Self {
550        Self(tables::mul(self.0, rhs.0))
551    }
552
553    /// Squaring through the `GF(2^8)` log and exponential tables.
554    #[inline]
555    const fn table_square(self) -> Self {
556        Self(tables::square(self.0))
557    }
558
559    /// Inversion through the `GF(2^8)` log and exponential tables.
560    #[inline]
561    const fn table_try_inverse(self) -> Option<Self> {
562        match tables::try_inverse(self.0) {
563            Some(inverse) => Some(Self(inverse)),
564            None => None,
565        }
566    }
567}
568
569/// Give a level Karatsuba multiplication over the `Mul` of the level below.
570///
571/// The recurrence is the one [`binary_tower_level`] documents on `reference_mul`, but the
572/// coefficient products go through the level below's operator, so the recursion stops as soon
573/// as it reaches a level with a fast path instead of running to the bottom of the tower.
574macro_rules! karatsuba_over_the_level_below {
575    ($name:ident) => {
576        impl $name {
577            /// Karatsuba multiplication modulo `X² = αX + 1`.
578            ///
579            /// With `z0 = a0·b0`, `z2 = a1·b1` and `z1 = a0·b1 + a1·b0`,
580            /// `a·b = (z0 + z2) + (z1 + α·z2)·X`.
581            #[inline]
582            fn karatsuba_mul(self, rhs: Self) -> Self {
583                let (a0, a1) = self.split();
584                let (b0, b1) = rhs.split();
585                let z0 = a0 * b0;
586                let z2 = a1 * b1;
587                let z1 = (a0 + a1) * (b0 + b1) + z0 + z2;
588                Self::join(z0 + z2, z1 + z2.mul_alpha())
589            }
590        }
591    };
592}
593
594karatsuba_over_the_level_below!(BinaryField16);
595karatsuba_over_the_level_below!(BinaryField32);
596
597impl BinaryField64 {
598    /// The carryless-multiply fast path where the target has the instruction for it, and the
599    /// recursive tower multiplication otherwise.
600    ///
601    /// [`HAS_HARDWARE_CLMUL`] is a constant, so only the chosen arm survives compilation.
602    #[inline]
603    fn dispatched_mul(self, rhs: Self) -> Self {
604        if HAS_HARDWARE_CLMUL {
605            Self(mul_64(self.0, rhs.0))
606        } else {
607            self.reference_mul(rhs)
608        }
609    }
610
611    /// The carryless-multiply fast path for squaring, under the same dispatch as
612    /// [`Self::dispatched_mul`].
613    #[inline]
614    fn dispatched_square(self) -> Self {
615        if HAS_HARDWARE_CLMUL {
616            Self(square_64(self.0))
617        } else {
618            self.reference_square()
619        }
620    }
621}
622
623impl BinaryField128 {
624    /// The carryless-multiply fast path where the target has the instruction for it, and the
625    /// recursive tower multiplication otherwise.
626    ///
627    /// [`HAS_HARDWARE_CLMUL`] is a constant, so only the chosen arm survives compilation.
628    #[inline]
629    fn dispatched_mul(self, rhs: Self) -> Self {
630        if HAS_HARDWARE_CLMUL {
631            Self(mul_128(self.0, rhs.0))
632        } else {
633            self.reference_mul(rhs)
634        }
635    }
636
637    /// The carryless-multiply fast path for squaring, under the same dispatch as
638    /// [`Self::dispatched_mul`].
639    #[inline]
640    fn dispatched_square(self) -> Self {
641        if HAS_HARDWARE_CLMUL {
642            Self(square_128(self.0))
643        } else {
644            self.reference_square()
645        }
646    }
647}
648
649#[cfg(test)]
650mod tests {
651    extern crate std;
652
653    use std::println;
654    use std::vec::Vec;
655
656    use p3_field::{Field, PrimeCharacteristicRing, RawDataSerializable};
657    use proptest::prelude::*;
658
659    use super::*;
660
661    /// The prime factors of `2^n − 1` for each level `n` of the tower.
662    const FACTORS_2: [u128; 1] = [3];
663    const FACTORS_4: [u128; 2] = [3, 5];
664    const FACTORS_8: [u128; 3] = [3, 5, 17];
665    const FACTORS_16: [u128; 4] = [3, 5, 17, 257];
666    const FACTORS_32: [u128; 5] = [3, 5, 17, 257, 65537];
667    const FACTORS_64: [u128; 7] = [3, 5, 17, 257, 641, 65537, 6700417];
668    const FACTORS_128: [u128; 9] = [3, 5, 17, 257, 641, 65537, 274177, 6700417, 67280421310721];
669
670    /// The order `2^bits − 1` of the multiplicative group of `GF(2^bits)`.
671    const fn group_order(bits: u32) -> u128 {
672        if bits == 128 {
673            u128::MAX
674        } else {
675            (1u128 << bits) - 1
676        }
677    }
678
679    /// `base^exp`, with an exponent too large for [`PrimeCharacteristicRing::exp_u64`].
680    fn pow_u128<F: Field>(base: F, mut exp: u128) -> F {
681        let mut acc = F::ONE;
682        let mut cur = base;
683        while exp != 0 {
684            if exp & 1 == 1 {
685                acc *= cur;
686            }
687            cur = cur.square();
688            exp >>= 1;
689        }
690        acc
691    }
692
693    /// Whether `g` generates the whole multiplicative group of `GF(2^bits)`.
694    ///
695    /// `g` has full order exactly when `g^((2^bits − 1)/q) != 1` for every prime `q`
696    /// dividing `2^bits − 1`.
697    fn has_full_order<F: Field>(g: F, bits: u32, factors: &[u128]) -> bool {
698        let order = group_order(bits);
699        factors.iter().all(|&q| pow_u128(g, order / q) != F::ONE)
700    }
701
702    macro_rules! assert_full_order {
703        ($t:ty, $bits:expr, $factors:expr) => {
704            assert!(
705                has_full_order(<$t>::GENERATOR, $bits, &$factors),
706                concat!(
707                    stringify!($t),
708                    "::GENERATOR does not generate the multiplicative group"
709                )
710            );
711        };
712    }
713
714    macro_rules! assert_defining_relation {
715        ($t:ty, $repr:ty, $bits:expr) => {{
716            // `X` is the generator of this level over the one below (bit `bits/2`) and
717            // `alpha` the generator of the level below over the one beneath it (bit `bits/4`),
718            // which is `1` at the bottom of the tower.
719            let x = <$t>::from_repr((1 as $repr) << ($bits / 2));
720            let alpha = <$t>::from_repr((1 as $repr) << ($bits / 4));
721            assert_eq!(
722                x.square(),
723                alpha * x + <$t>::ONE,
724                concat!(stringify!($t), " does not satisfy X^2 = alpha*X + 1")
725            );
726        }};
727    }
728
729    macro_rules! search_generator {
730        ($t:ty, $repr:ty, $bits:expr, $factors:expr) => {{
731            // A bit pattern below `2^(bits/2)` has a zero coefficient on `X` and so lies in the
732            // proper subfield `GF(2^(bits/2))`; the smallest generator is above that.
733            let start = 1u128 << ($bits / 2);
734            let found = (start..start + 1024)
735                .map(|cand| (cand, <$t>::from_repr(cand as $repr)))
736                .find(|&(_, g)| has_full_order(g, $bits, &$factors));
737            println!(
738                "{}: GENERATOR = {:?}",
739                stringify!($t),
740                found.map(|(cand, _)| cand)
741            );
742        }};
743    }
744
745    #[test]
746    fn gf4_multiplication_table() {
747        // Elements of GF(4) = GF(2)[X]/(X^2 + X + 1) as bit patterns: 0, 1, X = 2, X + 1 = 3.
748        let x = BinaryField2::from_repr(2);
749        assert_eq!(x * x, x + BinaryField2::ONE); // X^2 = X + 1
750        assert_eq!(x * (x + BinaryField2::ONE), BinaryField2::ONE); // X(X + 1) = 1
751        assert_eq!(x.inverse(), x + BinaryField2::ONE);
752    }
753
754    #[test]
755    fn frobenius_fixes_every_element_of_each_level() {
756        for r in 0..=u8::MAX {
757            let a = BinaryField8::from_repr(r);
758            assert_eq!(a.exp_power_of_2(8), a); // a^(2^8) = a
759        }
760        for r in 0..=u8::MAX {
761            let a = BinaryField4::from_repr(r & 0x0f);
762            assert_eq!(a.exp_power_of_2(4), a); // a^(2^4) = a
763        }
764    }
765
766    /// The table squaring at `GF(2^8)` must reproduce the recursion that runs to the bottom of
767    /// the tower.
768    #[test]
769    fn the_table_square_agrees_with_the_recursive_squaring_on_gf256() {
770        for r in 0..=u8::MAX {
771            let a = BinaryField8::from_repr(r);
772            assert_eq!(a.table_square(), a.reference_square(), "square({r})");
773        }
774    }
775
776    /// The table inversion at `GF(2^8)` must reproduce the recursion through the norm, which
777    /// is the definition of the inverse in this tower.
778    #[test]
779    fn the_table_inverse_agrees_with_the_recursive_inverse_on_gf256() {
780        for r in 0..=u8::MAX {
781            let a = BinaryField8::from_repr(r);
782            assert_eq!(
783                a.table_try_inverse(),
784                a.reference_try_inverse(),
785                "inverse({r})"
786            );
787        }
788    }
789
790    /// Karatsuba over the level below's operator must reproduce the recursion that runs to the
791    /// bottom of the tower, over every `GF(2^16)` left operand.
792    #[test]
793    fn karatsuba_agrees_with_the_recursive_product_over_every_gf16_operand() {
794        let others = [0u16, 1, 2, 0x00ff, 0x0100, 0x1234, 0xfffe, 0xffff];
795        for r in 0..=u16::MAX {
796            let a = BinaryField16::from_repr(r);
797            for other in others {
798                let b = BinaryField16::from_repr(other);
799                assert_eq!(a.karatsuba_mul(b), a.reference_mul(b), "mul({r}, {other})");
800            }
801        }
802    }
803
804    #[test]
805    fn inverse_agrees_with_fermat_on_gf256() {
806        for r in 1..=u8::MAX {
807            let a = BinaryField8::from_repr(r);
808            assert_eq!(a.inverse(), a.exp_u64(254));
809            assert_eq!(a * a.inverse(), BinaryField8::ONE);
810        }
811    }
812
813    #[test]
814    fn square_roots_square_back_to_the_input() {
815        for r in 0..=u8::MAX {
816            let a = BinaryField8::from_repr(r);
817            assert_eq!(a.try_sqrt().unwrap().square(), a);
818        }
819        let a = BinaryField128::from_repr(0x0123_4567_89ab_cdef_fedc_ba98_7654_3210);
820        assert_eq!(a.try_sqrt().unwrap().square(), a);
821    }
822
823    /// The sub-byte levels store fewer bits than their backing integer holds, so a decoder that
824    /// accepted any byte could build an element whose high bits are set. Such a value compares
825    /// and hashes differently from the canonical representative of the same field element.
826    #[test]
827    fn serde_round_trip_rejects_non_canonical_encodings() {
828        assert_eq!(
829            serde_json::to_string(&BinaryField4::from_repr(9)).unwrap(),
830            "9"
831        );
832        assert_eq!(
833            serde_json::from_str::<BinaryField4>("9").unwrap(),
834            BinaryField4::from_repr(9)
835        );
836
837        // `GF(4)` uses 2 bits and `GF(16)` 4 bits of their `u8`; the rest must be rejected,
838        // not silently truncated into range.
839        assert!(serde_json::from_str::<BinaryField2>("3").is_ok());
840        assert!(serde_json::from_str::<BinaryField2>("4").is_err());
841        assert!(serde_json::from_str::<BinaryField4>("15").is_ok());
842        assert!(serde_json::from_str::<BinaryField4>("16").is_err());
843
844        // The levels that fill their backing integer accept every value of it.
845        assert!(serde_json::from_str::<BinaryField8>("255").is_ok());
846        assert!(serde_json::from_str::<BinaryField8>("256").is_err());
847    }
848
849    #[test]
850    fn bytes_round_trip_and_postcard() {
851        let a = BinaryField128::from_repr(0x8000_0000_0000_0000_0000_0000_0000_0001);
852        let bytes: Vec<u8> = a.into_bytes().into_iter().collect();
853        assert_eq!(bytes.len(), 16);
854        assert_eq!(BinaryField128::from_le_bytes(bytes.try_into().unwrap()), a);
855
856        let encoded = postcard::to_allocvec(&a).unwrap();
857        assert_eq!(postcard::from_bytes::<BinaryField128>(&encoded).unwrap(), a);
858    }
859
860    /// Every byte string of the right length round-trips to a field element for every level,
861    /// since [`RawDataSerializable::into_bytes`] and `from_le_bytes` are inverses on the full
862    /// `NUM_BYTES`-byte space, not just on canonical representatives.
863    #[test]
864    fn from_le_bytes_round_trips_every_level() {
865        macro_rules! assert_bytes_round_trip {
866            ($t:ty, $repr:ty, $val:expr) => {{
867                let a = <$t>::from_repr($val as $repr);
868                let bytes: Vec<u8> = a.into_bytes().into_iter().collect();
869                assert_eq!(bytes.len(), core::mem::size_of::<$repr>());
870                assert_eq!(<$t>::from_le_bytes(bytes.try_into().unwrap()), a);
871            }};
872        }
873
874        assert_bytes_round_trip!(BinaryField2, u8, 0b11);
875        assert_bytes_round_trip!(BinaryField4, u8, 0b1001);
876        assert_bytes_round_trip!(BinaryField8, u8, 0xab);
877        assert_bytes_round_trip!(BinaryField16, u16, 0x1234);
878        assert_bytes_round_trip!(BinaryField32, u32, 0x1234_5678);
879        assert_bytes_round_trip!(BinaryField64, u64, 0x0123_4567_89ab_cdef);
880        assert_bytes_round_trip!(
881            BinaryField128,
882            u128,
883            0x8000_0000_0000_0000_0000_0000_0000_0001
884        );
885    }
886
887    /// `from_le_bytes` must be total: every byte string of the right length is a valid
888    /// element, not just the ones a masked-already `from_repr` call would ever feed it. The
889    /// sub-byte levels store fewer bits than their `u8` backing integer holds, so a decoder
890    /// that skipped masking could construct a value whose high bits are set and diverge from
891    /// the canonical representative of the same field element.
892    #[test]
893    fn from_le_bytes_masks_out_of_range_high_bits() {
894        assert_eq!(
895            BinaryField2::from_le_bytes([0xff]),
896            BinaryField2::from_repr(0b11)
897        );
898        assert_eq!(
899            BinaryField2::from_le_bytes([0b1010_0110]),
900            BinaryField2::from_repr(0b10)
901        );
902        assert_eq!(
903            BinaryField4::from_le_bytes([0xff]),
904            BinaryField4::from_repr(0b1111)
905        );
906        assert_eq!(
907            BinaryField4::from_le_bytes([0b1010_0111]),
908            BinaryField4::from_repr(0b0111)
909        );
910    }
911
912    /// `from_le_byte_iter` reads exactly `NUM_BYTES` bytes off the front of the stream and
913    /// agrees with `from_le_bytes` on them, leaving the rest for the next element.
914    #[test]
915    fn from_le_byte_iter_consumes_one_element_worth_of_bytes() {
916        macro_rules! assert_reads_one_element {
917            ($t:ty, $repr:ty) => {{
918                let width = core::mem::size_of::<$repr>();
919                let stream: Vec<u8> = (0..2 * width as u8).map(|i| i.wrapping_mul(37)).collect();
920
921                let mut iter = stream.iter().copied();
922                let first = <$t as TowerLevel>::from_le_byte_iter(&mut iter);
923                let second = <$t as TowerLevel>::from_le_byte_iter(&mut iter);
924
925                assert_eq!(iter.next(), None, "the stream must be fully consumed");
926                assert_eq!(
927                    first,
928                    <$t>::from_le_bytes(stream[..width].try_into().unwrap())
929                );
930                assert_eq!(
931                    second,
932                    <$t>::from_le_bytes(stream[width..].try_into().unwrap())
933                );
934            }};
935        }
936
937        assert_reads_one_element!(Gf2, u8);
938        assert_reads_one_element!(BinaryField2, u8);
939        assert_reads_one_element!(BinaryField4, u8);
940        assert_reads_one_element!(BinaryField8, u8);
941        assert_reads_one_element!(BinaryField16, u16);
942        assert_reads_one_element!(BinaryField32, u32);
943        assert_reads_one_element!(BinaryField64, u64);
944        assert_reads_one_element!(BinaryField128, u128);
945    }
946
947    #[test]
948    #[should_panic = "byte stream ended before a whole element was read"]
949    fn from_le_byte_iter_rejects_a_truncated_stream() {
950        let truncated = [0u8; 15];
951        let _ = BinaryField128::from_le_byte_iter(truncated.into_iter());
952    }
953
954    #[test]
955    fn field_testing_into_stream_matches_binary_field_128() {
956        p3_field_testing::test_into_stream::<BinaryField128>();
957    }
958
959    #[test]
960    fn order_counts_the_elements_of_each_level() {
961        assert_eq!(BinaryField2::order(), BigUint::from(4u32));
962        assert_eq!(BinaryField4::order(), BigUint::from(16u32));
963        assert_eq!(BinaryField8::order(), BigUint::from(256u32));
964        assert_eq!(BinaryField16::order(), BigUint::from(65536u32));
965        assert_eq!(BinaryField32::order(), BigUint::from(1u64 << 32));
966        assert_eq!(BinaryField64::order(), BigUint::from(1u128 << 64));
967        assert_eq!(BinaryField128::order(), BigUint::from(1u8) << 128usize);
968    }
969
970    #[test]
971    fn interpolation_nodes_are_basis_expansion() {
972        assert_eq!(BinaryField128::interpolation_node(0), BinaryField128::ZERO);
973        assert_eq!(BinaryField128::interpolation_node(1), BinaryField128::ONE);
974        assert_eq!(
975            BinaryField128::interpolation_node(2),
976            BinaryField128::from_repr(2)
977        );
978        assert_eq!(
979            BinaryField128::interpolation_node(5),
980            BinaryField128::from_repr(5)
981        );
982    }
983
984    /// The last index a level can enumerate is `2^BITS - 1`; anything above it would be masked
985    /// back onto an earlier node.
986    #[test]
987    fn interpolation_nodes_cover_the_whole_level() {
988        assert_eq!(
989            BinaryField4::interpolation_node(15),
990            BinaryField4::from_repr(15)
991        );
992        assert_eq!(
993            BinaryField8::interpolation_node(255),
994            BinaryField8::from_repr(255)
995        );
996    }
997
998    #[test]
999    #[should_panic = "interpolation node index out of range"]
1000    fn interpolation_node_rejects_an_index_beyond_the_level() {
1001        let _node = BinaryField8::interpolation_node(256);
1002    }
1003
1004    #[test]
1005    fn each_level_satisfies_the_tower_defining_relation() {
1006        assert_defining_relation!(BinaryField2, u8, 2);
1007        assert_defining_relation!(BinaryField4, u8, 4);
1008        assert_defining_relation!(BinaryField8, u8, 8);
1009        assert_defining_relation!(BinaryField16, u16, 16);
1010        assert_defining_relation!(BinaryField32, u32, 32);
1011        assert_defining_relation!(BinaryField64, u64, 64);
1012        assert_defining_relation!(BinaryField128, u128, 128);
1013    }
1014
1015    /// `GF(2)` is the prime subfield of the whole tower, so every level is a `GF(2)`-algebra:
1016    /// the embedding is a ring homomorphism and each mixed operator agrees with embedding first.
1017    #[test]
1018    fn every_level_is_an_algebra_over_gf2() {
1019        /// Statically require the full `Algebra<Gf2>` bound, not merely the operators.
1020        const fn assert_algebra_over_gf2<T: Algebra<Gf2>>() {}
1021
1022        macro_rules! assert_gf2_algebra {
1023            ($t:ty) => {{
1024                assert_algebra_over_gf2::<$t>();
1025
1026                assert_eq!(<$t>::from(Gf2::ZERO), <$t>::ZERO);
1027                assert_eq!(<$t>::from(Gf2::ONE), <$t>::ONE);
1028
1029                for x in [Gf2::ZERO, Gf2::ONE] {
1030                    for y in [Gf2::ZERO, Gf2::ONE] {
1031                        assert_eq!(<$t>::from(x + y), <$t>::from(x) + <$t>::from(y));
1032                        assert_eq!(<$t>::from(x * y), <$t>::from(x) * <$t>::from(y));
1033                    }
1034                }
1035
1036                for a in [
1037                    <$t>::ZERO,
1038                    <$t>::ONE,
1039                    <$t>::GENERATOR,
1040                    <$t>::GENERATOR.square(),
1041                ] {
1042                    for bit in [Gf2::ZERO, Gf2::ONE] {
1043                        let embedded = <$t>::from(bit);
1044
1045                        assert_eq!(a + bit, a + embedded);
1046                        assert_eq!(a - bit, a - embedded);
1047                        assert_eq!(a * bit, a * embedded);
1048                        assert_eq!(bit + a, embedded + a);
1049                        assert_eq!(bit - a, embedded - a);
1050                        assert_eq!(bit * a, embedded * a);
1051
1052                        let mut acc = a;
1053                        acc += bit;
1054                        assert_eq!(acc, a + embedded);
1055                        let mut acc = a;
1056                        acc -= bit;
1057                        assert_eq!(acc, a - embedded);
1058                        let mut acc = a;
1059                        acc *= bit;
1060                        assert_eq!(acc, a * embedded);
1061                    }
1062                }
1063            }};
1064        }
1065
1066        assert_gf2_algebra!(BinaryField2);
1067        assert_gf2_algebra!(BinaryField4);
1068        assert_gf2_algebra!(BinaryField8);
1069        assert_gf2_algebra!(BinaryField16);
1070        assert_gf2_algebra!(BinaryField32);
1071        assert_gf2_algebra!(BinaryField64);
1072        assert_gf2_algebra!(BinaryField128);
1073    }
1074
1075    #[test]
1076    fn generators_generate_the_multiplicative_group() {
1077        assert_full_order!(BinaryField2, 2, FACTORS_2);
1078        assert_full_order!(BinaryField4, 4, FACTORS_4);
1079        assert_full_order!(BinaryField8, 8, FACTORS_8);
1080        assert_full_order!(BinaryField16, 16, FACTORS_16);
1081        assert_full_order!(BinaryField32, 32, FACTORS_32);
1082        assert_full_order!(BinaryField64, 64, FACTORS_64);
1083        assert_full_order!(BinaryField128, 128, FACTORS_128);
1084    }
1085
1086    /// Scans for the smallest bit pattern generating each level's multiplicative group.
1087    ///
1088    /// The values it reports are pinned as the `GENERATOR` constants; run with
1089    /// `cargo test -p p3-binary-field --release -- --ignored --nocapture`.
1090    #[test]
1091    #[ignore = "one-off search used to pin the GENERATOR constants"]
1092    fn search_generators() {
1093        search_generator!(BinaryField2, u8, 2, FACTORS_2);
1094        search_generator!(BinaryField4, u8, 4, FACTORS_4);
1095        search_generator!(BinaryField8, u8, 8, FACTORS_8);
1096        search_generator!(BinaryField16, u16, 16, FACTORS_16);
1097        search_generator!(BinaryField32, u32, 32, FACTORS_32);
1098        search_generator!(BinaryField64, u64, 64, FACTORS_64);
1099        search_generator!(BinaryField128, u128, 128, FACTORS_128);
1100    }
1101
1102    fn bf128() -> impl Strategy<Value = BinaryField128> {
1103        any::<u128>().prop_map(BinaryField128::from_repr)
1104    }
1105
1106    fn bf64() -> impl Strategy<Value = BinaryField64> {
1107        any::<u64>().prop_map(BinaryField64::from_repr)
1108    }
1109
1110    fn bf32() -> impl Strategy<Value = BinaryField32> {
1111        any::<u32>().prop_map(BinaryField32::from_repr)
1112    }
1113
1114    fn bf16() -> impl Strategy<Value = BinaryField16> {
1115        any::<u16>().prop_map(BinaryField16::from_repr)
1116    }
1117
1118    proptest! {
1119        #![proptest_config(ProptestConfig::with_cases(1000))]
1120
1121        #[test]
1122        fn mul_is_commutative(a in bf128(), b in bf128()) {
1123            prop_assert_eq!(a * b, b * a);
1124        }
1125
1126        #[test]
1127        fn mul_is_associative(a in bf128(), b in bf128(), c in bf128()) {
1128            prop_assert_eq!((a * b) * c, a * (b * c));
1129        }
1130
1131        #[test]
1132        fn mul_distributes_over_addition(a in bf128(), b in bf128(), c in bf128()) {
1133            prop_assert_eq!(a * (b + c), a * b + a * c);
1134        }
1135
1136        #[test]
1137        fn nonzero_times_its_inverse_is_one(a in bf128()) {
1138            prop_assume!(a != BinaryField128::ZERO);
1139            prop_assert_eq!(a * a.inverse(), BinaryField128::ONE);
1140        }
1141
1142        /// The levels whose `square` dispatches must agree with the recursive definition.
1143        #[test]
1144        fn square_agrees_with_the_reference_squaring(a in bf128(), b in bf64()) {
1145            prop_assert_eq!(a.square(), a.reference_square());
1146            prop_assert_eq!(b.square(), b.reference_square());
1147        }
1148
1149        /// `reference_mul` recurses to the bottom of the tower without dispatching, so squaring
1150        /// through it is independent of every fast path.
1151        #[test]
1152        fn square_agrees_with_the_reference_product(a in bf128(), b in bf64()) {
1153            prop_assert_eq!(a.square(), a.reference_mul(a));
1154            prop_assert_eq!(b.square(), b.reference_mul(b));
1155        }
1156
1157        #[test]
1158        fn square_agrees_with_self_multiplication(a in bf128(), b in bf64()) {
1159            prop_assert_eq!(a.square(), a * a);
1160            prop_assert_eq!(b.square(), b * b);
1161        }
1162
1163        /// The levels whose `Mul` recurses through the level below's operator must agree with
1164        /// the recursion that runs to the bottom of the tower.
1165        #[test]
1166        fn karatsuba_agrees_with_the_recursive_product(a in bf32(), b in bf32(), c in bf16(), d in bf16()) {
1167            prop_assert_eq!(a.karatsuba_mul(b), a.reference_mul(b));
1168            prop_assert_eq!(c.karatsuba_mul(d), c.reference_mul(d));
1169        }
1170    }
1171}