1use p3_field::extension::{
2 Binomial, BinomiallyExtendable, CubicTrinomial, CubicTrinomialExtendable, ExtensionAlgebra,
3 HasTwoAdicBinomialExtension, HasTwoAdicCubicExtension, binomial_mul, binomial_square,
4 cubic_square, trinomial_cubic_mul,
5};
6use p3_field::{PrimeCharacteristicRing, TwoAdicField, field_to_array};
7
8use crate::Goldilocks;
9
10impl ExtensionAlgebra<Self, 2, Binomial<Self>> for Goldilocks {
11 #[inline]
12 fn ext_mul(a: &[Self; 2], b: &[Self; 2], res: &mut [Self; 2]) {
13 binomial_mul::<Self, Self, Self, 2>(a, b, res, <Self as BinomiallyExtendable<2>>::W);
14 }
15
16 #[inline]
17 fn ext_square(a: &[Self; 2], res: &mut [Self; 2]) {
18 binomial_square::<Self, Self, 2>(a, res, <Self as BinomiallyExtendable<2>>::W);
19 }
20}
21
22impl BinomiallyExtendable<2> for Goldilocks {
23 const W: Self = Self::new(7);
26
27 const DTH_ROOT: Self = Self::new(18446744069414584320);
29
30 const EXT_GENERATOR: [Self; 2] = [
31 Self::new(18081566051660590251),
32 Self::new(16121475356294670766),
33 ];
34}
35
36impl HasTwoAdicBinomialExtension<2> for Goldilocks {
37 const EXT_TWO_ADICITY: usize = 33;
38
39 fn ext_two_adic_generator(bits: usize) -> [Self; 2] {
40 assert!(bits <= 33);
41
42 if bits == 33 {
43 [Self::ZERO, Self::new(15659105665374529263)]
44 } else {
45 [Self::two_adic_generator(bits), Self::ZERO]
46 }
47 }
48}
49
50impl ExtensionAlgebra<Self, 3, CubicTrinomial> for Goldilocks {
51 #[inline]
52 fn ext_mul(a: &[Self; 3], b: &[Self; 3], res: &mut [Self; 3]) {
53 trinomial_cubic_mul::<Self>(a, b, res);
54 }
55
56 #[inline]
57 fn ext_square(a: &[Self; 3], res: &mut [Self; 3]) {
58 cubic_square::<Self>(a, res);
59 }
60}
61
62impl CubicTrinomialExtendable for Goldilocks {
63 const FROBENIUS_MATRIX: [[Self; 3]; 3] = [
70 [
71 Self::ONE,
72 Self::new(10615703402128488253),
73 Self::new(6700183068485440220),
74 ],
75 [
76 Self::ZERO,
77 Self::new(10050274602728160328),
78 Self::new(14531223735771536287),
79 ],
80 [
81 Self::ZERO,
82 Self::new(11746561000929144102),
83 Self::new(8396469466686423992),
84 ],
85 ];
86
87 const EXT_GENERATOR: [Self; 3] = [Self::TWO, Self::ONE, Self::ZERO];
98}
99
100impl HasTwoAdicCubicExtension for Goldilocks {
101 const EXT_TWO_ADICITY: usize = 32;
102
103 fn ext_two_adic_generator(bits: usize) -> [Self; 3] {
104 assert!(bits <= 32);
105
106 field_to_array(Self::two_adic_generator(bits))
107 }
108}
109
110impl ExtensionAlgebra<Self, 5, Binomial<Self>> for Goldilocks {
111 #[inline]
112 fn ext_mul(a: &[Self; 5], b: &[Self; 5], res: &mut [Self; 5]) {
113 binomial_mul::<Self, Self, Self, 5>(a, b, res, <Self as BinomiallyExtendable<5>>::W);
114 }
115
116 #[inline]
117 fn ext_square(a: &[Self; 5], res: &mut [Self; 5]) {
118 binomial_square::<Self, Self, 5>(a, res, <Self as BinomiallyExtendable<5>>::W);
119 }
120}
121
122impl BinomiallyExtendable<5> for Goldilocks {
123 const W: Self = Self::new(3);
136
137 const DTH_ROOT: Self = Self::new(1041288259238279555);
139
140 const EXT_GENERATOR: [Self; 5] = [Self::TWO, Self::ONE, Self::ZERO, Self::ZERO, Self::ZERO];
144}
145
146impl HasTwoAdicBinomialExtension<5> for Goldilocks {
147 const EXT_TWO_ADICITY: usize = 32;
148
149 fn ext_two_adic_generator(bits: usize) -> [Self; 5] {
150 assert!(bits <= 32);
151
152 field_to_array(Self::two_adic_generator(bits))
153 }
154}
155
156#[cfg(test)]
157mod test_quadratic_extension {
158
159 use num_bigint::BigUint;
160 use p3_field::extension::BinomialExtensionField;
161 use p3_field::{ExtensionField, PrimeCharacteristicRing};
162 use p3_field_testing::{
163 test_extension_field, test_field, test_packed_extension_field,
164 test_two_adic_extension_field,
165 };
166
167 use crate::Goldilocks;
168
169 type F = Goldilocks;
170 type EF = BinomialExtensionField<F, 2>;
171
172 const ZEROS: [EF; 1] = [EF::ZERO];
175 const ONES: [EF; 1] = [EF::ONE];
176
177 fn multiplicative_group_prime_factorization() -> [(BigUint, u32); 9] {
180 [
181 (BigUint::from(2u8), 33),
182 (BigUint::from(3u8), 1),
183 (BigUint::from(5u8), 1),
184 (BigUint::from(7u8), 1),
185 (BigUint::from(17u8), 1),
186 (BigUint::from(179u8), 1),
187 (BigUint::from(257u16), 1),
188 (BigUint::from(65537u32), 1),
189 (BigUint::from(7361031152998637u64), 1),
190 ]
191 }
192
193 test_field!(
194 super::EF,
195 &super::ZEROS,
196 &super::ONES,
197 &super::multiplicative_group_prime_factorization()
198 );
199
200 test_extension_field!(super::F, super::EF);
201 test_two_adic_extension_field!(super::F, super::EF);
202
203 type Pef = <EF as ExtensionField<F>>::ExtensionPacking;
204 const PACKED_ZEROS: [Pef; 1] = [Pef::ZERO];
205 const PACKED_ONES: [Pef; 1] = [Pef::ONE];
206 test_packed_extension_field!(
207 super::F,
208 super::EF,
209 super::Pef,
210 &super::PACKED_ZEROS,
211 &super::PACKED_ONES
212 );
213 p3_field_testing::test_packed_binomial_extension_division!(F, 2);
214}
215
216#[cfg(test)]
217mod test_cubic_trinomial_extension {
218
219 use num_bigint::BigUint;
220 use p3_field::extension::CubicTrinomialExtensionField;
221 use p3_field::{ExtensionField, PrimeCharacteristicRing};
222 use p3_field_testing::{
223 test_extension_field, test_field, test_frobenius, test_packed_extension_field,
224 test_two_adic_extension_field,
225 };
226
227 use crate::Goldilocks;
228
229 type F = Goldilocks;
230 type EF = CubicTrinomialExtensionField<F>;
231
232 const ZEROS: [EF; 1] = [EF::ZERO];
233 const ONES: [EF; 1] = [EF::ONE];
234
235 fn multiplicative_group_prime_factorization() -> [(BigUint, u32); 9] {
236 [
237 (BigUint::from(2u8), 32),
238 (BigUint::from(3u8), 2),
239 (BigUint::from(5u8), 1),
240 (BigUint::from(17u8), 1),
241 (BigUint::from(257u16), 1),
242 (BigUint::from(937u16), 1),
243 (BigUint::from(65537u32), 1),
244 (BigUint::from(724723u32), 1),
245 (BigUint::from(167034643597991036904547663171u128), 1),
246 ]
247 }
248
249 #[test]
251 fn test_defining_relation() {
252 let x = EF::new([F::ZERO, F::ONE, F::ZERO]);
253 let x_cubed = x * x * x;
254 let x_plus_one = x + EF::ONE;
255 assert_eq!(x_cubed, x_plus_one, "X^3 should equal X + 1");
256 }
257
258 test_field!(
259 super::EF,
260 &super::ZEROS,
261 &super::ONES,
262 &super::multiplicative_group_prime_factorization()
263 );
264
265 test_extension_field!(super::F, super::EF);
266 test_two_adic_extension_field!(super::F, super::EF);
267 test_frobenius!(super::F, super::EF);
268
269 type Pef = <EF as ExtensionField<F>>::ExtensionPacking;
270 const PACKED_ZEROS: [Pef; 1] = [Pef::ZERO];
271 const PACKED_ONES: [Pef; 1] = [Pef::ONE];
272 test_packed_extension_field!(
273 super::F,
274 super::EF,
275 super::Pef,
276 &super::PACKED_ZEROS,
277 &super::PACKED_ONES
278 );
279}
280
281#[cfg(test)]
282mod test_quintic_extension {
283
284 use num_bigint::BigUint;
285 use p3_field::extension::BinomialExtensionField;
286 use p3_field::{ExtensionField, PrimeCharacteristicRing};
287 use p3_field_testing::{
288 test_extension_field, test_field, test_packed_extension_field,
289 test_two_adic_extension_field,
290 };
291
292 use crate::Goldilocks;
293
294 type F = Goldilocks;
295 type EF = BinomialExtensionField<F, 5>;
296
297 const ZEROS: [EF; 1] = [EF::ZERO];
300 const ONES: [EF; 1] = [EF::ONE];
301
302 fn multiplicative_group_prime_factorization() -> [(num_bigint::BigUint, u32); 10] {
305 [
306 (BigUint::from(2u8), 32),
307 (BigUint::from(3u8), 1),
308 (BigUint::from(5u8), 2),
309 (BigUint::from(17u8), 1),
310 (BigUint::from(257u16), 1),
311 (BigUint::from(45971u16), 1),
312 (BigUint::from(65537u32), 1),
313 (BigUint::from(255006435240067831u64), 1),
314 (BigUint::from(280083648770327405561u128), 1),
315 (BigUint::from(7053197395277272939628824863222181u128), 1),
316 ]
317 }
318
319 test_field!(
320 super::EF,
321 &super::ZEROS,
322 &super::ONES,
323 &super::multiplicative_group_prime_factorization()
324 );
325
326 test_extension_field!(super::F, super::EF);
327 test_two_adic_extension_field!(super::F, super::EF);
328
329 type Pef = <EF as ExtensionField<F>>::ExtensionPacking;
330 const PACKED_ZEROS: [Pef; 1] = [Pef::ZERO];
331 const PACKED_ONES: [Pef; 1] = [Pef::ONE];
332 test_packed_extension_field!(
333 super::F,
334 super::EF,
335 super::Pef,
336 &super::PACKED_ZEROS,
337 &super::PACKED_ONES
338 );
339 p3_field_testing::test_packed_binomial_extension_division!(F, 5);
340}