1use crate::{
4 impl_add_binop_specify_output, impl_binops_additive, impl_binops_additive_specify_output,
5 impl_binops_multiplicative, impl_binops_multiplicative_mixed, impl_sub_binop_specify_output,
6};
7
8use super::fp::*;
9use super::fp2::*;
10use super::fp6::*;
11
12use core::fmt;
13use core::ops::{Add, Mul, Neg, Sub};
14use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
15
16use rand_core::RngCore;
17
18pub struct Fp12 {
20 pub c0: Fp6,
21 pub c1: Fp6,
22}
23
24impl From<Fp> for Fp12 {
25 fn from(f: Fp) -> Fp12 {
26 Fp12 {
27 c0: Fp6::from(f),
28 c1: Fp6::zero(),
29 }
30 }
31}
32
33impl From<Fp2> for Fp12 {
34 fn from(f: Fp2) -> Fp12 {
35 Fp12 {
36 c0: Fp6::from(f),
37 c1: Fp6::zero(),
38 }
39 }
40}
41
42impl From<Fp6> for Fp12 {
43 fn from(f: Fp6) -> Fp12 {
44 Fp12 {
45 c0: f,
46 c1: Fp6::zero(),
47 }
48 }
49}
50
51impl Eq for Fp12 {}
52impl PartialEq for Fp12 {
53 fn eq(&self, other: &Fp12) -> bool {
54 self.ct_eq(other).into()
55 }
56}
57
58impl Copy for Fp12 {}
59impl Clone for Fp12 {
60 #[inline]
61 fn clone(&self) -> Self {
62 *self
63 }
64}
65
66impl Default for Fp12 {
67 fn default() -> Self {
68 Fp12::zero()
69 }
70}
71
72#[cfg(feature = "zeroize")]
73impl zeroize::DefaultIsZeroes for Fp12 {}
74
75impl fmt::Debug for Fp12 {
76 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
77 write!(f, "{:?} + ({:?})*w", self.c0, self.c1)
78 }
79}
80
81impl ConditionallySelectable for Fp12 {
82 #[inline(always)]
83 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
84 Fp12 {
85 c0: Fp6::conditional_select(&a.c0, &b.c0, choice),
86 c1: Fp6::conditional_select(&a.c1, &b.c1, choice),
87 }
88 }
89}
90
91impl ConstantTimeEq for Fp12 {
92 #[inline(always)]
93 fn ct_eq(&self, other: &Self) -> Choice {
94 self.c0.ct_eq(&other.c0) & self.c1.ct_eq(&other.c1)
95 }
96}
97
98impl Fp12 {
99 #[inline]
100 pub const fn zero() -> Self {
101 Fp12 {
102 c0: Fp6::zero(),
103 c1: Fp6::zero(),
104 }
105 }
106
107 #[inline]
108 pub const fn one() -> Self {
109 Fp12 {
110 c0: Fp6::one(),
111 c1: Fp6::zero(),
112 }
113 }
114
115 pub(crate) fn random(mut rng: impl RngCore) -> Self {
116 Fp12 {
117 c0: Fp6::random(&mut rng),
118 c1: Fp6::random(&mut rng),
119 }
120 }
121
122 pub fn double(&self) -> Self {
123 Self {
124 c0: self.c0.double(),
125 c1: self.c1.double(),
126 }
127 }
128
129 pub fn mul_by_014(&self, c0: &Fp2, c1: &Fp2, c4: &Fp2) -> Fp12 {
130 let aa = self.c0.mul_by_01(c0, c1);
131 let bb = self.c1.mul_by_1(c4);
132 let o = c1 + c4;
133 let c1 = self.c1 + self.c0;
134 let c1 = c1.mul_by_01(c0, &o);
135 let c1 = c1 - aa - bb;
136 let c0 = bb;
137 let c0 = c0.mul_by_nonresidue();
138 let c0 = c0 + aa;
139
140 Fp12 { c0, c1 }
141 }
142
143 #[inline(always)]
144 pub fn is_zero(&self) -> Choice {
145 self.c0.is_zero() & self.c1.is_zero()
146 }
147
148 #[inline(always)]
149 pub fn conjugate(&self) -> Self {
150 Fp12 {
151 c0: self.c0,
152 c1: -self.c1,
153 }
154 }
155
156 #[inline(always)]
158 pub fn frobenius_map(&self) -> Self {
159 let c0 = self.c0.frobenius_map();
160 let c1 = self.c1.frobenius_map();
161
162 let c1 = c1
164 * Fp6::from(Fp2 {
165 c0: Fp::from_raw_unchecked([
166 0x0708_9552_b319_d465,
167 0xc669_5f92_b50a_8313,
168 0x97e8_3ccc_d117_228f,
169 0xa35b_aeca_b2dc_29ee,
170 0x1ce3_93ea_5daa_ce4d,
171 0x08f2_220f_b0fb_66eb,
172 ]),
173 c1: Fp::from_raw_unchecked([
174 0xb2f6_6aad_4ce5_d646,
175 0x5842_a06b_fc49_7cec,
176 0xcf48_95d4_2599_d394,
177 0xc11b_9cba_40a8_e8d0,
178 0x2e38_13cb_e5a0_de89,
179 0x110e_efda_8884_7faf,
180 ]),
181 });
182
183 Fp12 { c0, c1 }
184 }
185
186 #[inline]
187 pub fn square(&self) -> Self {
188 let ab = self.c0 * self.c1;
189 let c0c1 = self.c0 + self.c1;
190 let c0 = self.c1.mul_by_nonresidue();
191 let c0 = c0 + self.c0;
192 let c0 = c0 * c0c1;
193 let c0 = c0 - ab;
194 let c1 = ab + ab;
195 let c0 = c0 - ab.mul_by_nonresidue();
196
197 Fp12 { c0, c1 }
198 }
199
200 pub fn invert(&self) -> CtOption<Self> {
201 (self.c0.square() - self.c1.square().mul_by_nonresidue())
202 .invert()
203 .map(|t| Fp12 {
204 c0: self.c0 * t,
205 c1: self.c1 * -t,
206 })
207 }
208}
209
210impl ff::Field for Fp12 {
211 const ZERO: Self = Self::zero();
212
213 const ONE: Self = Self::one();
214
215 fn random(mut rng: impl RngCore) -> Self {
216 Fp12 {
217 c0: Fp6::random(&mut rng),
218 c1: Fp6::random(&mut rng),
219 }
220 }
221
222 fn is_zero(&self) -> Choice {
223 self.c0.is_zero() & self.c1.is_zero()
224 }
225
226 fn square(&self) -> Self {
227 self.square()
228 }
229
230 fn double(&self) -> Self {
231 self.double()
232 }
233
234 fn sqrt(&self) -> CtOption<Self> {
235 unimplemented!()
236 }
237
238 fn invert(&self) -> CtOption<Self> {
239 self.invert()
240 }
241
242 fn sqrt_ratio(_num: &Self, _div: &Self) -> (Choice, Self) {
243 unimplemented!()
244 }
245}
246
247impl<'a, 'b> Mul<&'b Fp12> for &'a Fp12 {
248 type Output = Fp12;
249
250 #[inline]
251 fn mul(self, other: &'b Fp12) -> Self::Output {
252 let aa = self.c0 * other.c0;
253 let bb = self.c1 * other.c1;
254 let o = other.c0 + other.c1;
255 let c1 = self.c1 + self.c0;
256 let c1 = c1 * o;
257 let c1 = c1 - aa;
258 let c1 = c1 - bb;
259 let c0 = bb.mul_by_nonresidue();
260 let c0 = c0 + aa;
261
262 Fp12 { c0, c1 }
263 }
264}
265
266impl<'a, 'b> Add<&'b Fp12> for &'a Fp12 {
267 type Output = Fp12;
268
269 #[inline]
270 fn add(self, rhs: &'b Fp12) -> Self::Output {
271 Fp12 {
272 c0: self.c0 + rhs.c0,
273 c1: self.c1 + rhs.c1,
274 }
275 }
276}
277
278impl<'a> Neg for &'a Fp12 {
279 type Output = Fp12;
280
281 #[inline]
282 fn neg(self) -> Self::Output {
283 Fp12 {
284 c0: -self.c0,
285 c1: -self.c1,
286 }
287 }
288}
289
290impl Neg for Fp12 {
291 type Output = Fp12;
292
293 #[inline]
294 fn neg(self) -> Self::Output {
295 -&self
296 }
297}
298
299impl<'a, 'b> Sub<&'b Fp12> for &'a Fp12 {
300 type Output = Fp12;
301
302 #[inline]
303 fn sub(self, rhs: &'b Fp12) -> Self::Output {
304 Fp12 {
305 c0: self.c0 - rhs.c0,
306 c1: self.c1 - rhs.c1,
307 }
308 }
309}
310
311impl_binops_additive!(Fp12, Fp12);
312impl_binops_multiplicative!(Fp12, Fp12);
313crate::impl_sum_prod!(Fp12);
314
315pub const FROBENIUS_COEFF_FQ12_C1: [Fp2; 12] = [
317 Fp2 {
319 c0: Fp([
320 0x760900000002fffd,
321 0xebf4000bc40c0002,
322 0x5f48985753c758ba,
323 0x77ce585370525745,
324 0x5c071a97a256ec6d,
325 0x15f65ec3fa80e493,
326 ]),
327 c1: Fp([0x0, 0x0, 0x0, 0x0, 0x0, 0x0]),
328 },
329 Fp2 {
331 c0: Fp([
332 0x7089552b319d465,
333 0xc6695f92b50a8313,
334 0x97e83cccd117228f,
335 0xa35baecab2dc29ee,
336 0x1ce393ea5daace4d,
337 0x8f2220fb0fb66eb,
338 ]),
339 c1: Fp([
340 0xb2f66aad4ce5d646,
341 0x5842a06bfc497cec,
342 0xcf4895d42599d394,
343 0xc11b9cba40a8e8d0,
344 0x2e3813cbe5a0de89,
345 0x110eefda88847faf,
346 ]),
347 },
348 Fp2 {
350 c0: Fp([
351 0xecfb361b798dba3a,
352 0xc100ddb891865a2c,
353 0xec08ff1232bda8e,
354 0xd5c13cc6f1ca4721,
355 0x47222a47bf7b5c04,
356 0x110f184e51c5f59,
357 ]),
358 c1: Fp([0x0, 0x0, 0x0, 0x0, 0x0, 0x0]),
359 },
360 Fp2 {
362 c0: Fp([
363 0x3e2f585da55c9ad1,
364 0x4294213d86c18183,
365 0x382844c88b623732,
366 0x92ad2afd19103e18,
367 0x1d794e4fac7cf0b9,
368 0xbd592fc7d825ec8,
369 ]),
370 c1: Fp([
371 0x7bcfa7a25aa30fda,
372 0xdc17dec12a927e7c,
373 0x2f088dd86b4ebef1,
374 0xd1ca2087da74d4a7,
375 0x2da2596696cebc1d,
376 0xe2b7eedbbfd87d2,
377 ]),
378 },
379 Fp2 {
381 c0: Fp([
382 0x30f1361b798a64e8,
383 0xf3b8ddab7ece5a2a,
384 0x16a8ca3ac61577f7,
385 0xc26a2ff874fd029b,
386 0x3636b76660701c6e,
387 0x51ba4ab241b6160,
388 ]),
389 c1: Fp([0x0, 0x0, 0x0, 0x0, 0x0, 0x0]),
390 },
391 Fp2 {
393 c0: Fp([
394 0x3726c30af242c66c,
395 0x7c2ac1aad1b6fe70,
396 0xa04007fbba4b14a2,
397 0xef517c3266341429,
398 0x95ba654ed2226b,
399 0x2e370eccc86f7dd,
400 ]),
401 c1: Fp([
402 0x82d83cf50dbce43f,
403 0xa2813e53df9d018f,
404 0xc6f0caa53c65e181,
405 0x7525cf528d50fe95,
406 0x4a85ed50f4798a6b,
407 0x171da0fd6cf8eebd,
408 ]),
409 },
410 Fp2 {
412 c0: Fp([
413 0x43f5fffffffcaaae,
414 0x32b7fff2ed47fffd,
415 0x7e83a49a2e99d69,
416 0xeca8f3318332bb7a,
417 0xef148d1ea0f4c069,
418 0x40ab3263eff0206,
419 ]),
420 c1: Fp([0x0, 0x0, 0x0, 0x0, 0x0, 0x0]),
421 },
422 Fp2 {
424 c0: Fp([
425 0xb2f66aad4ce5d646,
426 0x5842a06bfc497cec,
427 0xcf4895d42599d394,
428 0xc11b9cba40a8e8d0,
429 0x2e3813cbe5a0de89,
430 0x110eefda88847faf,
431 ]),
432 c1: Fp([
433 0x7089552b319d465,
434 0xc6695f92b50a8313,
435 0x97e83cccd117228f,
436 0xa35baecab2dc29ee,
437 0x1ce393ea5daace4d,
438 0x8f2220fb0fb66eb,
439 ]),
440 },
441 Fp2 {
443 c0: Fp([
444 0xcd03c9e48671f071,
445 0x5dab22461fcda5d2,
446 0x587042afd3851b95,
447 0x8eb60ebe01bacb9e,
448 0x3f97d6e83d050d2,
449 0x18f0206554638741,
450 ]),
451 c1: Fp([0x0, 0x0, 0x0, 0x0, 0x0, 0x0]),
452 },
453 Fp2 {
455 c0: Fp([
456 0x7bcfa7a25aa30fda,
457 0xdc17dec12a927e7c,
458 0x2f088dd86b4ebef1,
459 0xd1ca2087da74d4a7,
460 0x2da2596696cebc1d,
461 0xe2b7eedbbfd87d2,
462 ]),
463 c1: Fp([
464 0x3e2f585da55c9ad1,
465 0x4294213d86c18183,
466 0x382844c88b623732,
467 0x92ad2afd19103e18,
468 0x1d794e4fac7cf0b9,
469 0xbd592fc7d825ec8,
470 ]),
471 },
472 Fp2 {
474 c0: Fp([
475 0x890dc9e4867545c3,
476 0x2af322533285a5d5,
477 0x50880866309b7e2c,
478 0xa20d1b8c7e881024,
479 0x14e4f04fe2db9068,
480 0x14e56d3f1564853a,
481 ]),
482 c1: Fp([0x0, 0x0, 0x0, 0x0, 0x0, 0x0]),
483 },
484 Fp2 {
486 c0: Fp([
487 0x82d83cf50dbce43f,
488 0xa2813e53df9d018f,
489 0xc6f0caa53c65e181,
490 0x7525cf528d50fe95,
491 0x4a85ed50f4798a6b,
492 0x171da0fd6cf8eebd,
493 ]),
494 c1: Fp([
495 0x3726c30af242c66c,
496 0x7c2ac1aad1b6fe70,
497 0xa04007fbba4b14a2,
498 0xef517c3266341429,
499 0x95ba654ed2226b,
500 0x2e370eccc86f7dd,
501 ]),
502 },
503];
504
505#[test]
506fn test_arithmetic() {
507 use super::fp::*;
508 use super::fp2::*;
509
510 let a = Fp12 {
511 c0: Fp6 {
512 c0: Fp2 {
513 c0: Fp::from_raw_unchecked([
514 0x47f9_cb98_b1b8_2d58,
515 0x5fe9_11eb_a3aa_1d9d,
516 0x96bf_1b5f_4dd8_1db3,
517 0x8100_d27c_c925_9f5b,
518 0xafa2_0b96_7464_0eab,
519 0x09bb_cea7_d8d9_497d,
520 ]),
521 c1: Fp::from_raw_unchecked([
522 0x0303_cb98_b166_2daa,
523 0xd931_10aa_0a62_1d5a,
524 0xbfa9_820c_5be4_a468,
525 0x0ba3_643e_cb05_a348,
526 0xdc35_34bb_1f1c_25a6,
527 0x06c3_05bb_19c0_e1c1,
528 ]),
529 },
530 c1: Fp2 {
531 c0: Fp::from_raw_unchecked([
532 0x46f9_cb98_b162_d858,
533 0x0be9_109c_f7aa_1d57,
534 0xc791_bc55_fece_41d2,
535 0xf84c_5770_4e38_5ec2,
536 0xcb49_c1d9_c010_e60f,
537 0x0acd_b8e1_58bf_e3c8,
538 ]),
539 c1: Fp::from_raw_unchecked([
540 0x8aef_cb98_b15f_8306,
541 0x3ea1_108f_e4f2_1d54,
542 0xcf79_f69f_a1b7_df3b,
543 0xe4f5_4aa1_d16b_1a3c,
544 0xba5e_4ef8_6105_a679,
545 0x0ed8_6c07_97be_e5cf,
546 ]),
547 },
548 c2: Fp2 {
549 c0: Fp::from_raw_unchecked([
550 0xcee5_cb98_b15c_2db4,
551 0x7159_1082_d23a_1d51,
552 0xd762_30e9_44a1_7ca4,
553 0xd19e_3dd3_549d_d5b6,
554 0xa972_dc17_01fa_66e3,
555 0x12e3_1f2d_d6bd_e7d6,
556 ]),
557 c1: Fp::from_raw_unchecked([
558 0xad2a_cb98_b173_2d9d,
559 0x2cfd_10dd_0696_1d64,
560 0x0739_6b86_c6ef_24e8,
561 0xbd76_e2fd_b1bf_c820,
562 0x6afe_a7f6_de94_d0d5,
563 0x1099_4b0c_5744_c040,
564 ]),
565 },
566 },
567 c1: Fp6 {
568 c0: Fp2 {
569 c0: Fp::from_raw_unchecked([
570 0x47f9_cb98_b1b8_2d58,
571 0x5fe9_11eb_a3aa_1d9d,
572 0x96bf_1b5f_4dd8_1db3,
573 0x8100_d27c_c925_9f5b,
574 0xafa2_0b96_7464_0eab,
575 0x09bb_cea7_d8d9_497d,
576 ]),
577 c1: Fp::from_raw_unchecked([
578 0x0303_cb98_b166_2daa,
579 0xd931_10aa_0a62_1d5a,
580 0xbfa9_820c_5be4_a468,
581 0x0ba3_643e_cb05_a348,
582 0xdc35_34bb_1f1c_25a6,
583 0x06c3_05bb_19c0_e1c1,
584 ]),
585 },
586 c1: Fp2 {
587 c0: Fp::from_raw_unchecked([
588 0x46f9_cb98_b162_d858,
589 0x0be9_109c_f7aa_1d57,
590 0xc791_bc55_fece_41d2,
591 0xf84c_5770_4e38_5ec2,
592 0xcb49_c1d9_c010_e60f,
593 0x0acd_b8e1_58bf_e3c8,
594 ]),
595 c1: Fp::from_raw_unchecked([
596 0x8aef_cb98_b15f_8306,
597 0x3ea1_108f_e4f2_1d54,
598 0xcf79_f69f_a1b7_df3b,
599 0xe4f5_4aa1_d16b_1a3c,
600 0xba5e_4ef8_6105_a679,
601 0x0ed8_6c07_97be_e5cf,
602 ]),
603 },
604 c2: Fp2 {
605 c0: Fp::from_raw_unchecked([
606 0xcee5_cb98_b15c_2db4,
607 0x7159_1082_d23a_1d51,
608 0xd762_30e9_44a1_7ca4,
609 0xd19e_3dd3_549d_d5b6,
610 0xa972_dc17_01fa_66e3,
611 0x12e3_1f2d_d6bd_e7d6,
612 ]),
613 c1: Fp::from_raw_unchecked([
614 0xad2a_cb98_b173_2d9d,
615 0x2cfd_10dd_0696_1d64,
616 0x0739_6b86_c6ef_24e8,
617 0xbd76_e2fd_b1bf_c820,
618 0x6afe_a7f6_de94_d0d5,
619 0x1099_4b0c_5744_c040,
620 ]),
621 },
622 },
623 };
624
625 let b = Fp12 {
626 c0: Fp6 {
627 c0: Fp2 {
628 c0: Fp::from_raw_unchecked([
629 0x47f9_cb98_b1b8_2d58,
630 0x5fe9_11eb_a3aa_1d9d,
631 0x96bf_1b5f_4dd8_1db3,
632 0x8100_d272_c925_9f5b,
633 0xafa2_0b96_7464_0eab,
634 0x09bb_cea7_d8d9_497d,
635 ]),
636 c1: Fp::from_raw_unchecked([
637 0x0303_cb98_b166_2daa,
638 0xd931_10aa_0a62_1d5a,
639 0xbfa9_820c_5be4_a468,
640 0x0ba3_643e_cb05_a348,
641 0xdc35_34bb_1f1c_25a6,
642 0x06c3_05bb_19c0_e1c1,
643 ]),
644 },
645 c1: Fp2 {
646 c0: Fp::from_raw_unchecked([
647 0x46f9_cb98_b162_d858,
648 0x0be9_109c_f7aa_1d57,
649 0xc791_bc55_fece_41d2,
650 0xf84c_5770_4e38_5ec2,
651 0xcb49_c1d9_c010_e60f,
652 0x0acd_b8e1_58bf_e348,
653 ]),
654 c1: Fp::from_raw_unchecked([
655 0x8aef_cb98_b15f_8306,
656 0x3ea1_108f_e4f2_1d54,
657 0xcf79_f69f_a1b7_df3b,
658 0xe4f5_4aa1_d16b_1a3c,
659 0xba5e_4ef8_6105_a679,
660 0x0ed8_6c07_97be_e5cf,
661 ]),
662 },
663 c2: Fp2 {
664 c0: Fp::from_raw_unchecked([
665 0xcee5_cb98_b15c_2db4,
666 0x7159_1082_d23a_1d51,
667 0xd762_30e9_44a1_7ca4,
668 0xd19e_3dd3_549d_d5b6,
669 0xa972_dc17_01fa_66e3,
670 0x12e3_1f2d_d6bd_e7d6,
671 ]),
672 c1: Fp::from_raw_unchecked([
673 0xad2a_cb98_b173_2d9d,
674 0x2cfd_10dd_0696_1d64,
675 0x0739_6b86_c6ef_24e8,
676 0xbd76_e2fd_b1bf_c820,
677 0x6afe_a7f6_de94_d0d5,
678 0x1099_4b0c_5744_c040,
679 ]),
680 },
681 },
682 c1: Fp6 {
683 c0: Fp2 {
684 c0: Fp::from_raw_unchecked([
685 0x47f9_cb98_b1b8_2d58,
686 0x5fe9_11eb_a3aa_1d9d,
687 0x96bf_1b5f_4dd2_1db3,
688 0x8100_d27c_c925_9f5b,
689 0xafa2_0b96_7464_0eab,
690 0x09bb_cea7_d8d9_497d,
691 ]),
692 c1: Fp::from_raw_unchecked([
693 0x0303_cb98_b166_2daa,
694 0xd931_10aa_0a62_1d5a,
695 0xbfa9_820c_5be4_a468,
696 0x0ba3_643e_cb05_a348,
697 0xdc35_34bb_1f1c_25a6,
698 0x06c3_05bb_19c0_e1c1,
699 ]),
700 },
701 c1: Fp2 {
702 c0: Fp::from_raw_unchecked([
703 0x46f9_cb98_b162_d858,
704 0x0be9_109c_f7aa_1d57,
705 0xc791_bc55_fece_41d2,
706 0xf84c_5770_4e38_5ec2,
707 0xcb49_c1d9_c010_e60f,
708 0x0acd_b8e1_58bf_e3c8,
709 ]),
710 c1: Fp::from_raw_unchecked([
711 0x8aef_cb98_b15f_8306,
712 0x3ea1_108f_e4f2_1d54,
713 0xcf79_f69f_a117_df3b,
714 0xe4f5_4aa1_d16b_1a3c,
715 0xba5e_4ef8_6105_a679,
716 0x0ed8_6c07_97be_e5cf,
717 ]),
718 },
719 c2: Fp2 {
720 c0: Fp::from_raw_unchecked([
721 0xcee5_cb98_b15c_2db4,
722 0x7159_1082_d23a_1d51,
723 0xd762_30e9_44a1_7ca4,
724 0xd19e_3dd3_549d_d5b6,
725 0xa972_dc17_01fa_66e3,
726 0x12e3_1f2d_d6bd_e7d6,
727 ]),
728 c1: Fp::from_raw_unchecked([
729 0xad2a_cb98_b173_2d9d,
730 0x2cfd_10dd_0696_1d64,
731 0x0739_6b86_c6ef_24e8,
732 0xbd76_e2fd_b1bf_c820,
733 0x6afe_a7f6_de94_d0d5,
734 0x1099_4b0c_5744_c040,
735 ]),
736 },
737 },
738 };
739
740 let c = Fp12 {
741 c0: Fp6 {
742 c0: Fp2 {
743 c0: Fp::from_raw_unchecked([
744 0x47f9_cb98_71b8_2d58,
745 0x5fe9_11eb_a3aa_1d9d,
746 0x96bf_1b5f_4dd8_1db3,
747 0x8100_d27c_c925_9f5b,
748 0xafa2_0b96_7464_0eab,
749 0x09bb_cea7_d8d9_497d,
750 ]),
751 c1: Fp::from_raw_unchecked([
752 0x0303_cb98_b166_2daa,
753 0xd931_10aa_0a62_1d5a,
754 0xbfa9_820c_5be4_a468,
755 0x0ba3_643e_cb05_a348,
756 0xdc35_34bb_1f1c_25a6,
757 0x06c3_05bb_19c0_e1c1,
758 ]),
759 },
760 c1: Fp2 {
761 c0: Fp::from_raw_unchecked([
762 0x46f9_cb98_b162_d858,
763 0x0be9_109c_f7aa_1d57,
764 0x7791_bc55_fece_41d2,
765 0xf84c_5770_4e38_5ec2,
766 0xcb49_c1d9_c010_e60f,
767 0x0acd_b8e1_58bf_e3c8,
768 ]),
769 c1: Fp::from_raw_unchecked([
770 0x8aef_cb98_b15f_8306,
771 0x3ea1_108f_e4f2_1d54,
772 0xcf79_f69f_a1b7_df3b,
773 0xe4f5_4aa1_d16b_133c,
774 0xba5e_4ef8_6105_a679,
775 0x0ed8_6c07_97be_e5cf,
776 ]),
777 },
778 c2: Fp2 {
779 c0: Fp::from_raw_unchecked([
780 0xcee5_cb98_b15c_2db4,
781 0x7159_1082_d23a_1d51,
782 0xd762_40e9_44a1_7ca4,
783 0xd19e_3dd3_549d_d5b6,
784 0xa972_dc17_01fa_66e3,
785 0x12e3_1f2d_d6bd_e7d6,
786 ]),
787 c1: Fp::from_raw_unchecked([
788 0xad2a_cb98_b173_2d9d,
789 0x2cfd_10dd_0696_1d64,
790 0x0739_6b86_c6ef_24e8,
791 0xbd76_e2fd_b1bf_c820,
792 0x6afe_a7f6_de94_d0d5,
793 0x1099_4b0c_1744_c040,
794 ]),
795 },
796 },
797 c1: Fp6 {
798 c0: Fp2 {
799 c0: Fp::from_raw_unchecked([
800 0x47f9_cb98_b1b8_2d58,
801 0x5fe9_11eb_a3aa_1d9d,
802 0x96bf_1b5f_4dd8_1db3,
803 0x8100_d27c_c925_9f5b,
804 0xafa2_0b96_7464_0eab,
805 0x09bb_cea7_d8d9_497d,
806 ]),
807 c1: Fp::from_raw_unchecked([
808 0x0303_cb98_b166_2daa,
809 0xd931_10aa_0a62_1d5a,
810 0xbfa9_820c_5be4_a468,
811 0x0ba3_643e_cb05_a348,
812 0xdc35_34bb_1f1c_25a6,
813 0x06c3_05bb_19c0_e1c1,
814 ]),
815 },
816 c1: Fp2 {
817 c0: Fp::from_raw_unchecked([
818 0x46f9_cb98_b162_d858,
819 0x0be9_109c_f7aa_1d57,
820 0xc791_bc55_fece_41d2,
821 0xf84c_5770_4e38_5ec2,
822 0xcb49_c1d3_c010_e60f,
823 0x0acd_b8e1_58bf_e3c8,
824 ]),
825 c1: Fp::from_raw_unchecked([
826 0x8aef_cb98_b15f_8306,
827 0x3ea1_108f_e4f2_1d54,
828 0xcf79_f69f_a1b7_df3b,
829 0xe4f5_4aa1_d16b_1a3c,
830 0xba5e_4ef8_6105_a679,
831 0x0ed8_6c07_97be_e5cf,
832 ]),
833 },
834 c2: Fp2 {
835 c0: Fp::from_raw_unchecked([
836 0xcee5_cb98_b15c_2db4,
837 0x7159_1082_d23a_1d51,
838 0xd762_30e9_44a1_7ca4,
839 0xd19e_3dd3_549d_d5b6,
840 0xa972_dc17_01fa_66e3,
841 0x12e3_1f2d_d6bd_e7d6,
842 ]),
843 c1: Fp::from_raw_unchecked([
844 0xad2a_cb98_b173_2d9d,
845 0x2cfd_10dd_0696_1d64,
846 0x0739_6b86_c6ef_24e8,
847 0xbd76_e2fd_b1bf_c820,
848 0x6afe_a7f6_de94_d0d5,
849 0x1099_4b0c_5744_1040,
850 ]),
851 },
852 },
853 };
854
855 let a = a.square().invert().unwrap().square() + c;
859 let b = b.square().invert().unwrap().square() + a;
860 let c = c.square().invert().unwrap().square() + b;
861
862 assert_eq!(a.square(), a * a);
863 assert_eq!(b.square(), b * b);
864 assert_eq!(c.square(), c * c);
865
866 assert_eq!((a + b) * c.square(), (c * c * a) + (c * c * b));
867
868 assert_eq!(
869 a.invert().unwrap() * b.invert().unwrap(),
870 (a * b).invert().unwrap()
871 );
872 assert_eq!(a.invert().unwrap() * a, Fp12::one());
873
874 assert!(a != a.frobenius_map());
875 assert_eq!(
876 a,
877 a.frobenius_map()
878 .frobenius_map()
879 .frobenius_map()
880 .frobenius_map()
881 .frobenius_map()
882 .frobenius_map()
883 .frobenius_map()
884 .frobenius_map()
885 .frobenius_map()
886 .frobenius_map()
887 .frobenius_map()
888 .frobenius_map()
889 );
890}
891
892#[cfg(feature = "zeroize")]
893#[test]
894fn test_zeroize() {
895 use zeroize::Zeroize;
896
897 let mut a = Fp12::one();
898 a.zeroize();
899 assert!(bool::from(a.is_zero()));
900}