halo2curves/pluto_eris/
fp12.rs

1use ff::Field;
2
3use super::{fp::Fp, fp2::Fp2, fp6::Fp6};
4use crate::ff_ext::{
5    quadratic::{QuadExtField, QuadExtFieldArith, QuadSparseMul},
6    ExtField,
7};
8
9// -GAMMA is a quadratic non-residue in Fp6. Fp12 = Fp6[X]/(X^2 + GAMMA)
10// We introduce the variable w such that w^2 = -GAMMA
11// GAMMA = - v
12/// An element of Fp12, represented by c0 + c1 * v.
13pub type Fp12 = QuadExtField<Fp6>;
14
15impl QuadExtFieldArith for Fp12 {
16    type Base = Fp6;
17}
18
19impl QuadSparseMul for Fp12 {
20    type Base = Fp2;
21}
22
23impl ExtField for Fp12 {
24    const NON_RESIDUE: Self = Fp12::zero(); // no needs
25
26    fn frobenius_map(&mut self, power: usize) {
27        self.c0.frobenius_map(power);
28        self.c1.frobenius_map(power);
29        self.c1.c0.mul_assign(&FROBENIUS_COEFF_FP12_C1[power % 12]);
30        self.c1.c1.mul_assign(&FROBENIUS_COEFF_FP12_C1[power % 12]);
31        self.c1.c2.mul_assign(&FROBENIUS_COEFF_FP12_C1[power % 12]);
32    }
33}
34
35crate::impl_binops_additive!(Fp12, Fp12);
36crate::impl_binops_multiplicative!(Fp12, Fp12);
37crate::impl_binops_calls!(Fp12);
38crate::impl_sum_prod!(Fp12);
39crate::impl_cyclotomic_square!(Fp2, Fp12);
40
41/// Fp2(v)^((p^i-1)/6) for i=0,...,11
42pub const FROBENIUS_COEFF_FP12_C1: [Fp2; 12] = [
43    // Fp2(v)**(((p^0) - 1) / 6)
44    Fp2::ONE,
45    // Fp2(v)**(((p^1) - 1) / 6)
46    Fp2 {
47        // 0x3c3ad3da8b99cb1df0709dc343113ccd9892dedd51f30695d89c647b90de8f41df055384b9e6cfd4e70648622c750f32ee965dfef2303d3
48        c0: Fp::from_raw([
49            0x2ee965dfef2303d3,
50            0x4e70648622c750f3,
51            0x1df055384b9e6cfd,
52            0x5d89c647b90de8f4,
53            0xd9892dedd51f3069,
54            0xdf0709dc343113cc,
55            0x03c3ad3da8b99cb1,
56        ]),
57        // 0x149fd9ed2c7affe7aaa3b912182da22dccb29838628f04b6f333d052540294889f03876b2ddb143559f9373f4cf44e6afa0be24ad758a5ff
58        c1: Fp::from_raw([
59            0xfa0be24ad758a5ff,
60            0x59f9373f4cf44e6a,
61            0x9f03876b2ddb1435,
62            0xf333d05254029488,
63            0xccb29838628f04b6,
64            0xaaa3b912182da22d,
65            0x149fd9ed2c7affe7,
66        ]),
67    },
68    // Fp2(v)**(((p^2) - 1) / 6)
69    Fp2 {
70        // 0x480000000000360001c950000d7ee0e4a803c956d01c903d720dc8ad8b38dffaf50c100004c37fffffff
71        c0: Fp::from_raw([
72            0x100004c37fffffff,
73            0xc8ad8b38dffaf50c,
74            0xc956d01c903d720d,
75            0x50000d7ee0e4a803,
76            0x00000000360001c9,
77            0x0000000000004800,
78            0x0000000000000000,
79        ]),
80        c1: Fp::ZERO,
81    },
82    // Fp2(v)**(((p^3) - 1) / 6)
83    Fp2 {
84        // 0x1baee9e044d94d205764b80089c40010af5ca1e56a2a81e6a5d8739325984fc889d390efef216fe4f4af912a897f60a128a3be71be4995ca
85        c0: Fp::from_raw([
86            0x28a3be71be4995ca,
87            0xf4af912a897f60a1,
88            0x89d390efef216fe4,
89            0xa5d8739325984fc8,
90            0xaf5ca1e56a2a81e6,
91            0x5764b80089c40010,
92            0x1baee9e044d94d20,
93        ]),
94        // 0x20d4c11700e832829b26f1795339413be65e47a7716bc8bc07cd6b44b03ef1130b3c35a77291b29d6f45d28e4ef1ecb9678f4479a1151232
95        c1: Fp::from_raw([
96            0x678f4479a1151232,
97            0x6f45d28e4ef1ecb9,
98            0x0b3c35a77291b29d,
99            0x07cd6b44b03ef113,
100            0xe65e47a7716bc8bc,
101            0x9b26f1795339413b,
102            0x20d4c11700e83282,
103        ]),
104    },
105    // Fp2(v)**(((p^4) - 1) / 6)
106    Fp2 {
107        // 0x480000000000360001c950000d7ee0e4a803c956d01c903d720dc8ad8b38dffaf50c100004c37ffffffe
108        c0: Fp::from_raw([
109            0x100004c37ffffffe,
110            0xc8ad8b38dffaf50c,
111            0xc956d01c903d720d,
112            0x50000d7ee0e4a803,
113            0x00000000360001c9,
114            0x0000000000004800,
115            0x0000000000000000,
116        ]),
117        c1: Fp::ZERO,
118    },
119    // Fp2(v)**(((p^5) - 1) / 6)
120    Fp2 {
121        // 0x17eb3ca29c1fb06e785dae245592ec43d5d373f7950b517d484ead4b6c8a66d46be33bb7a38302e7a63f2ca466b80fadf9ba5891cf2691f7
122        c0: Fp::from_raw([
123            0xf9ba5891cf2691f7,
124            0xa63f2ca466b80fad,
125            0x6be33bb7a38302e7,
126            0x484ead4b6c8a66d4,
127            0xd5d373f7950b517d,
128            0x785dae245592ec43,
129            0x17eb3ca29c1fb06e,
130        ]),
131        // 0xc34e729d46d329af08338673b0b9f0e19abaf6f0edcc40514999af25c3c5c8a6c38ae3c44b69e68154c9b4f01fd9e4e6d83622ec9bc6c33
132        c1: Fp::from_raw([
133            0x6d83622ec9bc6c33,
134            0x154c9b4f01fd9e4e,
135            0x6c38ae3c44b69e68,
136            0x14999af25c3c5c8a,
137            0x19abaf6f0edcc405,
138            0xf08338673b0b9f0e,
139            0x0c34e729d46d329a,
140        ]),
141    },
142    // Fp2(v)**(((p^6) - 1) / 6)
143    Fp2 {
144        // 0x24000000000024000130e0000d7f70e4a803ca76f439266f443f9a5cda8a6c7be4a7a5fe8fadffd6a2a7e8c30006b9459ffffcd300000000
145        c0: Fp::from_raw([
146            0x9ffffcd300000000,
147            0xa2a7e8c30006b945,
148            0xe4a7a5fe8fadffd6,
149            0x443f9a5cda8a6c7b,
150            0xa803ca76f439266f,
151            0x0130e0000d7f70e4,
152            0x2400000000002400,
153        ]),
154        c1: Fp::ZERO,
155    },
156    // Fp2(v)**(((p^7) - 1) / 6)
157    Fp2 {
158        // 0x203c52c25746874e2229d623d94e5d17ce7a9c891f19f605e6b5d415217c8387c6b750c6440f92d95437843cdd3f6852711696f310dcfc2e
159        c0: Fp::from_raw([
160            0x711696f310dcfc2e,
161            0x5437843cdd3f6852,
162            0xc6b750c6440f92d9,
163            0xe6b5d415217c8387,
164            0xce7a9c891f19f605,
165            0x2229d623d94e5d17,
166            0x203c52c25746874e,
167        ]),
168        // 0xf602612d3852418568d26edf551ceb6db51323e91aa21b8510bca0a8687d7f345a41e9361d2eba148aeb183b3126adaa5f41a8828a75a02
169        c1: Fp::from_raw([
170            0xa5f41a8828a75a02,
171            0x48aeb183b3126ada,
172            0x45a41e9361d2eba1,
173            0x510bca0a8687d7f3,
174            0xdb51323e91aa21b8,
175            0x568d26edf551ceb6,
176            0x0f602612d3852418,
177        ]),
178    },
179    // Fp2(v)**(((p^8) - 1) / 6)
180    Fp2 {
181        // 0x24000000000024000130e0000d7f28e4a803ca76be3924a5f43f8cddf9a5c4781b50d5e1ff708dc8d9fa5d8a200bc4398ffff80f80000002
182        c0: Fp::from_raw([
183            0x8ffff80f80000002,
184            0xd9fa5d8a200bc439,
185            0x1b50d5e1ff708dc8,
186            0xf43f8cddf9a5c478,
187            0xa803ca76be3924a5,
188            0x0130e0000d7f28e4,
189            0x2400000000002400,
190        ]),
191        c1: Fp::ZERO,
192    },
193    // Fp2(v)**(((p^9) - 1) / 6)
194    Fp2 {
195        // 0x851161fbb26d6dfa9cc27ff83bb70d3f8a728918a0ea4889e6726c9b4f21cb35ad4150ea08c8ff1adf85798768758a4775c3e6141b66a37
196        c0: Fp::from_raw([
197            0x775c3e6141b66a37,
198            0xadf85798768758a4,
199            0x5ad4150ea08c8ff1,
200            0x9e6726c9b4f21cb3,
201            0xf8a728918a0ea488,
202            0xa9cc27ff83bb70d3,
203            0x0851161fbb26d6df,
204        ]),
205        // 0x32b3ee8ff17f17d6609ee86ba462fa8c1a582cf82cd5db33c722f182a4b7b68d96b70571d1c4d3933621634b114cc8c3870b8595eeaedcf
206        c1: Fp::from_raw([
207            0x3870b8595eeaedcf,
208            0x33621634b114cc8c,
209            0xd96b70571d1c4d39,
210            0x3c722f182a4b7b68,
211            0xc1a582cf82cd5db3,
212            0x6609ee86ba462fa8,
213            0x032b3ee8ff17f17d,
214        ]),
215    },
216    // Fp2(v)**(((p^10) - 1) / 6)
217    Fp2 {
218        // 0x24000000000024000130e0000d7f28e4a803ca76be3924a5f43f8cddf9a5c4781b50d5e1ff708dc8d9fa5d8a200bc4398ffff80f80000003
219        c0: Fp::from_raw([
220            0x8ffff80f80000003,
221            0xd9fa5d8a200bc439,
222            0x1b50d5e1ff708dc8,
223            0xf43f8cddf9a5c478,
224            0xa803ca76be3924a5,
225            0x0130e0000d7f28e4,
226            0x2400000000002400,
227        ]),
228        c1: Fp::ZERO,
229    },
230    // Fp2(v)**(((p^11) - 1) / 6)
231    Fp2 {
232        // 0xc14c35d63e0739188d331dbb7ec84a0d230567f5f2dd4f1fbf0ed116e0005a778c46a46ec2afceefc68bc1e994ea997a645a44130d96e0a
233        c0: Fp::from_raw([
234            0xa645a44130d96e0a,
235            0xfc68bc1e994ea997,
236            0x78c46a46ec2afcee,
237            0xfbf0ed116e0005a7,
238            0xd230567f5f2dd4f1,
239            0x88d331dbb7ec84a0,
240            0x0c14c35d63e07391,
241        ]),
242        // 0x17cb18d62b92f16510ada798d273d1d68e581b07e55c626a2fa5ff6a7e4e0ff1786ef7c24af7616e8d5b4d73fe091af7327c9aa4364393ce
243        c1: Fp::from_raw([
244            0x327c9aa4364393ce,
245            0x8d5b4d73fe091af7,
246            0x786ef7c24af7616e,
247            0x2fa5ff6a7e4e0ff1,
248            0x8e581b07e55c626a,
249            0x10ada798d273d1d6,
250            0x17cb18d62b92f165,
251        ]),
252    },
253];
254
255#[cfg(test)]
256mod test {
257    macro_rules! test_fp12 {
258        ($test:ident, $size: expr) => {
259            paste::paste! {
260            #[test]
261            fn [< $test test >]() {
262                use rand::SeedableRng;
263                use rand_xorshift::XorShiftRng;
264                let mut rng = XorShiftRng::from_seed(crate::tests::SEED);
265                crate::pluto_eris::fp12::test::$test(&mut rng, $size);
266            }
267            }
268        };
269    }
270    use ff::Field;
271    use rand::RngCore;
272
273    use super::*;
274    use crate::{arith_test, frobenius_test, setup_f12_test_funcs, test};
275
276    arith_test!(Fp12);
277
278    // F12 specific
279    setup_f12_test_funcs!(Fp12, Fp6, Fp2);
280    test_fp12!(f12_mul_by_014_, 500);
281    test_fp12!(f12_mul_by_034_, 500);
282    frobenius_test!(Fp12, Fp, 8);
283}