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 fn binomial_algebra_id() -> alloc::vec::Vec<u8> {
24 use p3_field::PrimeField64;
25 alloc::format!(
26 "p3-power-basis-v1:X^2-{}",
27 <Self as BinomiallyExtendable<2>>::W.as_canonical_u64()
28 )
29 .into_bytes()
30 }
31
32 const W: Self = Self::new(7);
35
36 const DTH_ROOT: Self = Self::new(18446744069414584320);
38
39 const EXT_GENERATOR: [Self; 2] = [
40 Self::new(18081566051660590251),
41 Self::new(16121475356294670766),
42 ];
43}
44
45impl HasTwoAdicBinomialExtension<2> for Goldilocks {
46 const EXT_TWO_ADICITY: usize = 33;
47
48 fn ext_two_adic_generator(bits: usize) -> [Self; 2] {
49 assert!(bits <= 33);
50
51 if bits == 33 {
52 [Self::ZERO, Self::new(15659105665374529263)]
53 } else {
54 [Self::two_adic_generator(bits), Self::ZERO]
55 }
56 }
57}
58
59impl ExtensionAlgebra<Self, 3, CubicTrinomial> for Goldilocks {
60 #[inline]
61 fn ext_mul(a: &[Self; 3], b: &[Self; 3], res: &mut [Self; 3]) {
62 trinomial_cubic_mul::<Self>(a, b, res);
63 }
64
65 #[inline]
66 fn ext_square(a: &[Self; 3], res: &mut [Self; 3]) {
67 cubic_square::<Self>(a, res);
68 }
69}
70
71impl CubicTrinomialExtendable for Goldilocks {
72 const FROBENIUS_MATRIX: [[Self; 3]; 3] = [
79 [
80 Self::ONE,
81 Self::new(10615703402128488253),
82 Self::new(6700183068485440220),
83 ],
84 [
85 Self::ZERO,
86 Self::new(10050274602728160328),
87 Self::new(14531223735771536287),
88 ],
89 [
90 Self::ZERO,
91 Self::new(11746561000929144102),
92 Self::new(8396469466686423992),
93 ],
94 ];
95
96 const EXT_GENERATOR: [Self; 3] = [Self::TWO, Self::ONE, Self::ZERO];
107}
108
109impl HasTwoAdicCubicExtension for Goldilocks {
110 const EXT_TWO_ADICITY: usize = 32;
111
112 fn ext_two_adic_generator(bits: usize) -> [Self; 3] {
113 assert!(bits <= 32);
114
115 field_to_array(Self::two_adic_generator(bits))
116 }
117}
118
119impl ExtensionAlgebra<Self, 5, Binomial<Self>> for Goldilocks {
120 #[inline]
121 fn ext_mul(a: &[Self; 5], b: &[Self; 5], res: &mut [Self; 5]) {
122 binomial_mul::<Self, Self, Self, 5>(a, b, res, <Self as BinomiallyExtendable<5>>::W);
123 }
124
125 #[inline]
126 fn ext_square(a: &[Self; 5], res: &mut [Self; 5]) {
127 binomial_square::<Self, Self, 5>(a, res, <Self as BinomiallyExtendable<5>>::W);
128 }
129}
130
131impl BinomiallyExtendable<5> for Goldilocks {
132 fn binomial_algebra_id() -> alloc::vec::Vec<u8> {
133 use p3_field::PrimeField64;
134 alloc::format!(
135 "p3-power-basis-v1:X^5-{}",
136 <Self as BinomiallyExtendable<5>>::W.as_canonical_u64()
137 )
138 .into_bytes()
139 }
140
141 const W: Self = Self::new(3);
154
155 const DTH_ROOT: Self = Self::new(1041288259238279555);
157
158 const EXT_GENERATOR: [Self; 5] = [Self::TWO, Self::ONE, Self::ZERO, Self::ZERO, Self::ZERO];
162}
163
164impl HasTwoAdicBinomialExtension<5> for Goldilocks {
165 const EXT_TWO_ADICITY: usize = 32;
166
167 fn ext_two_adic_generator(bits: usize) -> [Self; 5] {
168 assert!(bits <= 32);
169
170 field_to_array(Self::two_adic_generator(bits))
171 }
172}
173
174#[cfg(test)]
175mod test_quadratic_extension {
176
177 use num_bigint::BigUint;
178 use p3_field::extension::BinomialExtensionField;
179 use p3_field::{ExtensionField, PrimeCharacteristicRing};
180 use p3_field_testing::{
181 test_extension_field, test_field, test_packed_extension_field,
182 test_two_adic_extension_field,
183 };
184
185 use crate::Goldilocks;
186
187 type F = Goldilocks;
188 type EF = BinomialExtensionField<F, 2>;
189
190 const ZEROS: [EF; 1] = [EF::ZERO];
193 const ONES: [EF; 1] = [EF::ONE];
194
195 fn multiplicative_group_prime_factorization() -> [(BigUint, u32); 9] {
198 [
199 (BigUint::from(2u8), 33),
200 (BigUint::from(3u8), 1),
201 (BigUint::from(5u8), 1),
202 (BigUint::from(7u8), 1),
203 (BigUint::from(17u8), 1),
204 (BigUint::from(179u8), 1),
205 (BigUint::from(257u16), 1),
206 (BigUint::from(65537u32), 1),
207 (BigUint::from(7361031152998637u64), 1),
208 ]
209 }
210
211 test_field!(
212 super::EF,
213 &super::ZEROS,
214 &super::ONES,
215 &super::multiplicative_group_prime_factorization()
216 );
217
218 test_extension_field!(super::F, super::EF);
219 test_two_adic_extension_field!(super::F, super::EF);
220
221 type Pef = <EF as ExtensionField<F>>::ExtensionPacking;
222 const PACKED_ZEROS: [Pef; 1] = [Pef::ZERO];
223 const PACKED_ONES: [Pef; 1] = [Pef::ONE];
224 test_packed_extension_field!(
225 super::F,
226 super::EF,
227 super::Pef,
228 &super::PACKED_ZEROS,
229 &super::PACKED_ONES
230 );
231 p3_field_testing::test_packed_binomial_extension_division!(F, 2);
232}
233
234#[cfg(test)]
235mod test_cubic_trinomial_extension {
236
237 use num_bigint::BigUint;
238 use p3_field::extension::{CubicTrinomialExtensionField, HasFrobenius};
239 use p3_field::{ExtensionField, PrimeCharacteristicRing};
240 use p3_field_testing::{
241 test_extension_field, test_field, test_frobenius, test_packed_extension_field,
242 test_two_adic_extension_field,
243 };
244 use rand::rngs::SmallRng;
245 use rand::{RngExt, SeedableRng};
246
247 use crate::Goldilocks;
248
249 type F = Goldilocks;
250 type EF = CubicTrinomialExtensionField<F>;
251
252 const ZEROS: [EF; 1] = [EF::ZERO];
253 const ONES: [EF; 1] = [EF::ONE];
254
255 fn multiplicative_group_prime_factorization() -> [(BigUint, u32); 9] {
256 [
257 (BigUint::from(2u8), 32),
258 (BigUint::from(3u8), 2),
259 (BigUint::from(5u8), 1),
260 (BigUint::from(17u8), 1),
261 (BigUint::from(257u16), 1),
262 (BigUint::from(937u16), 1),
263 (BigUint::from(65537u32), 1),
264 (BigUint::from(724723u32), 1),
265 (BigUint::from(167034643597991036904547663171u128), 1),
266 ]
267 }
268
269 #[test]
271 fn test_defining_relation() {
272 let x = EF::new([F::ZERO, F::ONE, F::ZERO]);
273 let x_cubed = x * x * x;
274 let x_plus_one = x + EF::ONE;
275 assert_eq!(x_cubed, x_plus_one, "X^3 should equal X + 1");
276 }
277
278 #[test]
279 fn test_frobenius_matches_exponentiation_oracle() {
280 const P: u64 = 0xFFFF_FFFF_0000_0001;
281
282 let edge_values = [0, 1, P - 1, P, P + 1, u64::MAX];
283 for a0 in edge_values {
284 for a1 in edge_values {
285 for a2 in edge_values {
286 let x = EF::new([F::new(a0), F::new(a1), F::new(a2)]);
287 assert_eq!(x.frobenius(), x.exp_u64(P), "x = {x:?}");
288 }
289 }
290 }
291
292 let mut rng = SmallRng::seed_from_u64(0x0F0B_31A5);
293 for _ in 0..128 {
294 let x = EF::new([
295 F::new(rng.random()),
296 F::new(rng.random()),
297 F::new(rng.random()),
298 ]);
299 assert_eq!(x.frobenius(), x.exp_u64(P), "x = {x:?}");
300 }
301 }
302
303 test_field!(
304 super::EF,
305 &super::ZEROS,
306 &super::ONES,
307 &super::multiplicative_group_prime_factorization()
308 );
309
310 test_extension_field!(super::F, super::EF);
311 test_two_adic_extension_field!(super::F, super::EF);
312 test_frobenius!(super::F, super::EF);
313
314 type Pef = <EF as ExtensionField<F>>::ExtensionPacking;
315 const PACKED_ZEROS: [Pef; 1] = [Pef::ZERO];
316 const PACKED_ONES: [Pef; 1] = [Pef::ONE];
317 test_packed_extension_field!(
318 super::F,
319 super::EF,
320 super::Pef,
321 &super::PACKED_ZEROS,
322 &super::PACKED_ONES
323 );
324}
325
326#[cfg(test)]
327mod test_quintic_extension {
328
329 use num_bigint::BigUint;
330 use p3_field::extension::BinomialExtensionField;
331 use p3_field::{ExtensionField, PrimeCharacteristicRing};
332 use p3_field_testing::{
333 test_extension_field, test_field, test_packed_extension_field,
334 test_two_adic_extension_field,
335 };
336
337 use crate::Goldilocks;
338
339 type F = Goldilocks;
340 type EF = BinomialExtensionField<F, 5>;
341
342 const ZEROS: [EF; 1] = [EF::ZERO];
345 const ONES: [EF; 1] = [EF::ONE];
346
347 fn multiplicative_group_prime_factorization() -> [(num_bigint::BigUint, u32); 10] {
350 [
351 (BigUint::from(2u8), 32),
352 (BigUint::from(3u8), 1),
353 (BigUint::from(5u8), 2),
354 (BigUint::from(17u8), 1),
355 (BigUint::from(257u16), 1),
356 (BigUint::from(45971u16), 1),
357 (BigUint::from(65537u32), 1),
358 (BigUint::from(255006435240067831u64), 1),
359 (BigUint::from(280083648770327405561u128), 1),
360 (BigUint::from(7053197395277272939628824863222181u128), 1),
361 ]
362 }
363
364 test_field!(
365 super::EF,
366 &super::ZEROS,
367 &super::ONES,
368 &super::multiplicative_group_prime_factorization()
369 );
370
371 test_extension_field!(super::F, super::EF);
372 test_two_adic_extension_field!(super::F, super::EF);
373
374 type Pef = <EF as ExtensionField<F>>::ExtensionPacking;
375 const PACKED_ZEROS: [Pef; 1] = [Pef::ZERO];
376 const PACKED_ONES: [Pef; 1] = [Pef::ONE];
377 test_packed_extension_field!(
378 super::F,
379 super::EF,
380 super::Pef,
381 &super::PACKED_ZEROS,
382 &super::PACKED_ONES
383 );
384 p3_field_testing::test_packed_binomial_extension_division!(F, 5);
385}