Skip to main content

p3_mersenne_31/
extension.rs

1use p3_field::extension::{
2    Binomial, BinomiallyExtendable, Complex, ExtensionAlgebra, HasComplexBinomialExtension,
3    HasTwoAdicComplexBinomialExtension, binomial_mul, binomial_square,
4};
5use p3_field::{PrimeCharacteristicRing, TwoAdicField, field_to_array};
6
7use crate::Mersenne31;
8
9impl ExtensionAlgebra<Self, 3, Binomial<Self>> for Mersenne31 {
10    #[inline]
11    fn ext_mul(a: &[Self; 3], b: &[Self; 3], res: &mut [Self; 3]) {
12        binomial_mul::<Self, Self, Self, 3>(a, b, res, <Self as BinomiallyExtendable<3>>::W);
13    }
14
15    #[inline]
16    fn ext_square(a: &[Self; 3], res: &mut [Self; 3]) {
17        binomial_square::<Self, Self, 3>(a, res, <Self as BinomiallyExtendable<3>>::W);
18    }
19}
20
21impl BinomiallyExtendable<3> for Mersenne31 {
22    // ```sage
23    // p = 2^31 - 1
24    // F = GF(p)
25    // R.<x> = F[]
26    // assert (x^3 - 5).is_irreducible()
27    // ```
28    const W: Self = Self::new(5);
29
30    // ```sage
31    // F(5)^((p-1)/3)
32    // ```
33    const DTH_ROOT: Self = Self::new(1513477735);
34
35    // ```sage
36    // F.extension(x^3 - 5, 'u').multiplicative_generator()
37    // ```
38    const EXT_GENERATOR: [Self; 3] = [Self::new(10), Self::ONE, Self::ZERO];
39}
40
41impl HasComplexBinomialExtension<2> for Mersenne31 {
42    // Verifiable in Sage with
43    // ```sage
44    // p = 2**31 - 1  # Mersenne31
45    // F = GF(p)  # The base field GF(p)
46    // R.<x> = F[]  # The polynomial ring over F
47    // K.<i> = F.extension(x^2 + 1)  # The complex extension field
48    // R2.<y> = K[]
49    // f2 = y^2 - i - 2
50    // assert f2.is_irreducible()
51    // ```
52    const W: Complex<Self> = Complex::new_complex(Self::TWO, Self::ONE);
53
54    // DTH_ROOT = W^((p^2 - 1)/2).
55    const DTH_ROOT: Complex<Self> = Complex::new_real(Self::new(2147483646));
56
57    // Verifiable in Sage with
58    // ```sage
59    // K2.<j> = K.extension(f2)
60    //  g = j + 6
61    // for f in factor(p^4 - 1):
62    //   assert g^((p^4-1) // f) != 1
63    // ```
64    const EXT_GENERATOR: [Complex<Self>; 2] = [Complex::new_real(Self::new(6)), Complex::ONE];
65
66    /// Multiply a `Complex<Mersenne31>` element by `W = 2 + i` using only additions:
67    /// `(a + bi)(2 + i) = (2a - b) + (a + 2b)i`.
68    #[inline(always)]
69    fn mul_by_w(z: Complex<Self>) -> Complex<Self> {
70        let re = z.real();
71        let im = z.imag();
72        Complex::new_complex(re + re - im, re + im + im)
73    }
74}
75
76impl HasTwoAdicComplexBinomialExtension<2> for Mersenne31 {
77    const COMPLEX_EXT_TWO_ADICITY: usize = 33;
78
79    fn complex_ext_two_adic_generator(bits: usize) -> [Complex<Self>; 2] {
80        assert!(bits <= 33);
81        if bits == 33 {
82            [
83                Complex::ZERO,
84                Complex::new_complex(Self::new_reduced(1437746044), Self::new_reduced(946469285)),
85            ]
86        } else {
87            [Complex::two_adic_generator(bits), Complex::ZERO]
88        }
89    }
90}
91
92impl HasComplexBinomialExtension<3> for Mersenne31 {
93    // Verifiable in Sage with
94    // ```sage
95    // p = 2**31 - 1  # Mersenne31
96    // F = GF(p)  # The base field GF(p)
97    // R.<x> = F[]  # The polynomial ring over F
98    // K.<i> = F.extension(x^2 + 1)  # The complex extension field
99    // R2.<y> = K[]
100    // f2 = y^3 - 5*i
101    // assert f2.is_irreducible()
102    // ```
103    const W: Complex<Self> = Complex::new_imag(Self::new(5));
104
105    // DTH_ROOT = W^((p^2 - 1)/2).
106    const DTH_ROOT: Complex<Self> = Complex::new_real(Self::new(634005911));
107
108    // Verifiable in Sage with
109    // ```sage
110    // K2.<j> = K.extension(f2)
111    //  g = j + 5
112    // for f in factor(p^6 - 1):
113    //   assert g^((p^6-1) // f) != 1
114    // ```
115    const EXT_GENERATOR: [Complex<Self>; 3] = [
116        Complex::new_real(Self::new(5)),
117        Complex::new_real(Self::ONE),
118        Complex::ZERO,
119    ];
120}
121
122impl HasTwoAdicComplexBinomialExtension<3> for Mersenne31 {
123    const COMPLEX_EXT_TWO_ADICITY: usize = 32;
124
125    fn complex_ext_two_adic_generator(bits: usize) -> [Complex<Self>; 3] {
126        field_to_array(Complex::two_adic_generator(bits))
127    }
128}
129
130#[cfg(test)]
131mod test_cubic_extension {
132    use num_bigint::BigUint;
133    use p3_field::extension::BinomialExtensionField;
134    use p3_field::{ExtensionField, PrimeCharacteristicRing};
135    use p3_field_testing::{test_extension_field, test_field, test_packed_extension_field};
136
137    use crate::Mersenne31;
138
139    type F = Mersenne31;
140    type EF = BinomialExtensionField<F, 3>;
141
142    // There is a redundant representation of zero but we already tested it
143    // when testing the base field.
144    const ZEROS: [EF; 1] = [EF::ZERO];
145    const ONES: [EF; 1] = [EF::ONE];
146
147    // Get the prime factorization of the order of the multiplicative group.
148    // i.e. the prime factorization of P^3 - 1.
149    fn multiplicative_group_prime_factorization() -> [(BigUint, u32); 9] {
150        [
151            (BigUint::from(2u8), 1),
152            (BigUint::from(3u8), 3),
153            (BigUint::from(7u8), 1),
154            (BigUint::from(11u8), 1),
155            (BigUint::from(31u8), 1),
156            (BigUint::from(151u8), 1),
157            (BigUint::from(331u16), 1),
158            (BigUint::from(529510939u32), 1),
159            (BigUint::from(2903110321u32), 1),
160        ]
161    }
162
163    test_extension_field!(super::F, super::EF);
164
165    test_field!(
166        super::EF,
167        &super::ZEROS,
168        &super::ONES,
169        &super::multiplicative_group_prime_factorization()
170    );
171
172    type Pef = <EF as ExtensionField<F>>::ExtensionPacking;
173    const PACKED_ZEROS: [Pef; 1] = [Pef::ZERO];
174    const PACKED_ONES: [Pef; 1] = [Pef::ONE];
175    test_packed_extension_field!(
176        super::F,
177        super::EF,
178        super::Pef,
179        &super::PACKED_ZEROS,
180        &super::PACKED_ONES
181    );
182    p3_field_testing::test_packed_binomial_extension_division!(F, 3);
183}
184
185#[cfg(test)]
186mod test_cubic_complex_extension {
187    use num_bigint::BigUint;
188    use p3_field::extension::{BinomialExtensionField, Complex};
189    use p3_field::{ExtensionField, PrimeCharacteristicRing};
190    use p3_field_testing::{
191        test_extension_field, test_field, test_packed_extension_field,
192        test_two_adic_extension_field,
193    };
194
195    use crate::Mersenne31;
196
197    type F = Complex<Mersenne31>;
198    type EF = BinomialExtensionField<F, 3>;
199
200    // There is a redundant representation of zero but we already tested it
201    // when testing the base field.
202    const ZEROS: [EF; 1] = [EF::ZERO];
203    const ONES: [EF; 1] = [EF::ONE];
204
205    // Get the prime factorization of the order of the multiplicative group.
206    // i.e. the prime factorization of P^6 - 1.
207    fn multiplicative_group_prime_factorization() -> [(BigUint, u32); 14] {
208        [
209            (BigUint::from(2u8), 32),
210            (BigUint::from(3u8), 3),
211            (BigUint::from(7u8), 1),
212            (BigUint::from(11u8), 1),
213            (BigUint::from(13u8), 1),
214            (BigUint::from(31u8), 1),
215            (BigUint::from(43u8), 2),
216            (BigUint::from(79u8), 1),
217            (BigUint::from(151u8), 1),
218            (BigUint::from(331u16), 1),
219            (BigUint::from(1381u16), 1),
220            (BigUint::from(529510939u32), 1),
221            (BigUint::from(1758566101u32), 1),
222            (BigUint::from(2903110321u32), 1),
223        ]
224    }
225
226    test_field!(
227        super::EF,
228        &super::ZEROS,
229        &super::ONES,
230        &super::multiplicative_group_prime_factorization()
231    );
232
233    test_extension_field!(super::F, super::EF);
234
235    test_two_adic_extension_field!(super::F, super::EF);
236
237    type Pef = <EF as ExtensionField<F>>::ExtensionPacking;
238    const PACKED_ZEROS: [Pef; 1] = [Pef::ZERO];
239    const PACKED_ONES: [Pef; 1] = [Pef::ONE];
240    test_packed_extension_field!(
241        super::F,
242        super::EF,
243        super::Pef,
244        &super::PACKED_ZEROS,
245        &super::PACKED_ONES
246    );
247    p3_field_testing::test_packed_binomial_extension_division!(F, 3);
248}
249
250#[cfg(test)]
251mod test_quadratic_complex_extension {
252
253    use num_bigint::BigUint;
254    use p3_field::extension::{BinomialExtensionField, Complex};
255    use p3_field::{ExtensionField, PrimeCharacteristicRing};
256    use p3_field_testing::{
257        test_extension_field, test_field, test_packed_extension_field,
258        test_two_adic_extension_field,
259    };
260
261    use crate::Mersenne31;
262
263    type F = Complex<Mersenne31>;
264    type EF = BinomialExtensionField<F, 2>;
265
266    // There is a redundant representation of zero but we already tested it
267    // when testing the base field.
268    const ZEROS: [EF; 1] = [EF::ZERO];
269    const ONES: [EF; 1] = [EF::ONE];
270
271    // Get the prime factorization of the order of the multiplicative group.
272    // i.e. the prime factorization of P^4 - 1.
273    fn multiplicative_group_prime_factorization() -> [(BigUint, u32); 11] {
274        [
275            (BigUint::from(2u8), 33),
276            (BigUint::from(3u8), 2),
277            (BigUint::from(5u8), 1),
278            (BigUint::from(7u8), 1),
279            (BigUint::from(11u8), 1),
280            (BigUint::from(31u8), 1),
281            (BigUint::from(151u8), 1),
282            (BigUint::from(331u16), 1),
283            (BigUint::from(733u16), 1),
284            (BigUint::from(1709u16), 1),
285            (BigUint::from(368140581013u64), 1),
286        ]
287    }
288
289    test_field!(
290        super::EF,
291        &super::ZEROS,
292        &super::ONES,
293        &super::multiplicative_group_prime_factorization()
294    );
295
296    test_extension_field!(super::F, super::EF);
297
298    test_two_adic_extension_field!(super::F, super::EF);
299
300    type Pef = <EF as ExtensionField<F>>::ExtensionPacking;
301    const PACKED_ZEROS: [Pef; 1] = [Pef::ZERO];
302    const PACKED_ONES: [Pef; 1] = [Pef::ONE];
303    test_packed_extension_field!(
304        super::F,
305        super::EF,
306        super::Pef,
307        &super::PACKED_ZEROS,
308        &super::PACKED_ONES
309    );
310    p3_field_testing::test_packed_binomial_extension_division!(F, 2);
311}