Skip to main content

p3_field/extension/
mod.rs

1use core::iter;
2
3use crate::field::Field;
4use crate::{Algebra, ExtensionField};
5
6mod binomial_extension;
7mod complex;
8mod packed_binomial_extension;
9mod packed_quintic_extension;
10mod quintic_extension;
11
12use alloc::vec::Vec;
13
14pub use binomial_extension::*;
15pub use complex::*;
16pub use packed_binomial_extension::*;
17pub use packed_quintic_extension::PackedQuinticTrinomialExtensionField;
18pub use quintic_extension::{QuinticTrinomialExtensionField, trinomial_quintic_mul};
19
20/// Trait for fields that support binomial extension of the form `F[X]/(X^D - W)`.
21///
22/// A type implementing this trait can define a degree-`D` extension field using an
23/// irreducible binomial polynomial `X^D - W`, where `W` is a nonzero constant in the base field.
24///
25/// This is used to construct extension fields with efficient arithmetic.
26pub trait BinomiallyExtendable<const D: usize>:
27    Field + BinomiallyExtendableAlgebra<Self, D>
28{
29    /// The constant coefficient `W` in the binomial `X^D - W`.
30    const W: Self;
31
32    /// A `D`-th root of unity derived from `W`.
33    ///
34    /// This is `W^((n - 1)/D)`, where `n` is the order of the field.
35    /// Valid only when `n = kD + 1` for some `k`.
36    const DTH_ROOT: Self;
37
38    /// A generator for the extension field, expressed as a degree-`D` polynomial.
39    ///
40    /// This is an array of size `D`, where each entry is a base field element.
41    const EXT_GENERATOR: [Self; D];
42}
43
44/// Trait for algebras which support binomial extensions of the form `A[X]/(X^D - W)`
45/// with `W` in the base field `F`.
46pub trait BinomiallyExtendableAlgebra<F: Field, const D: usize>: Algebra<F> {
47    /// Multiplication in the algebra extension ring `A<X> / (X^D - W)`.
48    ///
49    /// Some algebras may want to reimplement this with faster methods.
50    #[inline]
51    fn binomial_mul(a: &[Self; D], b: &[Self; D], res: &mut [Self; D], w: F) {
52        binomial_mul::<F, Self, Self, D>(a, b, res, w);
53    }
54
55    /// Addition of elements in the algebra extension ring `A<X> / (X^D - W)`.
56    ///
57    /// As addition has no dependence on `W` so this is equivalent
58    /// to an algorithm for adding arrays of elements of `A`.
59    ///
60    /// Some algebras may want to reimplement this with faster methods.
61    #[inline]
62    #[must_use]
63    fn binomial_add(a: &[Self; D], b: &[Self; D]) -> [Self; D] {
64        vector_add(a, b)
65    }
66
67    /// Subtraction of elements in the algebra extension ring `A<X> / (X^D - W)`.
68    ///
69    /// As subtraction has no dependence on `W` so this is equivalent
70    /// to an algorithm for subtracting arrays of elements of `A`.
71    ///
72    /// Some algebras may want to reimplement this with faster methods.
73    #[inline]
74    #[must_use]
75    fn binomial_sub(a: &[Self; D], b: &[Self; D]) -> [Self; D] {
76        vector_sub(a, b)
77    }
78
79    #[inline]
80    fn binomial_base_mul(lhs: [Self; D], rhs: Self) -> [Self; D] {
81        lhs.map(|x| x * rhs.clone())
82    }
83}
84
85/// Trait for extension fields that support Frobenius automorphisms.
86///
87/// The Frobenius automorphism is a field map `x ↦ x^n`,
88/// where `n` is the order of the base field.
89///
90/// This map is an automorphism of the field that fixes the base field.
91pub trait HasFrobenius<F: Field>: ExtensionField<F> {
92    /// Apply the Frobenius automorphism once.
93    ///
94    /// Equivalent to raising the element to the `n`th power.
95    #[must_use]
96    fn frobenius(&self) -> Self;
97
98    /// Apply the Frobenius automorphism `count` times.
99    ///
100    /// Equivalent to raising to the `n^count` power.
101    #[must_use]
102    fn repeated_frobenius(&self, count: usize) -> Self;
103
104    /// Computes the pseudo inverse of the given field element.
105    ///
106    /// Returns `0` if `self == 0`, and `1/self` otherwise.
107    /// In other words, returns `self^(n^D - 2)` where `D` is the extension degree.
108    #[must_use]
109    fn pseudo_inv(&self) -> Self;
110
111    /// Returns the full Galois orbit of the element under Frobenius.
112    ///
113    /// This is the sequence `[x, x^n, x^{n^2}, ..., x^{n^{D-1}}]`,
114    /// where `D` is the extension degree.
115    #[must_use]
116    fn galois_orbit(self) -> Vec<Self> {
117        iter::successors(Some(self), |x| Some(x.frobenius()))
118            .take(Self::DIMENSION)
119            .collect()
120    }
121}
122
123/// Trait for binomial extensions that support a two-adic subgroup generator.
124pub trait HasTwoAdicBinomialExtension<const D: usize>: BinomiallyExtendable<D> {
125    /// Two-adicity of the multiplicative group of the extension field.
126    ///
127    /// This is the number of times 2 divides the order of the field minus 1.
128    const EXT_TWO_ADICITY: usize;
129
130    /// Returns a two-adic generator for the extension field.
131    ///
132    /// This is used to generate the 2^bits-th roots of unity in the extension field.
133    /// Behavior is undefined if `bits > EXT_TWO_ADICITY`.
134    #[must_use]
135    fn ext_two_adic_generator(bits: usize) -> [Self; D];
136}
137
138/// Trait for fields that support a degree-5 extension using the trinomial `X^5 + X^2 - 1`.
139///
140/// This trait should only be implemented for fields where `X^5 + X^2 - 1` is irreducible.
141/// The implementor must verify irreducibility for their specific field.
142pub trait QuinticTrinomialExtendable: Field + QuinticExtendableAlgebra<Self> {
143    /// Frobenius coefficients for the quintic extension.
144    ///
145    /// `FROBENIUS_COEFFS[k]` represents `X^{(k+1)*p} mod (X^5 + X^2 - 1)` as a polynomial
146    /// with coefficients `[c_0, c_1, c_2, c_3, c_4]` where `X^{(k+1)*p} = Σ c_i * X^i`.
147    ///
148    /// These precomputed values enable efficient Frobenius automorphism computation.
149    const FROBENIUS_COEFFS: [[Self; 5]; 4];
150
151    /// A generator for the multiplicative group of the extension field `F_{p^5}*`.
152    ///
153    /// Represented as polynomial coefficients `[g_0, g_1, g_2, g_3, g_4]`.
154    const EXT_GENERATOR: [Self; 5];
155}
156
157/// Trait for algebras supporting quintic extension arithmetic over `A[X]/(X^5 + X^2 - 1)`.
158///
159/// Implementors may override the default methods with optimized versions
160/// (e.g., SIMD implementations for packed fields).
161pub trait QuinticExtendableAlgebra<F: Field>: Algebra<F> {
162    /// Multiply two elements in the quintic extension ring.
163    ///
164    /// Computes `a * b mod (X^5 + X^2 - 1)` and stores the result in `res`.
165    #[inline]
166    fn quintic_mul(a: &[Self; 5], b: &[Self; 5], res: &mut [Self; 5]) {
167        quintic_extension::trinomial_quintic_mul(a, b, res);
168    }
169
170    /// Square an element in the quintic extension ring.
171    ///
172    /// Computes `a^2 mod (X^5 + X^2 - 1)` and stores the result in `res`.
173    /// Uses optimized formulas exploiting the symmetry `a_i * a_j = a_j * a_i`.
174    #[inline]
175    fn quintic_square(a: &[Self; 5], res: &mut [Self; 5]) {
176        quintic_extension::quintic_square(a, res);
177    }
178
179    /// Add two elements in the quintic extension ring.
180    ///
181    /// Addition is coefficient-wise and independent of the modulus polynomial.
182    #[inline]
183    #[must_use]
184    fn quintic_add(a: &[Self; 5], b: &[Self; 5]) -> [Self; 5] {
185        vector_add(a, b)
186    }
187
188    /// Subtract two elements in the quintic extension ring.
189    ///
190    /// Subtraction is coefficient-wise and independent of the modulus polynomial.
191    #[inline]
192    #[must_use]
193    fn quintic_sub(a: &[Self; 5], b: &[Self; 5]) -> [Self; 5] {
194        vector_sub(a, b)
195    }
196
197    /// Multiply a quintic extension element by a base field scalar.
198    #[inline]
199    fn quintic_base_mul(lhs: [Self; 5], rhs: Self) -> [Self; 5] {
200        lhs.map(|x| x * rhs.clone())
201    }
202}
203
204/// Trait for quintic extensions that support two-adic subgroup generators.
205pub trait HasTwoAdicQuinticExtension: QuinticTrinomialExtendable {
206    /// Two-adicity of the multiplicative group order `p^5 - 1`.
207    const EXT_TWO_ADICITY: usize;
208
209    /// Returns a two-adic generator for the specified bit count.
210    ///
211    /// # Panics
212    /// Panics if `bits > EXT_TWO_ADICITY`.
213    #[must_use]
214    fn ext_two_adic_generator(bits: usize) -> [Self; 5];
215}