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
9pub 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(); 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
41pub const FROBENIUS_COEFF_FP12_C1: [Fp2; 12] = [
43 Fp2::ONE,
45 Fp2 {
47 c0: Fp::from_raw([
49 0x2ee965dfef2303d3,
50 0x4e70648622c750f3,
51 0x1df055384b9e6cfd,
52 0x5d89c647b90de8f4,
53 0xd9892dedd51f3069,
54 0xdf0709dc343113cc,
55 0x03c3ad3da8b99cb1,
56 ]),
57 c1: Fp::from_raw([
59 0xfa0be24ad758a5ff,
60 0x59f9373f4cf44e6a,
61 0x9f03876b2ddb1435,
62 0xf333d05254029488,
63 0xccb29838628f04b6,
64 0xaaa3b912182da22d,
65 0x149fd9ed2c7affe7,
66 ]),
67 },
68 Fp2 {
70 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 {
84 c0: Fp::from_raw([
86 0x28a3be71be4995ca,
87 0xf4af912a897f60a1,
88 0x89d390efef216fe4,
89 0xa5d8739325984fc8,
90 0xaf5ca1e56a2a81e6,
91 0x5764b80089c40010,
92 0x1baee9e044d94d20,
93 ]),
94 c1: Fp::from_raw([
96 0x678f4479a1151232,
97 0x6f45d28e4ef1ecb9,
98 0x0b3c35a77291b29d,
99 0x07cd6b44b03ef113,
100 0xe65e47a7716bc8bc,
101 0x9b26f1795339413b,
102 0x20d4c11700e83282,
103 ]),
104 },
105 Fp2 {
107 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 {
121 c0: Fp::from_raw([
123 0xf9ba5891cf2691f7,
124 0xa63f2ca466b80fad,
125 0x6be33bb7a38302e7,
126 0x484ead4b6c8a66d4,
127 0xd5d373f7950b517d,
128 0x785dae245592ec43,
129 0x17eb3ca29c1fb06e,
130 ]),
131 c1: Fp::from_raw([
133 0x6d83622ec9bc6c33,
134 0x154c9b4f01fd9e4e,
135 0x6c38ae3c44b69e68,
136 0x14999af25c3c5c8a,
137 0x19abaf6f0edcc405,
138 0xf08338673b0b9f0e,
139 0x0c34e729d46d329a,
140 ]),
141 },
142 Fp2 {
144 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 {
158 c0: Fp::from_raw([
160 0x711696f310dcfc2e,
161 0x5437843cdd3f6852,
162 0xc6b750c6440f92d9,
163 0xe6b5d415217c8387,
164 0xce7a9c891f19f605,
165 0x2229d623d94e5d17,
166 0x203c52c25746874e,
167 ]),
168 c1: Fp::from_raw([
170 0xa5f41a8828a75a02,
171 0x48aeb183b3126ada,
172 0x45a41e9361d2eba1,
173 0x510bca0a8687d7f3,
174 0xdb51323e91aa21b8,
175 0x568d26edf551ceb6,
176 0x0f602612d3852418,
177 ]),
178 },
179 Fp2 {
181 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 {
195 c0: Fp::from_raw([
197 0x775c3e6141b66a37,
198 0xadf85798768758a4,
199 0x5ad4150ea08c8ff1,
200 0x9e6726c9b4f21cb3,
201 0xf8a728918a0ea488,
202 0xa9cc27ff83bb70d3,
203 0x0851161fbb26d6df,
204 ]),
205 c1: Fp::from_raw([
207 0x3870b8595eeaedcf,
208 0x33621634b114cc8c,
209 0xd96b70571d1c4d39,
210 0x3c722f182a4b7b68,
211 0xc1a582cf82cd5db3,
212 0x6609ee86ba462fa8,
213 0x032b3ee8ff17f17d,
214 ]),
215 },
216 Fp2 {
218 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 {
232 c0: Fp::from_raw([
234 0xa645a44130d96e0a,
235 0xfc68bc1e994ea997,
236 0x78c46a46ec2afcee,
237 0xfbf0ed116e0005a7,
238 0xd230567f5f2dd4f1,
239 0x88d331dbb7ec84a0,
240 0x0c14c35d63e07391,
241 ]),
242 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 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}