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::{array, slice};
8
9use num_bigint::BigUint;
10use p3_maybe_rayon::prelude::{ParallelIterator, ParallelSlice};
11use p3_util::iter_array_chunks_padded;
12use serde::Serialize;
13use serde::de::DeserializeOwned;
14
15use crate::exponentiation::bits_u64;
16use crate::integers::{QuotientMap, from_integer_types};
17use crate::packed::PackedField;
18use crate::{Packable, PackedFieldExtension, PackedValue};
19
20/// A commutative ring, `R`, with prime characteristic, `p`.
21///
22/// This permits elements like:
23/// - A single finite field element.
24/// - A symbolic expression which would evaluate to a field element.
25/// - An array of finite field elements.
26/// - A polynomial with coefficients in a finite field.
27///
28/// ### Mathematical Description
29///
30/// Mathematically, a commutative ring is a set of objects which supports an addition-like
31/// like operation, `+`, and a multiplication-like operation `*`.
32///
33/// Let `x, y, z` denote arbitrary elements of the set.
34///
35/// Then, an operation is addition-like if it satisfies the following properties:
36/// - Commutativity => `x + y = y + x`
37/// - Associativity => `x + (y + z) = (x + y) + z`
38/// - Unit => There exists an identity element `ZERO` satisfying `x + ZERO = x`.
39/// - Inverses => For every `x` there exists a unique inverse `(-x)` satisfying `x + (-x) = ZERO`
40///
41/// Similarly, an operation is multiplication-like if it satisfies the following properties:
42/// - Commutativity => `x * y = y * x`
43/// - Associativity => `x * (y * z) = (x * y) * z`
44/// - Unit => There exists an identity element `ONE` satisfying `x * ONE = x`.
45/// - Distributivity => The two operations `+` and `*` must together satisfy `x * (y + z) = (x * y) + (x * z)`
46///
47/// Unlike in the addition case, we do not require inverses to exist with respect to `*`.
48///
49/// The simplest examples of commutative rings are the integers (`ℤ`), and the integers mod `N` (`ℤ/N`).
50///
51/// The characteristic of a ring is the smallest positive integer `r` such that `0 = r . 1 = 1 + 1 + ... + 1 (r times)`.
52/// For example, the characteristic of the modulo ring `ℤ/N` is `N`.
53///
54/// Rings with prime characteristic are particularly special due to their close relationship with finite fields.
55pub trait PrimeCharacteristicRing:
56    Sized
57    + Default
58    + Clone
59    + Add<Output = Self>
60    + AddAssign
61    + Sub<Output = Self>
62    + SubAssign
63    + Neg<Output = Self>
64    + Mul<Output = Self>
65    + MulAssign
66    + Sum
67    + Product
68    + Debug
69{
70    /// The field `ℤ/p` where the characteristic of this ring is p.
71    type PrimeSubfield: PrimeField;
72
73    /// The additive identity of the ring.
74    ///
75    /// For every element `a` in the ring we require the following properties:
76    ///
77    /// `a + ZERO = ZERO + a = a,`
78    ///
79    /// `a + (-a) = (-a) + a = ZERO.`
80    const ZERO: Self;
81
82    /// The multiplicative identity of the ring.
83    ///
84    /// For every element `a` in the ring we require the following property:
85    ///
86    /// `a*ONE = ONE*a = a.`
87    const ONE: Self;
88
89    /// The element in the ring given by `ONE + ONE`.
90    ///
91    /// This is provided as a convenience as `TWO` occurs regularly in
92    /// the proving system. This also is slightly faster than computing
93    /// it via addition. Note that multiplication by `TWO` is discouraged.
94    /// Instead of `a * TWO` use `a.double()` which will be faster.
95    ///
96    /// If the field has characteristic 2 this is equal to ZERO.
97    const TWO: Self;
98
99    /// The element in the ring given by `-ONE`.
100    ///
101    /// This is provided as a convenience as `NEG_ONE` occurs regularly in
102    /// the proving system. This also is slightly faster than computing
103    /// it via negation. Note that where possible `NEG_ONE` should be absorbed
104    /// into mathematical operations. For example `a - b` will be faster
105    /// than `a + NEG_ONE * b` and similarly `(-b)` is faster than `NEG_ONE * b`.
106    ///
107    /// If the field has characteristic 2 this is equal to ONE.
108    const NEG_ONE: Self;
109
110    /// Embed an element of the prime field `ℤ/p` into the ring `R`.
111    ///
112    /// Given any element `[r] ∈ ℤ/p`, represented by an integer `r` between `0` and `p - 1`
113    /// `from_prime_subfield([r])` will be equal to:
114    ///
115    /// `Self::ONE + ... + Self::ONE (r times)`
116    fn from_prime_subfield(f: Self::PrimeSubfield) -> Self;
117
118    /// Return `Self::ONE` if `b` is `true` and `Self::ZERO` if `b` is `false`.
119    #[must_use]
120    #[inline(always)]
121    fn from_bool(b: bool) -> Self {
122        // Some rings might reimplement this to avoid the branch.
123        if b { Self::ONE } else { Self::ZERO }
124    }
125
126    from_integer_types!(
127        u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
128    );
129
130    /// The elementary function `double(a) = 2*a`.
131    ///
132    /// This function should be preferred over calling `a + a` or `TWO * a` as a faster implementation may be available for some rings.
133    /// If the field has characteristic 2 then this returns 0.
134    #[must_use]
135    #[inline(always)]
136    fn double(&self) -> Self {
137        self.clone() + self.clone()
138    }
139
140    /// The elementary function `square(a) = a^2`.
141    ///
142    /// This function should be preferred over calling `a * a`, as a faster implementation may be available for some rings.
143    #[must_use]
144    #[inline(always)]
145    fn square(&self) -> Self {
146        self.clone() * self.clone()
147    }
148
149    /// The elementary function `cube(a) = a^3`.
150    ///
151    /// This function should be preferred over calling `a * a * a`, as a faster implementation may be available for some rings.
152    #[must_use]
153    #[inline(always)]
154    fn cube(&self) -> Self {
155        self.square() * self.clone()
156    }
157
158    /// Computes the arithmetic generalization of boolean `xor`.
159    ///
160    /// For boolean inputs, `x ^ y = x + y - 2 xy`.
161    #[must_use]
162    #[inline(always)]
163    fn xor(&self, y: &Self) -> Self {
164        self.clone() + y.clone() - self.clone() * y.clone().double()
165    }
166
167    /// Computes the arithmetic generalization of a triple `xor`.
168    ///
169    /// For boolean inputs `x ^ y ^ z = x + y + z - 2(xy + xz + yz) + 4xyz`.
170    #[must_use]
171    #[inline(always)]
172    fn xor3(&self, y: &Self, z: &Self) -> Self {
173        self.xor(y).xor(z)
174    }
175
176    /// Computes the arithmetic generalization of `andnot`.
177    ///
178    /// For boolean inputs `(!x) & y = (1 - x)y`.
179    #[must_use]
180    #[inline(always)]
181    fn andn(&self, y: &Self) -> Self {
182        (Self::ONE - self.clone()) * y.clone()
183    }
184
185    /// The vanishing polynomial for boolean values: `x * (1 - x)`.
186    ///
187    /// This is a polynomial of degree `2` that evaluates to `0` if the input is `0` or `1`.
188    /// If our space is a field, then this will be nonzero on all other inputs.
189    #[must_use]
190    #[inline(always)]
191    fn bool_check(&self) -> Self {
192        // We use `x * (1 - x)` instead of `x * (x - 1)` as this lets us delegate to the `andn` function.
193        self.andn(self)
194    }
195
196    /// Exponentiation by a `u64` power.
197    ///
198    /// This uses the standard square and multiply approach.
199    /// For specific powers regularly used and known in advance,
200    /// this will be slower than custom addition chain exponentiation.
201    #[must_use]
202    #[inline]
203    fn exp_u64(&self, power: u64) -> Self {
204        let mut current = self.clone();
205        let mut product = Self::ONE;
206
207        for j in 0..bits_u64(power) {
208            if (power >> j) & 1 != 0 {
209                product *= current.clone();
210            }
211            current = current.square();
212        }
213        product
214    }
215
216    /// Exponentiation by a small constant power.
217    ///
218    /// For a collection of small values we implement custom multiplication chain circuits which can be faster than the
219    /// simpler square and multiply approach.
220    ///
221    /// For large values this defaults back to `self.exp_u64`.
222    #[must_use]
223    #[inline(always)]
224    fn exp_const_u64<const POWER: u64>(&self) -> Self {
225        match POWER {
226            0 => Self::ONE,
227            1 => self.clone(),
228            2 => self.square(),
229            3 => self.cube(),
230            4 => self.square().square(),
231            5 => self.square().square() * self.clone(),
232            6 => self.square().cube(),
233            7 => {
234                let x2 = self.square();
235                let x3 = x2.clone() * self.clone();
236                let x4 = x2.square();
237                x3 * x4
238            }
239            _ => self.exp_u64(POWER),
240        }
241    }
242
243    /// The elementary function `exp_power_of_2(a, power_log) = a^{2^power_log}`.
244    ///
245    /// Computed via repeated squaring.
246    #[must_use]
247    #[inline]
248    fn exp_power_of_2(&self, power_log: usize) -> Self {
249        let mut res = self.clone();
250        for _ in 0..power_log {
251            res = res.square();
252        }
253        res
254    }
255
256    /// The elementary function `mul_2exp_u64(a, exp) = a * 2^{exp}`.
257    ///
258    /// Here `2^{exp}` is computed using the square and multiply approach.
259    #[must_use]
260    #[inline]
261    fn mul_2exp_u64(&self, exp: u64) -> Self {
262        self.clone() * Self::TWO.exp_u64(exp)
263    }
264
265    /// Construct an iterator which returns powers of `self`: `self^0, self^1, self^2, ...`.
266    #[must_use]
267    #[inline]
268    fn powers(&self) -> Powers<Self> {
269        self.shifted_powers(Self::ONE)
270    }
271
272    /// Construct an iterator which returns powers of `self` shifted by `start`: `start, start*self^1, start*self^2, ...`.
273    #[must_use]
274    #[inline]
275    fn shifted_powers(&self, start: Self) -> Powers<Self> {
276        Powers {
277            base: self.clone(),
278            current: start,
279        }
280    }
281
282    /// Compute the dot product of two vectors.
283    #[must_use]
284    #[inline]
285    fn dot_product<const N: usize>(u: &[Self; N], v: &[Self; N]) -> Self {
286        u.iter().zip(v).map(|(x, y)| x.clone() * y.clone()).sum()
287    }
288
289    /// Compute the sum of a slice of elements whose length is a compile time constant.
290    ///
291    /// The rust compiler doesn't realize that add is associative
292    /// so we help it out and minimize the dependency chains by hand.
293    /// Thus while this function has the same throughput as `input.iter().sum()`,
294    /// it will usually have much lower latency.
295    ///
296    /// # Panics
297    ///
298    /// May panic if the length of the input slice is not equal to `N`.
299    #[must_use]
300    #[inline]
301    fn sum_array<const N: usize>(input: &[Self]) -> Self {
302        // It looks a little strange but using a const parameter and an assert_eq! instead of
303        // using input.len() leads to a significant performance improvement.
304        // We could make this input &[Self; N] but that would require sticking .try_into().unwrap() everywhere.
305        // Checking godbolt, the compiler seems to unroll everything anyway.
306        assert_eq!(N, input.len());
307
308        // For `N <= 8` we implement a tree sum structure and for `N > 8` we break the input into
309        // chunks of `8`, perform a tree sum on each chunk and sum the results. The parameter `8`
310        // was determined experimentally by testing the speed of the poseidon2 internal layer computations.
311        // This is a useful benchmark as we have a mix of summations of size 15, 23 with other work in between.
312        // I only tested this on `AVX2` though so there might be a better value for other architectures.
313        match N {
314            0 => Self::ZERO,
315            1 => input[0].clone(),
316            2 => input[0].clone() + input[1].clone(),
317            3 => input[0].clone() + input[1].clone() + input[2].clone(),
318            4 => (input[0].clone() + input[1].clone()) + (input[2].clone() + input[3].clone()),
319            5 => Self::sum_array::<4>(&input[..4]) + Self::sum_array::<1>(&input[4..]),
320            6 => Self::sum_array::<4>(&input[..4]) + Self::sum_array::<2>(&input[4..]),
321            7 => Self::sum_array::<4>(&input[..4]) + Self::sum_array::<3>(&input[4..]),
322            8 => Self::sum_array::<4>(&input[..4]) + Self::sum_array::<4>(&input[4..]),
323            _ => {
324                // We know that N > 8 here so this saves an add over the usual
325                // initialisation of acc to Self::ZERO.
326                let mut acc = Self::sum_array::<8>(&input[..8]);
327                for i in (16..=N).step_by(8) {
328                    acc += Self::sum_array::<8>(&input[(i - 8)..i])
329                }
330                // This would be much cleaner if we could use const generic expressions but
331                // this will do for now.
332                match N & 7 {
333                    0 => acc,
334                    1 => acc + Self::sum_array::<1>(&input[(8 * (N / 8))..]),
335                    2 => acc + Self::sum_array::<2>(&input[(8 * (N / 8))..]),
336                    3 => acc + Self::sum_array::<3>(&input[(8 * (N / 8))..]),
337                    4 => acc + Self::sum_array::<4>(&input[(8 * (N / 8))..]),
338                    5 => acc + Self::sum_array::<5>(&input[(8 * (N / 8))..]),
339                    6 => acc + Self::sum_array::<6>(&input[(8 * (N / 8))..]),
340                    7 => acc + Self::sum_array::<7>(&input[(8 * (N / 8))..]),
341                    _ => unreachable!(),
342                }
343            }
344        }
345    }
346
347    /// Allocates a vector of zero elements of length `len`. Many operating systems zero pages
348    /// before assigning them to a userspace process. In that case, our process should not need to
349    /// write zeros, which would be redundant. However, the compiler may not always recognize this.
350    ///
351    /// In particular, `vec![Self::ZERO; len]` appears to result in redundant userspace zeroing.
352    /// This is the default implementation, but implementors may wish to provide their own
353    /// implementation which transmutes something like `vec![0u32; len]`.
354    #[must_use]
355    #[inline]
356    fn zero_vec(len: usize) -> Vec<Self> {
357        vec![Self::ZERO; len]
358    }
359}
360
361/// A vector space `V` over `F` with a fixed basis. Fixing the basis allows elements of `V` to be
362/// converted to and from `DIMENSION` many elements of `F` which are interpreted as basis coefficients.
363///
364/// We usually expect `F` to be a field but do not enforce this and so allow it to be just a ring.
365/// This lets every ring implement `BasedVectorSpace<Self>` and is useful in a couple of other cases.
366///
367/// ## Safety
368/// We make no guarantees about consistency of the choice of basis across different versions of Plonky3.
369/// If this choice of basis changes, the behaviour of `BasedVectorSpace` will also change. Due to this,
370/// we recommend avoiding using this trait unless absolutely necessary.
371///
372/// ### Mathematical Description
373/// Given a vector space, `A` over `F`, a basis is a set of elements `B = {b_0, ..., b_{n-1}}`
374/// in `A` such that, given any element `a`, we can find a unique set of `n` elements of `F`,
375/// `f_0, ..., f_{n - 1}` satisfying `a = f_0 b_0 + ... + f_{n - 1} b_{n - 1}`. Thus the choice
376/// of `B` gives rise to a natural linear map between the vector space `A` and the canonical
377/// `n` dimensional vector space `F^n`.
378///
379/// This allows us to map between elements of `A` and arrays of `n` elements of `F`.
380/// Clearly this map depends entirely on the choice of basis `B` which may change
381/// across versions of Plonky3.
382///
383/// The situation is slightly more complicated in cases where `F` is not a field but boils down
384/// to an identical description once we enforce that `A` is a free module over `F`.
385pub trait BasedVectorSpace<F: PrimeCharacteristicRing>: Sized {
386    /// The dimension of the vector space, i.e. the number of elements in
387    /// its basis.
388    const DIMENSION: usize;
389
390    /// Fixes a basis for the algebra `A` and uses this to
391    /// map an element of `A` to a slice of `DIMENSION` `F` elements.
392    ///
393    /// # Safety
394    ///
395    /// The value produced by this function fundamentally depends
396    /// on the choice of basis. Care must be taken
397    /// to ensure portability if these values might ever be passed to
398    /// (or rederived within) another compilation environment where a
399    /// different basis might have been used.
400    #[must_use]
401    fn as_basis_coefficients_slice(&self) -> &[F];
402
403    /// Fixes a basis for the algebra `A` and uses this to
404    /// map `DIMENSION` `F` elements to an element of `A`.
405    ///
406    /// # Safety
407    ///
408    /// The value produced by this function fundamentally depends
409    /// on the choice of basis. Care must be taken
410    /// to ensure portability if these values might ever be passed to
411    /// (or rederived within) another compilation environment where a
412    /// different basis might have been used.
413    ///
414    /// Returns `None` if the length of the slice is different to `DIMENSION`.
415    #[must_use]
416    #[inline]
417    fn from_basis_coefficients_slice(slice: &[F]) -> Option<Self> {
418        Self::from_basis_coefficients_iter(slice.iter().cloned())
419    }
420
421    /// Fixes a basis for the algebra `A` and uses this to
422    /// map `DIMENSION` `F` elements to an element of `A`. Similar
423    /// to `core:array::from_fn`, the `DIMENSION` `F` elements are
424    /// given by `Fn(0), ..., Fn(DIMENSION - 1)` called in that order.
425    ///
426    /// # Safety
427    ///
428    /// The value produced by this function fundamentally depends
429    /// on the choice of basis. Care must be taken
430    /// to ensure portability if these values might ever be passed to
431    /// (or rederived within) another compilation environment where a
432    /// different basis might have been used.
433    #[must_use]
434    fn from_basis_coefficients_fn<Fn: FnMut(usize) -> F>(f: Fn) -> Self;
435
436    /// Fixes a basis for the algebra `A` and uses this to
437    /// map `DIMENSION` `F` elements to an element of `A`.
438    ///
439    /// # Safety
440    ///
441    /// The value produced by this function fundamentally depends
442    /// on the choice of basis. Care must be taken
443    /// to ensure portability if these values might ever be passed to
444    /// (or rederived within) another compilation environment where a
445    /// different basis might have been used.
446    ///
447    /// Returns `None` if the length of the iterator is different to `DIMENSION`.
448    #[must_use]
449    fn from_basis_coefficients_iter<I: ExactSizeIterator<Item = F>>(iter: I) -> Option<Self>;
450
451    /// Given a basis for the Algebra `A`, return the i'th basis element.
452    ///
453    /// # Safety
454    ///
455    /// The value produced by this function fundamentally depends
456    /// on the choice of basis. Care must be taken
457    /// to ensure portability if these values might ever be passed to
458    /// (or rederived within) another compilation environment where a
459    /// different basis might have been used.
460    ///
461    /// Returns `None` if `i` is greater than or equal to `DIMENSION`.
462    #[must_use]
463    #[inline]
464    fn ith_basis_element(i: usize) -> Option<Self> {
465        (i < Self::DIMENSION).then(|| Self::from_basis_coefficients_fn(|j| F::from_bool(i == j)))
466    }
467
468    /// Convert from a vector of `Self` to a vector of `F` by flattening the basis coefficients.
469    ///
470    /// Depending on the `BasedVectorSpace` this may be essentially a no-op and should certainly
471    /// be reimplemented in those cases.
472    ///
473    /// # Safety
474    ///
475    /// The value produced by this function fundamentally depends
476    /// on the choice of basis. Care must be taken
477    /// to ensure portability if these values might ever be passed to
478    /// (or rederived within) another compilation environment where a
479    /// different basis might have been used.
480    #[must_use]
481    #[inline]
482    fn flatten_to_base(vec: Vec<Self>) -> Vec<F> {
483        vec.into_iter()
484            .flat_map(|x| x.as_basis_coefficients_slice().to_vec())
485            .collect()
486    }
487
488    /// Convert from a vector of `F` to a vector of `Self` by combining the basis coefficients.
489    ///
490    /// Depending on the `BasedVectorSpace` this may be essentially a no-op and should certainly
491    /// be reimplemented in those cases.
492    ///
493    /// # Panics
494    /// This will panic if the length of `vec` is not a multiple of `Self::DIMENSION`.
495    ///
496    /// # Safety
497    ///
498    /// The value produced by this function fundamentally depends
499    /// on the choice of basis. Care must be taken
500    /// to ensure portability if these values might ever be passed to
501    /// (or rederived within) another compilation environment where a
502    /// different basis might have been used.
503    #[must_use]
504    #[inline]
505    fn reconstitute_from_base(vec: Vec<F>) -> Vec<Self>
506    where
507        F: Sync,
508        Self: Send,
509    {
510        assert_eq!(vec.len() % Self::DIMENSION, 0);
511
512        vec.par_chunks_exact(Self::DIMENSION)
513            .map(|chunk| {
514                Self::from_basis_coefficients_slice(chunk)
515                    .expect("Chunk length not equal to dimension")
516            })
517            .collect()
518    }
519}
520
521impl<F: PrimeCharacteristicRing> BasedVectorSpace<F> for F {
522    const DIMENSION: usize = 1;
523
524    #[inline]
525    fn as_basis_coefficients_slice(&self) -> &[F] {
526        slice::from_ref(self)
527    }
528
529    #[inline]
530    fn from_basis_coefficients_fn<Fn: FnMut(usize) -> F>(mut f: Fn) -> Self {
531        f(0)
532    }
533
534    #[inline]
535    fn from_basis_coefficients_iter<I: ExactSizeIterator<Item = F>>(mut iter: I) -> Option<Self> {
536        (iter.len() == 1).then(|| iter.next().unwrap()) // Unwrap will not panic as we know the length is 1.
537    }
538
539    #[inline]
540    fn flatten_to_base(vec: Vec<Self>) -> Vec<F> {
541        vec
542    }
543
544    #[inline]
545    fn reconstitute_from_base(vec: Vec<F>) -> Vec<Self> {
546        vec
547    }
548}
549
550/// A ring implements `InjectiveMonomial<N>` if the algebraic function
551/// `f(x) = x^N` is an injective map on elements of the ring.
552///
553/// We do not enforce that this map be invertible as there are useful
554/// cases such as polynomials or symbolic expressions where no inverse exists.
555///
556/// However, if the ring is a field with order `q` or an array of such field elements,
557/// then `f(x) = x^N` will be injective if and only if it is invertible and so in
558/// such cases this monomial acts as a permutation. Moreover, this will occur
559/// exactly when `N` and `q - 1` are relatively prime i.e. `gcd(N, q - 1) = 1`.
560pub trait InjectiveMonomial<const N: u64>: PrimeCharacteristicRing {
561    /// Compute `x -> x^n` for a given `n > 1` such that this
562    /// map is injective.
563    #[must_use]
564    #[inline]
565    fn injective_exp_n(&self) -> Self {
566        self.exp_const_u64::<N>()
567    }
568}
569
570/// A ring implements `PermutationMonomial<N>` if the algebraic function
571/// `f(x) = x^N` is invertible and thus acts as a permutation on elements of the ring.
572///
573/// In all cases we care about, this means that we can find another integer `K` such
574/// that `x = x^{NK}` for all elements of our ring.
575pub trait PermutationMonomial<const N: u64>: InjectiveMonomial<N> {
576    /// Compute `x -> x^K` for a given `K > 1` such that
577    /// `x^{NK} = x` for all elements `x`.
578    #[must_use]
579    fn injective_exp_root_n(&self) -> Self;
580}
581
582/// A ring `R` implements `Algebra<F>` if there is an injective homomorphism
583///  from `F` into `R`; in particular only `F::ZERO` maps to `R::ZERO`.
584///
585/// For the most part, we will usually expect `F` to be a field but there
586/// are a few cases where it is handy to allow it to just be a ring. In
587/// particular, every ring naturally implements `Algebra<Self>`.
588///
589/// ### Mathematical Description
590///
591/// Let `x` and `y` denote arbitrary elements of `F`. Then
592/// we require that our map `from` has the properties:
593/// - Preserves Identity: `from(F::ONE) = R::ONE`
594/// - Commutes with Addition: `from(x + y) = from(x) + from(y)`
595/// - Commutes with Multiplication: `from(x * y) = from(x) * from(y)`
596///
597/// Such maps are known as ring homomorphisms and are injective if the
598/// only element which maps to `R::ZERO` is `F::ZERO`.
599///
600/// The existence of this map makes `R` into an `F`-module and hence an `F`-algebra.
601/// If, additionally, `R` is a field, then this makes `R` a field extension of `F`.
602pub trait Algebra<F>:
603    PrimeCharacteristicRing
604    + From<F>
605    + Add<F, Output = Self>
606    + AddAssign<F>
607    + Sub<F, Output = Self>
608    + SubAssign<F>
609    + Mul<F, Output = Self>
610    + MulAssign<F>
611{
612}
613
614// Every ring is an algebra over itself.
615impl<R: PrimeCharacteristicRing> Algebra<R> for R {}
616
617/// A collection of methods designed to help hash field elements.
618///
619/// Most fields will want to reimplement many/all of these methods as the default implementations
620/// are slow and involve converting to/from byte representations.
621pub trait RawDataSerializable: Sized {
622    /// The number of bytes which this field element occupies in memory.
623    /// Must be equal to the length of self.into_bytes().
624    const NUM_BYTES: usize;
625
626    /// Convert a field element into a collection of bytes.
627    #[must_use]
628    fn into_bytes(self) -> impl IntoIterator<Item = u8>;
629
630    /// Convert an iterator of field elements into an iterator of bytes.
631    #[must_use]
632    fn into_byte_stream(input: impl IntoIterator<Item = Self>) -> impl IntoIterator<Item = u8> {
633        input.into_iter().flat_map(|elem| elem.into_bytes())
634    }
635
636    /// Convert an iterator of field elements into an iterator of u32s.
637    ///
638    /// If `NUM_BYTES` does not divide `4`, multiple `F`s may be packed together to make a single `u32`. Furthermore,
639    /// if `NUM_BYTES * input.len()` does not divide `4`, the final `u32` will involve padding bytes which are set to `0`.
640    #[must_use]
641    fn into_u32_stream(input: impl IntoIterator<Item = Self>) -> impl IntoIterator<Item = u32> {
642        let bytes = Self::into_byte_stream(input);
643        iter_array_chunks_padded(bytes, 0).map(u32::from_le_bytes)
644    }
645
646    /// Convert an iterator of field elements into an iterator of u64s.
647    ///
648    /// If `NUM_BYTES` does not divide `8`, multiple `F`s may be packed together to make a single `u64`. Furthermore,
649    /// if `NUM_BYTES * input.len()` does not divide `8`, the final `u64` will involve padding bytes which are set to `0`.
650    #[must_use]
651    fn into_u64_stream(input: impl IntoIterator<Item = Self>) -> impl IntoIterator<Item = u64> {
652        let bytes = Self::into_byte_stream(input);
653        iter_array_chunks_padded(bytes, 0).map(u64::from_le_bytes)
654    }
655
656    /// Convert an iterator of field element arrays into an iterator of byte arrays.
657    ///
658    /// Converts an element `[F; N]` into the byte array `[[u8; N]; NUM_BYTES]`. This is
659    /// intended for use with vectorized hash functions which use vector operations
660    /// to compute several hashes in parallel.
661    #[must_use]
662    fn into_parallel_byte_streams<const N: usize>(
663        input: impl IntoIterator<Item = [Self; N]>,
664    ) -> impl IntoIterator<Item = [u8; N]> {
665        input.into_iter().flat_map(|vector| {
666            let bytes = vector.map(|elem| elem.into_bytes().into_iter().collect::<Vec<_>>());
667            (0..Self::NUM_BYTES).map(move |i| array::from_fn(|j| bytes[j][i]))
668        })
669    }
670
671    /// Convert an iterator of field element arrays into an iterator of u32 arrays.
672    ///
673    /// Converts an element `[F; N]` into the u32 array `[[u32; N]; NUM_BYTES/4]`. This is
674    /// intended for use with vectorized hash functions which use vector operations
675    /// to compute several hashes in parallel.
676    ///
677    /// This function is guaranteed to be equivalent to starting with `Iterator<[F; N]>` performing a transpose
678    /// operation to get `[Iterator<F>; N]`, calling `into_u32_stream` on each element to get `[Iterator<u32>; N]` and then
679    /// performing another transpose operation to get `Iterator<[u32; N]>`.
680    ///
681    /// If `NUM_BYTES` does not divide `4`, multiple `[F; N]`s may be packed together to make a single `[u32; N]`. Furthermore,
682    /// if `NUM_BYTES * input.len()` does not divide `4`, the final `[u32; N]` will involve padding bytes which are set to `0`.
683    #[must_use]
684    fn into_parallel_u32_streams<const N: usize>(
685        input: impl IntoIterator<Item = [Self; N]>,
686    ) -> impl IntoIterator<Item = [u32; N]> {
687        let bytes = Self::into_parallel_byte_streams(input);
688        iter_array_chunks_padded(bytes, [0; N]).map(|byte_array: [[u8; N]; 4]| {
689            array::from_fn(|i| u32::from_le_bytes(array::from_fn(|j| byte_array[j][i])))
690        })
691    }
692
693    /// Convert an iterator of field element arrays into an iterator of u64 arrays.
694    ///
695    /// Converts an element `[F; N]` into the u64 array `[[u64; N]; NUM_BYTES/8]`. This is
696    /// intended for use with vectorized hash functions which use vector operations
697    /// to compute several hashes in parallel.
698    ///
699    /// This function is guaranteed to be equivalent to starting with `Iterator<[F; N]>` performing a transpose
700    /// operation to get `[Iterator<F>; N]`, calling `into_u64_stream` on each element to get `[Iterator<u64>; N]` and then
701    /// performing another transpose operation to get `Iterator<[u64; N]>`.
702    ///
703    /// If `NUM_BYTES` does not divide `8`, multiple `[F; N]`s may be packed together to make a single `[u64; N]`. Furthermore,
704    /// if `NUM_BYTES * input.len()` does not divide `8`, the final `[u64; N]` will involve padding bytes which are set to `0`.
705    #[must_use]
706    fn into_parallel_u64_streams<const N: usize>(
707        input: impl IntoIterator<Item = [Self; N]>,
708    ) -> impl IntoIterator<Item = [u64; N]> {
709        let bytes = Self::into_parallel_byte_streams(input);
710        iter_array_chunks_padded(bytes, [0; N]).map(|byte_array: [[u8; N]; 8]| {
711            array::from_fn(|i| u64::from_le_bytes(array::from_fn(|j| byte_array[j][i])))
712        })
713    }
714}
715
716/// A field `F`. This permits both modular fields `ℤ/p` along with their field extensions.
717///
718/// A ring is a field if every element `x` has a unique multiplicative inverse `x^{-1}`
719/// which satisfies `x * x^{-1} = F::ONE`.
720pub trait Field:
721    Algebra<Self>
722    + RawDataSerializable
723    + Packable
724    + 'static
725    + Copy
726    + Div<Self, Output = Self>
727    + Eq
728    + Hash
729    + Send
730    + Sync
731    + Display
732    + Serialize
733    + DeserializeOwned
734{
735    type Packing: PackedField<Scalar = Self>;
736
737    /// A generator of this field's multiplicative group.
738    const GENERATOR: Self;
739
740    /// Check if the given field element is equal to the unique additive identity (ZERO).
741    #[must_use]
742    #[inline]
743    fn is_zero(&self) -> bool {
744        *self == Self::ZERO
745    }
746
747    /// Check if the given field element is equal to the unique multiplicative identity (ONE).
748    #[must_use]
749    #[inline]
750    fn is_one(&self) -> bool {
751        *self == Self::ONE
752    }
753
754    /// The multiplicative inverse of this field element, if it exists.
755    ///
756    /// NOTE: The inverse of `0` is undefined and will return `None`.
757    #[must_use]
758    fn try_inverse(&self) -> Option<Self>;
759
760    /// The multiplicative inverse of this field element.
761    ///
762    /// # Panics
763    /// The function will panic if the field element is `0`.
764    /// Use try_inverse if you want to handle this case.
765    #[must_use]
766    fn inverse(&self) -> Self {
767        self.try_inverse().expect("Tried to invert zero")
768    }
769
770    /// The elementary function `halve(a) = a/2`.
771    ///
772    /// # Panics
773    /// The function will panic if the field has characteristic 2.
774    #[must_use]
775    fn halve(&self) -> Self {
776        // This should be overwritten by most field implementations.
777        let half = Self::from_prime_subfield(
778            Self::PrimeSubfield::TWO
779                .try_inverse()
780                .expect("Cannot divide by 2 in fields with characteristic 2"),
781        );
782        *self * half
783    }
784
785    /// Divide by a given power of two. `div_2exp_u64(a, exp) = a/2^exp`
786    ///
787    /// # Panics
788    /// The function will panic if the field has characteristic 2.
789    #[must_use]
790    #[inline]
791    fn div_2exp_u64(&self, exp: u64) -> Self {
792        // This should be overwritten by most field implementations.
793        *self
794            * Self::from_prime_subfield(
795                Self::PrimeSubfield::TWO
796                    .try_inverse()
797                    .expect("Cannot divide by 2 in fields with characteristic 2")
798                    .exp_u64(exp),
799            )
800    }
801
802    /// Add two slices of field elements together, returning the result in the first slice.
803    ///
804    /// Makes use of packing to speed up the addition.
805    ///
806    /// This is optimal for cases where the two slices are small to medium length. E.g. between
807    /// `F::Packing::WIDTH` and roughly however many elements fit in a cache line.
808    ///
809    /// For larger slices, it's likely worthwhile to use parallelization before calling this.
810    /// Similarly if you need to add a large number of slices together, it's best to
811    /// break them into small chunks and call this on the smaller chunks.
812    ///
813    /// # Panics
814    /// The function will panic if the lengths of the two slices are not equal.
815    #[inline]
816    fn add_slices(slice_1: &mut [Self], slice_2: &[Self]) {
817        let (shorts_1, suffix_1) = Self::Packing::pack_slice_with_suffix_mut(slice_1);
818        let (shorts_2, suffix_2) = Self::Packing::pack_slice_with_suffix(slice_2);
819        debug_assert_eq!(shorts_1.len(), shorts_2.len());
820        debug_assert_eq!(suffix_1.len(), suffix_2.len());
821        for (x_1, &x_2) in shorts_1.iter_mut().zip(shorts_2) {
822            *x_1 += x_2;
823        }
824        for (x_1, &x_2) in suffix_1.iter_mut().zip(suffix_2) {
825            *x_1 += x_2;
826        }
827    }
828
829    /// The number of elements in the field.
830    ///
831    /// This will either be prime if the field is a PrimeField or a power of a
832    /// prime if the field is an extension field.
833    #[must_use]
834    fn order() -> BigUint;
835
836    /// The number of bits required to define an element of this field.
837    ///
838    /// Usually due to storage and practical reasons the memory size of
839    /// a field element will be a little larger than bits().
840    #[must_use]
841    #[inline]
842    fn bits() -> usize {
843        Self::order().bits() as usize
844    }
845}
846
847/// A field isomorphic to `ℤ/p` for some prime `p`.
848///
849/// There is a natural map from `ℤ` to `ℤ/p` which sends an integer `r` to its conjugacy class `[r]`.
850/// Canonically, each conjugacy class `[r]` can be represented by the unique integer `s` in `[0, p - 1)`
851/// satisfying `s = r mod p`. This however is often not the most convenient computational representation
852/// and so internal representations of field elements might differ from this and may change over time.
853pub trait PrimeField:
854    Field
855    + Ord
856    + QuotientMap<u8>
857    + QuotientMap<u16>
858    + QuotientMap<u32>
859    + QuotientMap<u64>
860    + QuotientMap<u128>
861    + QuotientMap<usize>
862    + QuotientMap<i8>
863    + QuotientMap<i16>
864    + QuotientMap<i32>
865    + QuotientMap<i64>
866    + QuotientMap<i128>
867    + QuotientMap<isize>
868{
869    /// Return the representative of `value` in canonical form
870    /// which lies in the range `0 <= x < self.order()`.
871    #[must_use]
872    fn as_canonical_biguint(&self) -> BigUint;
873}
874
875/// A prime field `ℤ/p` with order, `p < 2^64`.
876pub trait PrimeField64: PrimeField {
877    const ORDER_U64: u64;
878
879    /// Return the representative of `value` in canonical form
880    /// which lies in the range `0 <= x < ORDER_U64`.
881    #[must_use]
882    fn as_canonical_u64(&self) -> u64;
883
884    /// Convert a field element to a `u64` such that any two field elements
885    /// are converted to the same `u64` if and only if they represent the same value.
886    ///
887    /// This will be the fastest way to convert a field element to a `u64` and
888    /// is intended for use in hashing. It will also be consistent across different targets.
889    #[must_use]
890    #[inline(always)]
891    fn to_unique_u64(&self) -> u64 {
892        // A simple default which is optimal for some fields.
893        self.as_canonical_u64()
894    }
895}
896
897/// A prime field `ℤ/p` with order `p < 2^32`.
898pub trait PrimeField32: PrimeField64 {
899    const ORDER_U32: u32;
900
901    /// Return the representative of `value` in canonical form
902    /// which lies in the range `0 <= x < ORDER_U64`.
903    #[must_use]
904    fn as_canonical_u32(&self) -> u32;
905
906    /// Convert a field element to a `u32` such that any two field elements
907    /// are converted to the same `u32` if and only if they represent the same value.
908    ///
909    /// This will be the fastest way to convert a field element to a `u32` and
910    /// is intended for use in hashing. It will also be consistent across different targets.
911    #[must_use]
912    #[inline(always)]
913    fn to_unique_u32(&self) -> u32 {
914        // A simple default which is optimal for some fields.
915        self.as_canonical_u32()
916    }
917}
918
919/// A field `EF` which is also an algebra over a field `F`.
920///
921/// This provides a couple of convenience methods on top of the
922/// standard methods provided by `Field`, `Algebra<F>` and `BasedVectorSpace<F>`.
923///
924/// It also provides a type which handles packed vectors of extension field elements.
925pub trait ExtensionField<Base: Field>: Field + Algebra<Base> + BasedVectorSpace<Base> {
926    type ExtensionPacking: PackedFieldExtension<Base, Self> + 'static + Copy + Send + Sync;
927
928    /// Determine if the given element lies in the base field.
929    #[must_use]
930    fn is_in_basefield(&self) -> bool;
931
932    /// If the element lies in the base field project it down.
933    /// Otherwise return None.
934    #[must_use]
935    fn as_base(&self) -> Option<Base>;
936}
937
938// Every field is trivially a one dimensional extension over itself.
939impl<F: Field> ExtensionField<F> for F {
940    type ExtensionPacking = F::Packing;
941
942    #[inline]
943    fn is_in_basefield(&self) -> bool {
944        true
945    }
946
947    #[inline]
948    fn as_base(&self) -> Option<F> {
949        Some(*self)
950    }
951}
952
953/// A field which supplies information like the two-adicity of its multiplicative group, and methods
954/// for obtaining two-adic generators.
955pub trait TwoAdicField: Field {
956    /// The number of factors of two in this field's multiplicative group.
957    const TWO_ADICITY: usize;
958
959    /// Returns a generator of the multiplicative group of order `2^bits`.
960    /// Assumes `bits <= TWO_ADICITY`, otherwise the result is undefined.
961    #[must_use]
962    fn two_adic_generator(bits: usize) -> Self;
963}
964
965/// An iterator which returns the powers of a base element `b` shifted by current `c`: `c, c * b, c * b^2, ...`.
966#[derive(Clone, Debug)]
967pub struct Powers<F> {
968    pub base: F,
969    pub current: F,
970}
971
972impl<R: PrimeCharacteristicRing> Iterator for Powers<R> {
973    type Item = R;
974
975    fn next(&mut self) -> Option<R> {
976        let result = self.current.clone();
977        self.current *= self.base.clone();
978        Some(result)
979    }
980}