p3_field/
field.rs

1use alloc::vec;
2use alloc::vec::Vec;
3use core::fmt::{Debug, Display};
4use core::hash::Hash;
5use core::iter::{Product, Sum};
6use core::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign};
7use core::slice;
8
9use itertools::Itertools;
10use num_bigint::BigUint;
11use num_traits::One;
12use nums::{Factorizer, FactorizerFromSplitter, MillerRabin, PollardRho};
13use serde::de::DeserializeOwned;
14use serde::Serialize;
15
16use crate::exponentiation::exp_u64_by_squaring;
17use crate::packed::{PackedField, PackedValue};
18use crate::Packable;
19
20/// A commutative algebra over a finite field.
21///
22/// This permits elements like:
23/// - an actual field element
24/// - a symbolic expression which would evaluate to a field element
25/// - an array of field elements
26///
27/// Mathematically speaking, this is an algebraic structure with addition,
28/// multiplication and scalar multiplication. The addition and multiplication
29/// maps must be both commutative and associative, and there must
30/// exist identity elements for both (named `ZERO` and `ONE`
31/// respectively). Furthermore, multiplication must distribute over
32/// addition. Finally, the scalar multiplication must be realized by
33/// a ring homomorphism from the field to the algebra.
34pub trait FieldAlgebra:
35    Sized
36    + Default
37    + Clone
38    + Add<Output = Self>
39    + AddAssign
40    + Sub<Output = Self>
41    + SubAssign
42    + Neg<Output = Self>
43    + Mul<Output = Self>
44    + MulAssign
45    + Sum
46    + Product
47    + Debug
48{
49    type F: Field;
50
51    /// The additive identity of the algebra.
52    ///
53    /// For every element `a` in the algebra we require the following properties:
54    ///
55    /// `a + ZERO = ZERO + a = a,`
56    ///
57    /// `a + (-a) = (-a) + a = ZERO.`
58    const ZERO: Self;
59
60    /// The multiplicative identity of the Algebra
61    ///
62    /// For every element `a` in the algebra we require the following property:
63    ///
64    /// `a*ONE = ONE*a = a.`
65    const ONE: Self;
66
67    /// The element in the algebra given by `ONE + ONE`.
68    ///
69    /// This is provided as a convenience as `TWO` occurs regularly in
70    /// the proving system. This also is slightly faster than computing
71    /// it via addition. Note that multiplication by `TWO` is discouraged.
72    /// Instead of `a * TWO` use `a.double()` which will be faster.
73    ///
74    /// If the field has characteristic 2 this is equal to ZERO.
75    const TWO: Self;
76
77    /// The element in the algebra given by `-ONE`.
78    ///
79    /// This is provided as a convenience as `NEG_ONE` occurs regularly in
80    /// the proving system. This also is slightly faster than computing
81    /// it via negation. Note that where possible `NEG_ONE` should be absorbed
82    /// into mathematical operations. For example `a - b` will be faster
83    /// than `a + NEG_ONE * b` and similarly `(-b)` is faster than `NEG_ONE * b`.
84    ///
85    /// If the field has characteristic 2 this is equal to ONE.
86    const NEG_ONE: Self;
87
88    /// Interpret a field element as a commutative algebra element.
89    ///
90    /// Mathematically speaking, this map is a ring homomorphism from the base field
91    /// to the commutative algebra. The existence of this map makes this structure
92    /// an algebra and not simply a commutative ring.
93    fn from_f(f: Self::F) -> Self;
94
95    /// Convert from a `bool`.
96    fn from_bool(b: bool) -> Self {
97        if b {
98            Self::ONE
99        } else {
100            Self::ZERO
101        }
102    }
103
104    /// Convert from a canonical `u8`.
105    ///
106    /// If the input is not canonical, i.e. if it exceeds the field's characteristic, then the
107    /// behavior is undefined.
108    fn from_canonical_u8(n: u8) -> Self;
109
110    /// Convert from a canonical `u16`.
111    ///
112    /// If the input is not canonical, i.e. if it exceeds the field's characteristic, then the
113    /// behavior is undefined.
114    fn from_canonical_u16(n: u16) -> Self;
115
116    /// Convert from a canonical `u32`.
117    ///
118    /// If the input is not canonical, i.e. if it exceeds the field's characteristic, then the
119    /// behavior is undefined.
120    fn from_canonical_u32(n: u32) -> Self;
121
122    /// Convert from a canonical `u64`.
123    ///
124    /// If the input is not canonical, i.e. if it exceeds the field's characteristic, then the
125    /// behavior is undefined.
126    fn from_canonical_u64(n: u64) -> Self;
127
128    /// Convert from a canonical `usize`.
129    ///
130    /// If the input is not canonical, i.e. if it exceeds the field's characteristic, then the
131    /// behavior is undefined.
132    fn from_canonical_usize(n: usize) -> Self;
133
134    fn from_wrapped_u32(n: u32) -> Self;
135    fn from_wrapped_u64(n: u64) -> Self;
136
137    /// The elementary function `double(a) = 2*a`.
138    ///
139    /// This function should be preferred over calling `a + a` or `TWO * a` as a faster implementation may be available for some algebras.
140    /// If the field has characteristic 2 then this returns 0.
141    #[must_use]
142    fn double(&self) -> Self {
143        self.clone() + self.clone()
144    }
145
146    /// The elementary function `square(a) = a^2`.
147    ///
148    /// This function should be preferred over calling `a * a`, as a faster implementation may be available for some algebras.
149    #[must_use]
150    fn square(&self) -> Self {
151        self.clone() * self.clone()
152    }
153
154    /// The elementary function `cube(a) = a^3`.
155    ///
156    /// This function should be preferred over calling `a * a * a`, as a faster implementation may be available for some algebras.
157    #[must_use]
158    fn cube(&self) -> Self {
159        self.square() * self.clone()
160    }
161
162    /// Exponentiation by a `u64` power.
163    ///
164    /// The default implementation calls `exp_u64_generic`, which by default performs exponentiation
165    /// by squaring. Rather than override this method, it is generally recommended to have the
166    /// concrete field type override `exp_u64_generic`, so that any optimizations will apply to all
167    /// abstract fields.
168    #[must_use]
169    #[inline]
170    fn exp_u64(&self, power: u64) -> Self {
171        Self::F::exp_u64_generic(self.clone(), power)
172    }
173
174    /// Exponentiation by a constant power.
175    ///
176    /// For a collection of small values we implement custom multiplication chain circuits which can be faster than the
177    /// simpler square and multiply approach.
178    #[must_use]
179    #[inline(always)]
180    fn exp_const_u64<const POWER: u64>(&self) -> Self {
181        match POWER {
182            0 => Self::ONE,
183            1 => self.clone(),
184            2 => self.square(),
185            3 => self.cube(),
186            4 => self.square().square(),
187            5 => self.square().square() * self.clone(),
188            6 => self.square().cube(),
189            7 => {
190                let x2 = self.square();
191                let x3 = x2.clone() * self.clone();
192                let x4 = x2.square();
193                x3 * x4
194            }
195            _ => self.exp_u64(POWER),
196        }
197    }
198
199    /// Compute self^{2^power_log} by repeated squaring.
200    #[must_use]
201    fn exp_power_of_2(&self, power_log: usize) -> Self {
202        let mut res = self.clone();
203        for _ in 0..power_log {
204            res = res.square();
205        }
206        res
207    }
208
209    /// self * 2^exp
210    #[must_use]
211    #[inline]
212    fn mul_2exp_u64(&self, exp: u64) -> Self {
213        self.clone() * Self::TWO.exp_u64(exp)
214    }
215
216    /// Construct an iterator which returns powers of `self: self^0, self^1, self^2, ...`.
217    #[must_use]
218    fn powers(&self) -> Powers<Self> {
219        self.shifted_powers(Self::ONE)
220    }
221
222    /// Construct an iterator which returns powers of `self` shifted by `start: start, start*self^1, start*self^2, ...`.
223    fn shifted_powers(&self, start: Self) -> Powers<Self> {
224        Powers {
225            base: self.clone(),
226            current: start,
227        }
228    }
229
230    /// Construct an iterator which returns powers of `self` packed into `PackedField` elements.
231    ///
232    /// E.g. if `PACKING::WIDTH = 4` this returns the elements:
233    /// `[self^0, self^1, self^2, self^3], [self^4, self^5, self^6, self^7], ...`.
234    fn powers_packed<P: PackedField<Scalar = Self>>(&self) -> Powers<P> {
235        self.shifted_powers_packed(Self::ONE)
236    }
237
238    /// Construct an iterator which returns powers of `self` shifted by start
239    /// and packed into `PackedField` elements.
240    ///
241    /// E.g. if `PACKING::WIDTH = 4` this returns the elements:
242    /// `[start, start*self, start*self^2, start*self^3], [start*self^4, start*self^5, start*self^6, start*self^7], ...`.
243    fn shifted_powers_packed<P: PackedField<Scalar = Self>>(&self, start: Self) -> Powers<P> {
244        let mut current = P::from_f(start);
245        let slice = current.as_slice_mut();
246        for i in 1..P::WIDTH {
247            slice[i] = slice[i - 1].clone() * self.clone();
248        }
249
250        Powers {
251            base: P::from_f(self.clone()).exp_u64(P::WIDTH as u64),
252            current,
253        }
254    }
255
256    /// Compute the dot product of two vectors.
257    fn dot_product<const N: usize>(u: &[Self; N], v: &[Self; N]) -> Self {
258        u.iter().zip(v).map(|(x, y)| x.clone() * y.clone()).sum()
259    }
260
261    /// Allocates a vector of zero elements of length `len`. Many operating systems zero pages
262    /// before assigning them to a userspace process. In that case, our process should not need to
263    /// write zeros, which would be redundant. However, the compiler may not always recognize this.
264    ///
265    /// In particular, `vec![Self::ZERO; len]` appears to result in redundant userspace zeroing.
266    /// This is the default implementation, but implementors may wish to provide their own
267    /// implementation which transmutes something like `vec![0u32; len]`.
268    #[inline]
269    fn zero_vec(len: usize) -> Vec<Self> {
270        vec![Self::ZERO; len]
271    }
272}
273
274/// An element of a finite field.
275pub trait Field:
276    FieldAlgebra<F = Self>
277    + Packable
278    + 'static
279    + Copy
280    + Div<Self, Output = Self>
281    + Eq
282    + Hash
283    + Send
284    + Sync
285    + Display
286    + Serialize
287    + DeserializeOwned
288{
289    type Packing: PackedField<Scalar = Self>;
290
291    /// A generator of this field's entire multiplicative group.
292    const GENERATOR: Self;
293
294    fn is_zero(&self) -> bool {
295        *self == Self::ZERO
296    }
297
298    fn is_one(&self) -> bool {
299        *self == Self::ONE
300    }
301
302    /// self / 2^exp
303    #[must_use]
304    #[inline]
305    fn div_2exp_u64(&self, exp: u64) -> Self {
306        *self / Self::TWO.exp_u64(exp)
307    }
308
309    /// Exponentiation by a `u64` power. This is similar to `exp_u64`, but more general in that it
310    /// can be used with `FieldAlgebra`s, not just this concrete field.
311    ///
312    /// The default implementation uses naive square and multiply. Implementations may want to
313    /// override this and handle certain powers with more optimal addition chains.
314    #[must_use]
315    #[inline]
316    fn exp_u64_generic<FA: FieldAlgebra<F = Self>>(val: FA, power: u64) -> FA {
317        exp_u64_by_squaring(val, power)
318    }
319
320    /// The multiplicative inverse of this field element, if it exists.
321    ///
322    /// NOTE: The inverse of `0` is undefined and will return `None`.
323    #[must_use]
324    fn try_inverse(&self) -> Option<Self>;
325
326    #[must_use]
327    fn inverse(&self) -> Self {
328        self.try_inverse().expect("Tried to invert zero")
329    }
330
331    /// Computes input/2.
332    /// Should be overwritten by most field implementations to use bitshifts.
333    /// Will error if the field characteristic is 2.
334    #[must_use]
335    fn halve(&self) -> Self {
336        let half = Self::TWO
337            .try_inverse()
338            .expect("Cannot divide by 2 in fields with characteristic 2");
339        *self * half
340    }
341
342    fn order() -> BigUint;
343
344    /// A list of (factor, exponent) pairs.
345    fn multiplicative_group_factors() -> Vec<(BigUint, usize)> {
346        let primality_test = MillerRabin { error_bits: 128 };
347        let composite_splitter = PollardRho;
348        let factorizer = FactorizerFromSplitter {
349            primality_test,
350            composite_splitter,
351        };
352        let n = Self::order() - BigUint::one();
353        factorizer.factor_counts(&n)
354    }
355
356    #[inline]
357    fn bits() -> usize {
358        Self::order().bits() as usize
359    }
360}
361
362pub trait PrimeField: Field + Ord {
363    fn as_canonical_biguint(&self) -> BigUint;
364}
365
366/// A prime field of order less than `2^64`.
367pub trait PrimeField64: PrimeField {
368    const ORDER_U64: u64;
369
370    /// Return the representative of `value` that is less than `ORDER_U64`.
371    fn as_canonical_u64(&self) -> u64;
372
373    /// Convert a field element to a `u64` such that any two field elements
374    /// are converted to the same `u64` if and only if they represent the same value.
375    ///
376    /// This will be the fastest way to convert a field element to a `u64` and
377    /// is intended for use in hashing. It will also be consistent across different targets.
378    fn to_unique_u64(&self) -> u64 {
379        // A simple default which is optimal for some fields.
380        self.as_canonical_u64()
381    }
382}
383
384/// A prime field of order less than `2^32`.
385pub trait PrimeField32: PrimeField64 {
386    const ORDER_U32: u32;
387
388    /// Return the representative of `value` that is less than `ORDER_U32`.
389    fn as_canonical_u32(&self) -> u32;
390
391    /// Convert a field element to a `u32` such that any two field elements
392    /// are converted to the same `u32` if and only if they represent the same value.
393    ///
394    /// This will be the fastest way to convert a field element to a `u32` and
395    /// is intended for use in hashing. It will also be consistent across different targets.
396    fn to_unique_u32(&self) -> u32 {
397        // A simple default which is optimal for some fields.
398        self.as_canonical_u32()
399    }
400}
401
402/// A commutative algebra over an extension field.
403///
404/// Mathematically, this trait captures a slightly more interesting structure than the above one liner.
405/// As implemented here, A FieldExtensionAlgebra `FEA` over and extension field `EF` is
406/// really the result of applying extension of scalars to a FieldAlgebra `FA` to lift `FA`
407/// from an algebra over `F` to an algebra over `EF` and so `FEA = EF ⊗ FA` where the tensor
408/// product is over `F`.
409pub trait FieldExtensionAlgebra<Base: FieldAlgebra>:
410    FieldAlgebra
411    + From<Base>
412    + Add<Base, Output = Self>
413    + AddAssign<Base>
414    + Sub<Base, Output = Self>
415    + SubAssign<Base>
416    + Mul<Base, Output = Self>
417    + MulAssign<Base>
418{
419    const D: usize;
420
421    fn from_base(b: Base) -> Self;
422
423    /// Suppose this field extension is represented by the quotient
424    /// ring B[X]/(f(X)) where B is `Base` and f is an irreducible
425    /// polynomial of degree `D`. This function takes a slice `bs` of
426    /// length at exactly D, and constructs the field element
427    /// \sum_i bs[i] * X^i.
428    ///
429    /// NB: The value produced by this function fundamentally depends
430    /// on the choice of irreducible polynomial f. Care must be taken
431    /// to ensure portability if these values might ever be passed to
432    /// (or rederived within) another compilation environment where a
433    /// different f might have been used.
434    fn from_base_slice(bs: &[Base]) -> Self;
435
436    /// Similar to `core:array::from_fn`, with the same caveats as
437    /// `from_base_slice`.
438    fn from_base_fn<F: FnMut(usize) -> Base>(f: F) -> Self;
439    fn from_base_iter<I: Iterator<Item = Base>>(iter: I) -> Self;
440
441    /// Suppose this field extension is represented by the quotient
442    /// ring B[X]/(f(X)) where B is `Base` and f is an irreducible
443    /// polynomial of degree `D`. This function takes a field element
444    /// \sum_i bs[i] * X^i and returns the coefficients as a slice
445    /// `bs` of length at most D containing, from lowest degree to
446    /// highest.
447    ///
448    /// NB: The value produced by this function fundamentally depends
449    /// on the choice of irreducible polynomial f. Care must be taken
450    /// to ensure portability if these values might ever be passed to
451    /// (or rederived within) another compilation environment where a
452    /// different f might have been used.
453    fn as_base_slice(&self) -> &[Base];
454
455    /// Suppose this field extension is represented by the quotient
456    /// ring B[X]/(f(X)) where B is `Base` and f is an irreducible
457    /// polynomial of degree `D`. This function returns the field
458    /// element `X^exponent` if `exponent < D` and panics otherwise.
459    /// (The fact that f is not known at the point that this function
460    /// is defined prevents implementing exponentiation of higher
461    /// powers since the reduction cannot be performed.)
462    ///
463    /// NB: The value produced by this function fundamentally depends
464    /// on the choice of irreducible polynomial f. Care must be taken
465    /// to ensure portability if these values might ever be passed to
466    /// (or rederived within) another compilation environment where a
467    /// different f might have been used.
468    fn monomial(exponent: usize) -> Self {
469        assert!(exponent < Self::D, "requested monomial of too high degree");
470        let mut vec = vec![Base::ZERO; Self::D];
471        vec[exponent] = Base::ONE;
472        Self::from_base_slice(&vec)
473    }
474}
475
476pub trait ExtensionField<Base: Field>: Field + FieldExtensionAlgebra<Base> {
477    type ExtensionPacking: FieldExtensionAlgebra<Base::Packing, F = Self>
478        + 'static
479        + Copy
480        + Send
481        + Sync;
482
483    #[inline(always)]
484    fn is_in_basefield(&self) -> bool {
485        self.as_base_slice()[1..].iter().all(Field::is_zero)
486    }
487
488    fn as_base(&self) -> Option<Base> {
489        if self.is_in_basefield() {
490            Some(self.as_base_slice()[0])
491        } else {
492            None
493        }
494    }
495
496    /// Construct an iterator which returns powers of `self` packed into `ExtensionPacking` elements.
497    ///
498    /// E.g. if `PACKING::WIDTH = 4` this returns the elements:
499    /// `[self^0, self^1, self^2, self^3], [self^4, self^5, self^6, self^7], ...`.
500    fn ext_powers_packed(&self) -> Powers<Self::ExtensionPacking> {
501        let powers = self.powers().take(Base::Packing::WIDTH + 1).collect_vec();
502        // Transpose first WIDTH powers
503        let current = Self::ExtensionPacking::from_base_fn(|i| {
504            Base::Packing::from_fn(|j| powers[j].as_base_slice()[i])
505        });
506        // Broadcast self^WIDTH
507        let multiplier = Self::ExtensionPacking::from_base_fn(|i| {
508            Base::Packing::from(powers[Base::Packing::WIDTH].as_base_slice()[i])
509        });
510
511        Powers {
512            base: multiplier,
513            current,
514        }
515    }
516}
517
518impl<F: Field> ExtensionField<F> for F {
519    type ExtensionPacking = F::Packing;
520}
521
522impl<FA: FieldAlgebra> FieldExtensionAlgebra<FA> for FA {
523    const D: usize = 1;
524
525    fn from_base(b: FA) -> Self {
526        b
527    }
528
529    fn from_base_slice(bs: &[FA]) -> Self {
530        assert_eq!(bs.len(), 1);
531        bs[0].clone()
532    }
533
534    fn from_base_iter<I: Iterator<Item = FA>>(mut iter: I) -> Self {
535        iter.next().unwrap()
536    }
537
538    fn from_base_fn<F: FnMut(usize) -> FA>(mut f: F) -> Self {
539        f(0)
540    }
541
542    #[inline(always)]
543    fn as_base_slice(&self) -> &[FA] {
544        slice::from_ref(self)
545    }
546}
547
548/// A field which supplies information like the two-adicity of its multiplicative group, and methods
549/// for obtaining two-adic generators.
550pub trait TwoAdicField: Field {
551    /// The number of factors of two in this field's multiplicative group.
552    const TWO_ADICITY: usize;
553
554    /// Returns a generator of the multiplicative group of order `2^bits`.
555    /// Assumes `bits <= TWO_ADICITY`, otherwise the result is undefined.
556    #[must_use]
557    fn two_adic_generator(bits: usize) -> Self;
558}
559
560/// An iterator which returns the powers of a base element `b` shifted by current `c`: `c, c * b, c * b^2, ...`.
561#[derive(Clone, Debug)]
562pub struct Powers<F> {
563    pub base: F,
564    pub current: F,
565}
566
567impl<FA: FieldAlgebra> Iterator for Powers<FA> {
568    type Item = FA;
569
570    fn next(&mut self) -> Option<FA> {
571        let result = self.current.clone();
572        self.current *= self.base.clone();
573        Some(result)
574    }
575}