1use alloc::vec::Vec;
2
3use crate::{
4 arith::U256,
5 fields::{FieldElement, Fq, Fq2, Fq12, Fr, const_fq, fq2_nonresidue},
6};
7use core::{
8 fmt,
9 ops::{Add, Mul, Neg, Sub},
10};
11use rand::Rng;
12
13#[cfg(feature = "rustc-serialize")]
14use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
15
16const ATE_LOOP_COUNT_NAF: [u8; 64] = [
22 1, 0, 1, 0, 0, 0, 3, 0, 3, 0, 0, 0, 3, 0, 1, 0, 3, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 0, 3, 0, 1, 0,
23 0, 3, 0, 0, 0, 0, 3, 0, 1, 0, 0, 0, 3, 0, 3, 0, 0, 1, 0, 0, 0, 3, 0, 0, 3, 0, 1, 0, 1, 0, 0, 0,
24];
25
26pub trait GroupElement:
27 Sized
28 + Copy
29 + Clone
30 + PartialEq
31 + Eq
32 + fmt::Debug
33 + Add<Output = Self>
34 + Sub<Output = Self>
35 + Neg<Output = Self>
36 + Mul<Fr, Output = Self>
37{
38 fn zero() -> Self;
39 fn one() -> Self;
40 fn random<R: Rng>(rng: &mut R) -> Self;
41 fn is_zero(&self) -> bool;
42 fn double(&self) -> Self;
43}
44
45pub trait GroupParams: Sized + fmt::Debug {
46 #[cfg(feature = "rustc-serialize")]
47 type Base: FieldElement + Decodable + Encodable;
48 #[cfg(not(feature = "rustc-serialize"))]
49 type Base: FieldElement;
50
51 fn name() -> &'static str;
52 fn one() -> G<Self>;
53 fn coeff_b() -> Self::Base;
54 fn check_order() -> bool {
55 false
56 }
57}
58
59#[repr(C)]
60pub struct G<P: GroupParams> {
61 x: P::Base,
62 y: P::Base,
63 z: P::Base,
64}
65
66impl<P: GroupParams> G<P> {
67 pub fn new(x: P::Base, y: P::Base, z: P::Base) -> Self {
68 G { x: x, y: y, z: z }
69 }
70
71 pub fn x(&self) -> &P::Base {
72 &self.x
73 }
74
75 pub fn x_mut(&mut self) -> &mut P::Base {
76 &mut self.x
77 }
78
79 pub fn y(&self) -> &P::Base {
80 &self.y
81 }
82
83 pub fn y_mut(&mut self) -> &mut P::Base {
84 &mut self.y
85 }
86
87 pub fn z(&self) -> &P::Base {
88 &self.z
89 }
90
91 pub fn z_mut(&mut self) -> &mut P::Base {
92 &mut self.z
93 }
94}
95
96#[derive(Debug)]
97pub struct AffineG<P: GroupParams> {
98 x: P::Base,
99 y: P::Base,
100}
101
102#[derive(Debug)]
103pub enum Error {
104 NotOnCurve,
105 NotInSubgroup,
106}
107
108impl<P: GroupParams> AffineG<P> {
109 pub fn new(x: P::Base, y: P::Base) -> Result<Self, Error> {
110 if y.squared() == (x.squared() * x) + P::coeff_b() {
111 if P::check_order() {
112 let p: G<P> = G {
113 x: x,
114 y: y,
115 z: P::Base::one(),
116 };
117
118 if (p * (-Fr::one())) + p != G::zero() {
119 return Err(Error::NotInSubgroup);
120 }
121 }
122
123 Ok(AffineG { x: x, y: y })
124 } else {
125 Err(Error::NotOnCurve)
126 }
127 }
128
129 pub fn x(&self) -> &P::Base {
130 &self.x
131 }
132
133 pub fn x_mut(&mut self) -> &mut P::Base {
134 &mut self.x
135 }
136
137 pub fn y(&self) -> &P::Base {
138 &self.y
139 }
140
141 pub fn y_mut(&mut self) -> &mut P::Base {
142 &mut self.y
143 }
144}
145
146impl<P: GroupParams> PartialEq for AffineG<P> {
147 fn eq(&self, other: &Self) -> bool {
148 self.x == other.x && self.y == other.y
149 }
150}
151
152impl<P: GroupParams> Eq for AffineG<P> {}
153
154impl<P: GroupParams> fmt::Debug for G<P> {
155 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
156 write!(f, "{}({:?}, {:?}, {:?})", P::name(), self.x, self.y, self.z)
157 }
158}
159
160impl<P: GroupParams> Clone for G<P> {
161 fn clone(&self) -> Self {
162 G {
163 x: self.x,
164 y: self.y,
165 z: self.z,
166 }
167 }
168}
169
170impl<P: GroupParams> Copy for G<P> {}
171
172impl<P: GroupParams> Clone for AffineG<P> {
173 fn clone(&self) -> Self {
174 AffineG {
175 x: self.x,
176 y: self.y,
177 }
178 }
179}
180
181impl<P: GroupParams> Copy for AffineG<P> {}
182
183impl<P: GroupParams> PartialEq for G<P> {
184 fn eq(&self, other: &Self) -> bool {
185 if self.is_zero() {
186 return other.is_zero();
187 }
188
189 if other.is_zero() {
190 return false;
191 }
192
193 let z1_squared = self.z.squared();
194 let z2_squared = other.z.squared();
195
196 if self.x * z2_squared != other.x * z1_squared {
197 return false;
198 }
199
200 let z1_cubed = self.z * z1_squared;
201 let z2_cubed = other.z * z2_squared;
202
203 if self.y * z2_cubed != other.y * z1_cubed {
204 return false;
205 }
206
207 return true;
208 }
209}
210impl<P: GroupParams> Eq for G<P> {}
211
212impl<P: GroupParams> G<P> {
213 pub fn to_affine(&self) -> Option<AffineG<P>> {
214 if self.z.is_zero() {
215 None
216 } else if self.z == P::Base::one() {
217 Some(AffineG {
218 x: self.x,
219 y: self.y,
220 })
221 } else {
222 let zinv = self.z.inverse().unwrap();
223 let zinv_squared = zinv.squared();
224
225 Some(AffineG {
226 x: self.x * zinv_squared,
227 y: self.y * (zinv_squared * zinv),
228 })
229 }
230 }
231}
232
233impl<P: GroupParams> AffineG<P> {
234 pub fn to_jacobian(&self) -> G<P> {
235 G {
236 x: self.x,
237 y: self.y,
238 z: P::Base::one(),
239 }
240 }
241}
242
243#[cfg(feature = "rustc-serialize")]
244impl<P: GroupParams> Encodable for G<P> {
245 fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
246 if self.is_zero() {
247 let l: u8 = 0;
248 l.encode(s)
249 } else {
250 let l: u8 = 4;
251 l.encode(s)?;
252 self.to_affine().unwrap().encode(s)
253 }
254 }
255}
256
257#[cfg(feature = "rustc-serialize")]
258impl<P: GroupParams> Encodable for AffineG<P> {
259 fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
260 self.x.encode(s)?;
261 self.y.encode(s)?;
262
263 Ok(())
264 }
265}
266
267#[cfg(feature = "rustc-serialize")]
268impl<P: GroupParams> Decodable for G<P> {
269 fn decode<S: Decoder>(s: &mut S) -> Result<G<P>, S::Error> {
270 let l = u8::decode(s)?;
271 if l == 0 {
272 Ok(G::zero())
273 } else if l == 4 {
274 Ok(AffineG::decode(s)?.to_jacobian())
275 } else {
276 Err(s.error("invalid leading byte for uncompressed group element"))
277 }
278 }
279}
280
281#[cfg(feature = "rustc-serialize")]
282impl<P: GroupParams> Decodable for AffineG<P> {
283 fn decode<S: Decoder>(s: &mut S) -> Result<AffineG<P>, S::Error> {
284 let x = P::Base::decode(s)?;
285 let y = P::Base::decode(s)?;
286
287 Self::new(x, y).map_err(|e| match e {
288 Error::NotOnCurve => s.error("point is not on the curve"),
289 Error::NotInSubgroup => s.error("point is not in the subgroup"),
290 })
291 }
292}
293
294impl<P: GroupParams> GroupElement for G<P> {
295 fn zero() -> Self {
296 G {
297 x: P::Base::zero(),
298 y: P::Base::one(),
299 z: P::Base::zero(),
300 }
301 }
302
303 fn one() -> Self {
304 P::one()
305 }
306
307 fn random<R: Rng>(rng: &mut R) -> Self {
308 P::one() * Fr::random(rng)
309 }
310
311 fn is_zero(&self) -> bool {
312 self.z.is_zero()
313 }
314
315 fn double(&self) -> Self {
316 let a = self.x.squared();
317 let b = self.y.squared();
318 let c = b.squared();
319 let mut d = (self.x + b).squared() - a - c;
320 d = d + d;
321 let e = a + a + a;
322 let f = e.squared();
323 let x3 = f - (d + d);
324 let mut eight_c = c + c;
325 eight_c = eight_c + eight_c;
326 eight_c = eight_c + eight_c;
327 let y1z1 = self.y * self.z;
328
329 G {
330 x: x3,
331 y: e * (d - x3) - eight_c,
332 z: y1z1 + y1z1,
333 }
334 }
335}
336
337impl<P: GroupParams> Mul<Fr> for G<P> {
338 type Output = G<P>;
339
340 fn mul(self, other: Fr) -> G<P> {
341 let mut res = G::zero();
342 let mut found_one = false;
343
344 for i in U256::from(other).bits() {
345 if found_one {
346 res = res.double();
347 }
348
349 if i {
350 found_one = true;
351 res = res + self;
352 }
353 }
354
355 res
356 }
357}
358
359impl<P: GroupParams> Add<G<P>> for G<P> {
360 type Output = G<P>;
361
362 fn add(self, other: G<P>) -> G<P> {
363 if self.is_zero() {
364 return other;
365 }
366
367 if other.is_zero() {
368 return self;
369 }
370
371 let z1_squared = self.z.squared();
372 let z2_squared = other.z.squared();
373 let u1 = self.x * z2_squared;
374 let u2 = other.x * z1_squared;
375 let z1_cubed = self.z * z1_squared;
376 let z2_cubed = other.z * z2_squared;
377 let s1 = self.y * z2_cubed;
378 let s2 = other.y * z1_cubed;
379
380 if u1 == u2 && s1 == s2 {
381 self.double()
382 } else {
383 let h = u2 - u1;
384 let s2_minus_s1 = s2 - s1;
385 let i = (h + h).squared();
386 let j = h * i;
387 let r = s2_minus_s1 + s2_minus_s1;
388 let v = u1 * i;
389 let s1_j = s1 * j;
390 let x3 = r.squared() - j - (v + v);
391
392 G {
393 x: x3,
394 y: r * (v - x3) - (s1_j + s1_j),
395 z: ((self.z + other.z).squared() - z1_squared - z2_squared) * h,
396 }
397 }
398 }
399}
400
401impl<P: GroupParams> Neg for G<P> {
402 type Output = G<P>;
403
404 fn neg(self) -> G<P> {
405 if self.is_zero() {
406 self
407 } else {
408 G {
409 x: self.x,
410 y: -self.y,
411 z: self.z,
412 }
413 }
414 }
415}
416
417impl<P: GroupParams> Neg for AffineG<P> {
418 type Output = AffineG<P>;
419
420 fn neg(self) -> AffineG<P> {
421 AffineG {
422 x: self.x,
423 y: -self.y,
424 }
425 }
426}
427
428impl<P: GroupParams> Sub<G<P>> for G<P> {
429 type Output = G<P>;
430
431 fn sub(self, other: G<P>) -> G<P> {
432 self + (-other)
433 }
434}
435
436#[derive(Debug)]
437pub struct G1Params;
438
439impl GroupParams for G1Params {
440 type Base = Fq;
441
442 fn name() -> &'static str {
443 "G1"
444 }
445
446 fn one() -> G<Self> {
447 G {
448 x: Fq::one(),
449 y: const_fq([
450 0xa6ba871b8b1e1b3a,
451 0x14f1d651eb8e167b,
452 0xccdd46def0f28c58,
453 0x1c14ef83340fbe5e,
454 ]),
455 z: Fq::one(),
456 }
457 }
458
459 fn coeff_b() -> Fq {
460 const_fq([
461 0x7a17caa950ad28d7,
462 0x1f6ac17ae15521b9,
463 0x334bea4e696bd284,
464 0x2a1f6744ce179d8e,
465 ])
466 }
467}
468
469pub type G1 = G<G1Params>;
470
471pub type AffineG1 = AffineG<G1Params>;
472
473#[derive(Debug)]
474pub struct G2Params;
475
476impl GroupParams for G2Params {
477 type Base = Fq2;
478
479 fn name() -> &'static str {
480 "G2"
481 }
482
483 fn one() -> G<Self> {
484 G {
485 x: Fq2::new(
486 const_fq([
487 0x8e83b5d102bc2026,
488 0xdceb1935497b0172,
489 0xfbb8264797811adf,
490 0x19573841af96503b,
491 ]),
492 const_fq([
493 0xafb4737da84c6140,
494 0x6043dd5a5802d8c4,
495 0x09e950fc52a02f86,
496 0x14fef0833aea7b6b,
497 ]),
498 ),
499 y: Fq2::new(
500 const_fq([
501 0x619dfa9d886be9f6,
502 0xfe7fd297f59e9b78,
503 0xff9e1a62231b7dfe,
504 0x28fd7eebae9e4206,
505 ]),
506 const_fq([
507 0x64095b56c71856ee,
508 0xdc57f922327d3cbb,
509 0x55f935be33351076,
510 0x0da4a0e693fd6482,
511 ]),
512 ),
513 z: Fq2::one(),
514 }
515 }
516
517 fn coeff_b() -> Fq2 {
518 Fq2::new(
519 const_fq([
520 0x3bf938e377b802a8,
521 0x020b1b273633535d,
522 0x26b7edf049755260,
523 0x2514c6324384a86d,
524 ]),
525 const_fq([
526 0x38e7ecccd1dcff67,
527 0x65f0b37d93ce0d3e,
528 0xd749d0dd22ac00aa,
529 0x0141b9ce4a688d4d,
530 ]),
531 )
532 }
533
534 fn check_order() -> bool {
535 true
536 }
537}
538
539pub type G2 = G<G2Params>;
540
541pub type AffineG2 = AffineG<G2Params>;
542
543#[cfg(test)]
544mod tests;
545
546#[test]
547fn test_g1() {
548 tests::group_trials::<G1>();
549}
550
551#[test]
552fn test_g2() {
553 tests::group_trials::<G2>();
554}
555
556#[test]
557fn test_affine_jacobian_conversion() {
558 let rng = &mut ::rand::rng();
559
560 assert!(G1::zero().to_affine().is_none());
561 assert!(G2::zero().to_affine().is_none());
562
563 for _ in 0..1000 {
564 let a = G1::one() * Fr::random(rng);
565 let b = a.to_affine().unwrap();
566 let c = b.to_jacobian();
567
568 assert_eq!(a, c);
569 }
570
571 for _ in 0..1000 {
572 let a = G2::one() * Fr::random(rng);
573 let b = a.to_affine().unwrap();
574 let c = b.to_jacobian();
575
576 assert_eq!(a, c);
577 }
578}
579
580#[inline]
581fn twist() -> Fq2 {
582 fq2_nonresidue()
583}
584
585#[inline]
586fn two_inv() -> Fq {
587 const_fq([
588 9781510331150239090,
589 15059239858463337189,
590 10331104244869713732,
591 2249375503248834476,
592 ])
593}
594
595#[inline]
596fn twist_mul_by_q_x() -> Fq2 {
597 Fq2::new(
598 const_fq([
599 13075984984163199792,
600 3782902503040509012,
601 8791150885551868305,
602 1825854335138010348,
603 ]),
604 const_fq([
605 7963664994991228759,
606 12257807996192067905,
607 13179524609921305146,
608 2767831111890561987,
609 ]),
610 )
611}
612
613#[inline]
614fn twist_mul_by_q_y() -> Fq2 {
615 Fq2::new(
616 const_fq([
617 16482010305593259561,
618 13488546290961988299,
619 3578621962720924518,
620 2681173117283399901,
621 ]),
622 const_fq([
623 11661927080404088775,
624 553939530661941723,
625 7860678177968807019,
626 3208568454732775116,
627 ]),
628 )
629}
630
631#[derive(PartialEq, Eq)]
632pub struct EllCoeffs {
633 pub ell_0: Fq2,
634 pub ell_vw: Fq2,
635 pub ell_vv: Fq2,
636}
637
638#[derive(PartialEq, Eq)]
639pub struct G2Precomp {
640 pub q: AffineG<G2Params>,
641 pub coeffs: Vec<EllCoeffs>,
642}
643
644impl G2Precomp {
645 pub fn miller_loop(&self, g1: &AffineG<G1Params>) -> Fq12 {
646 let mut f = Fq12::one();
647
648 let mut idx = 0;
649
650 for i in ATE_LOOP_COUNT_NAF.iter() {
651 let c = &self.coeffs[idx];
652 idx += 1;
653 f = f
654 .squared()
655 .mul_by_024(c.ell_0, c.ell_vw.scale(g1.y), c.ell_vv.scale(g1.x));
656
657 if *i != 0 {
658 let c = &self.coeffs[idx];
659 idx += 1;
660 f = f.mul_by_024(c.ell_0, c.ell_vw.scale(g1.y), c.ell_vv.scale(g1.x));
661 }
662 }
663
664 let c = &self.coeffs[idx];
665 idx += 1;
666 f = f.mul_by_024(c.ell_0, c.ell_vw.scale(g1.y), c.ell_vv.scale(g1.x));
667
668 let c = &self.coeffs[idx];
669 f = f.mul_by_024(c.ell_0, c.ell_vw.scale(g1.y), c.ell_vv.scale(g1.x));
670
671 f
672 }
673}
674
675pub fn miller_loop_batch(g2_precomputes: &Vec<G2Precomp>, g1_vec: &Vec<AffineG<G1Params>>) -> Fq12 {
676 let mut f = Fq12::one();
677
678 let mut idx = 0;
679
680 for i in ATE_LOOP_COUNT_NAF.iter() {
681 f = f.squared();
682 for (g2_precompute, g1) in g2_precomputes.iter().zip(g1_vec.iter()) {
683 let c = &g2_precompute.coeffs[idx];
684 f = f.mul_by_024(c.ell_0, c.ell_vw.scale(g1.y), c.ell_vv.scale(g1.x));
685 }
686 idx += 1;
687 if *i != 0 {
688 for (g2_precompute, g1) in g2_precomputes.iter().zip(g1_vec.iter()) {
689 let c = &g2_precompute.coeffs[idx];
690 f = f.mul_by_024(c.ell_0, c.ell_vw.scale(g1.y), c.ell_vv.scale(g1.x));
691 }
692 idx += 1;
693 }
694 }
695
696 for (g2_precompute, g1) in g2_precomputes.iter().zip(g1_vec.iter()) {
697 let c = &g2_precompute.coeffs[idx];
698 f = f.mul_by_024(c.ell_0, c.ell_vw.scale(g1.y), c.ell_vv.scale(g1.x));
699 }
700 idx += 1;
701 for (g2_precompute, g1) in g2_precomputes.iter().zip(g1_vec.iter()) {
702 let c = &g2_precompute.coeffs[idx];
703 f = f.mul_by_024(c.ell_0, c.ell_vw.scale(g1.y), c.ell_vv.scale(g1.x));
704 }
705 f
706}
707
708#[test]
709fn test_miller_loop() {
710 use crate::fields::Fq6;
711
712 let g1 = G1::one()
713 * Fr::from_str(
714 "18097487326282793650237947474982649264364522469319914492172746413872781676",
715 )
716 .unwrap();
717 let g2 = G2::one()
718 * Fr::from_str(
719 "20390255904278144451778773028944684152769293537511418234311120800877067946",
720 )
721 .unwrap();
722
723 let g1_pre = g1.to_affine().unwrap();
724 let g2_pre = g2.to_affine().unwrap().precompute();
725
726 let gt = g2_pre.miller_loop(&g1_pre);
727
728 let expected: Fq12 = Fq12::new(
729 Fq6::new(
730 Fq2::new(
731 Fq::new(U256([
732 51910954035973319022896381997847359481,
733 49070349125448662928383548013678560320,
734 ]))
735 .unwrap(),
736 Fq::new(U256([
737 150594250655925940766158230906714822921,
738 45067780486977162411874315270532662559,
739 ]))
740 .unwrap(),
741 ),
742 Fq2::new(
743 Fq::new(U256([
744 293313211826787380313097274184299135668,
745 28033688961864567415258173424862015279,
746 ]))
747 .unwrap(),
748 Fq::new(U256([
749 167463228417728651969785007140185669229,
750 7077084888790581611350259269763958251,
751 ]))
752 .unwrap(),
753 ),
754 Fq2::new(
755 Fq::new(U256([
756 166574695108782631900870170909221310910,
757 36301755601680728879208628452507017454,
758 ]))
759 .unwrap(),
760 Fq::new(U256([
761 61790765844042689836493058059938629070,
762 8459680572251855304146082351314233167,
763 ]))
764 .unwrap(),
765 ),
766 ),
767 Fq6::new(
768 Fq2::new(
769 Fq::new(U256([
770 274725556782132290265566702453516000786,
771 47645385003117491559484060631887523335,
772 ]))
773 .unwrap(),
774 Fq::new(U256([
775 218741759704184655717004970623859820160,
776 5768209145436844234600983552836237590,
777 ]))
778 .unwrap(),
779 ),
780 Fq2::new(
781 Fq::new(U256([
782 166365676746880051357185694330614395245,
783 44422629177536239628987108174157680084,
784 ]))
785 .unwrap(),
786 Fq::new(U256([
787 188797990739833756731082975171894736944,
788 643465180603364587407484249282263717,
789 ]))
790 .unwrap(),
791 ),
792 Fq2::new(
793 Fq::new(U256([
794 271144479861903489720584548513988144824,
795 10463758518630442972881156820224659715,
796 ]))
797 .unwrap(),
798 Fq::new(U256([
799 214759070354702766397810519515686065785,
800 63150584453541665372008601383729030318,
801 ]))
802 .unwrap(),
803 ),
804 ),
805 );
806 assert_eq!(gt, expected);
807}
808
809impl AffineG<G2Params> {
810 fn mul_by_q(&self) -> Self {
811 AffineG {
812 x: twist_mul_by_q_x() * self.x.frobenius_map(1),
813 y: twist_mul_by_q_y() * self.y.frobenius_map(1),
814 }
815 }
816
817 pub fn precompute(&self) -> G2Precomp {
818 let mut r = self.to_jacobian();
819
820 let mut coeffs = Vec::with_capacity(102);
821
822 let q_neg = self.neg();
823 for i in ATE_LOOP_COUNT_NAF.iter() {
824 coeffs.push(r.doubling_step_for_flipped_miller_loop());
825
826 if *i == 1 {
827 coeffs.push(r.mixed_addition_step_for_flipped_miller_loop(self));
828 }
829 if *i == 3 {
830 coeffs.push(r.mixed_addition_step_for_flipped_miller_loop(&q_neg));
831 }
832 }
833 let q1 = self.mul_by_q();
834 let q2 = -(q1.mul_by_q());
835
836 coeffs.push(r.mixed_addition_step_for_flipped_miller_loop(&q1));
837 coeffs.push(r.mixed_addition_step_for_flipped_miller_loop(&q2));
838
839 G2Precomp {
840 q: *self,
841 coeffs: coeffs,
842 }
843 }
844}
845
846impl G2 {
847 fn mixed_addition_step_for_flipped_miller_loop(
848 &mut self,
849 base: &AffineG<G2Params>,
850 ) -> EllCoeffs {
851 let d = self.x - self.z * base.x;
852 let e = self.y - self.z * base.y;
853 let f = d.squared();
854 let g = e.squared();
855 let h = d * f;
856 let i = self.x * f;
857 let j = self.z * g + h - (i + i);
858
859 self.x = d * j;
860 self.y = e * (i - j) - h * self.y;
861 self.z = self.z * h;
862
863 EllCoeffs {
864 ell_0: twist() * (e * base.x - d * base.y),
865 ell_vv: e.neg(),
866 ell_vw: d,
867 }
868 }
869
870 fn doubling_step_for_flipped_miller_loop(&mut self) -> EllCoeffs {
871 let a = (self.x * self.y).scale(two_inv());
872 let b = self.y.squared();
873 let c = self.z.squared();
874 let d = c + c + c;
875 let e = G2Params::coeff_b() * d;
876 let f = e + e + e;
877 let g = (b + f).scale(two_inv());
878 let h = (self.y + self.z).squared() - (b + c);
879 let i = e - b;
880 let j = self.x.squared();
881 let e_sq = e.squared();
882
883 self.x = a * (b - f);
884 self.y = g.squared() - (e_sq + e_sq + e_sq);
885 self.z = b * h;
886
887 EllCoeffs {
888 ell_0: twist() * i,
889 ell_vw: h.neg(),
890 ell_vv: j + j + j,
891 }
892 }
893}
894
895#[test]
896fn test_prepared_g2() {
897 let g2 = G2::one()
898 * Fr::from_str(
899 "20390255904278144451778773028944684152769293537511418234311120800877067946",
900 )
901 .unwrap();
902
903 let g2_p = g2.to_affine().unwrap().precompute();
904
905 let expected_g2_p = G2Precomp {
906 q: AffineG {
907 x: Fq2::new(
908 Fq::new(U256([
909 286108132425575157823044300810193365120,
910 40955922372263072279965766273066553545,
911 ]))
912 .unwrap(),
913 Fq::new(U256([
914 51787456028377068413742525949644831103,
915 18727496177066613612143648473641354138,
916 ]))
917 .unwrap(),
918 ),
919 y: Fq2::new(
920 Fq::new(U256([
921 105235307093009526756443741536710213857,
922 56697136982397507595538316605420403515,
923 ]))
924 .unwrap(),
925 Fq::new(U256([
926 329285813328264858787093963282305459902,
927 40620233227497131789363095249389429612,
928 ]))
929 .unwrap(),
930 ),
931 },
932 coeffs: Vec::from([
933 EllCoeffs {
934 ell_0: Fq2::new(
935 Fq::new(U256([
936 145915152615018094207274265949237364577,
937 7720188347992263845704223037750674843,
938 ]))
939 .unwrap(),
940 Fq::new(U256([
941 1642602221754736777334297091439332137,
942 43455737427254701713230610624368790806,
943 ]))
944 .unwrap(),
945 ),
946 ell_vw: Fq2::new(
947 Fq::new(U256([
948 192300176042178641247789718482757908684,
949 15253255261571338892647481759611271748,
950 ]))
951 .unwrap(),
952 Fq::new(U256([
953 84481530492606440649863882423335628050,
954 47407062771372090504997924471673219553,
955 ]))
956 .unwrap(),
957 ),
958 ell_vv: Fq2::new(
959 Fq::new(U256([
960 232941999867492381013751617901190279960,
961 33161335727531633874118709394498248694,
962 ]))
963 .unwrap(),
964 Fq::new(U256([
965 205159091107726234051689046255658875895,
966 18784742195738106358087607099254122817,
967 ]))
968 .unwrap(),
969 ),
970 },
971 EllCoeffs {
972 ell_0: Fq2::new(
973 Fq::new(U256([
974 44903717410722925336080339155272113598,
975 2432148164440313442445265360131108750,
976 ]))
977 .unwrap(),
978 Fq::new(U256([
979 115058944839679151514931430187558137193,
980 19913547532675326995005163334665928687,
981 ]))
982 .unwrap(),
983 ),
984 ell_vw: Fq2::new(
985 Fq::new(U256([
986 162225342243516818284353803749727397649,
987 2902812998987289816105769597190405892,
988 ]))
989 .unwrap(),
990 Fq::new(U256([
991 280882305470180330735174149091034017688,
992 45000755139204939118391532933575113126,
993 ]))
994 .unwrap(),
995 ),
996 ell_vv: Fq2::new(
997 Fq::new(U256([
998 81439170073299243743458979294198176188,
999 8269567577349210062003854855333109246,
1000 ]))
1001 .unwrap(),
1002 Fq::new(U256([
1003 229588642195598894684486216729209468602,
1004 50120631775179825949138513731773141671,
1005 ]))
1006 .unwrap(),
1007 ),
1008 },
1009 EllCoeffs {
1010 ell_0: Fq2::new(
1011 Fq::new(U256([
1012 62571086408084349816772432183764211635,
1013 50233214695378430835319156584725532968,
1014 ]))
1015 .unwrap(),
1016 Fq::new(U256([
1017 187531012616569709709565459550531626708,
1018 25399966597901061874032352675540749982,
1019 ]))
1020 .unwrap(),
1021 ),
1022 ell_vw: Fq2::new(
1023 Fq::new(U256([
1024 125202410210363842487043120679844927964,
1025 32132029049461004568346717732357115368,
1026 ]))
1027 .unwrap(),
1028 Fq::new(U256([
1029 40047990517661970904320150752358301419,
1030 29547330482153702904408059941549019061,
1031 ]))
1032 .unwrap(),
1033 ),
1034 ell_vv: Fq2::new(
1035 Fq::new(U256([
1036 72725441636162608820485881978479394755,
1037 4335829118654814821890758647864621059,
1038 ]))
1039 .unwrap(),
1040 Fq::new(U256([
1041 3808530996119731737716737121624391430,
1042 14840119309897919310042357130477699760,
1043 ]))
1044 .unwrap(),
1045 ),
1046 },
1047 EllCoeffs {
1048 ell_0: Fq2::new(
1049 Fq::new(U256([
1050 230923838046707456761202857863657685779,
1051 30663581424308030115949734185266015957,
1052 ]))
1053 .unwrap(),
1054 Fq::new(U256([
1055 75804784823545649980980649059385057066,
1056 40783805432413650791639865054248573254,
1057 ]))
1058 .unwrap(),
1059 ),
1060 ell_vw: Fq2::new(
1061 Fq::new(U256([
1062 220403174695454806701510356109644664970,
1063 61694366506643321007589345694791625235,
1064 ]))
1065 .unwrap(),
1066 Fq::new(U256([
1067 111050616308506297168851165107648527276,
1068 29953858315513175963460036136567176100,
1069 ]))
1070 .unwrap(),
1071 ),
1072 ell_vv: Fq2::new(
1073 Fq::new(U256([
1074 339360714692284035291265180647668192278,
1075 51066683198194726198561068977822786062,
1076 ]))
1077 .unwrap(),
1078 Fq::new(U256([
1079 20532264324124291215869821260466642056,
1080 53772344434441015474139364759811842825,
1081 ]))
1082 .unwrap(),
1083 ),
1084 },
1085 EllCoeffs {
1086 ell_0: Fq2::new(
1087 Fq::new(U256([
1088 53390632401876602131528763251836289052,
1089 7039696239984002955384050250007606842,
1090 ]))
1091 .unwrap(),
1092 Fq::new(U256([
1093 120756148133186395786471763371515340851,
1094 62560956052144901655506280432592733452,
1095 ]))
1096 .unwrap(),
1097 ),
1098 ell_vw: Fq2::new(
1099 Fq::new(U256([
1100 308576049186755490218939550330371718607,
1101 60158766280438165965298754059752443327,
1102 ]))
1103 .unwrap(),
1104 Fq::new(U256([
1105 36519660971413271753359371158311247925,
1106 33166369001790145692925310192829466902,
1107 ]))
1108 .unwrap(),
1109 ),
1110 ell_vv: Fq2::new(
1111 Fq::new(U256([
1112 178902296336418821251231963767960641976,
1113 54039139529656231144797458475123200306,
1114 ]))
1115 .unwrap(),
1116 Fq::new(U256([
1117 327709063289359470903820254941214044104,
1118 29921523827667065809753199129798632038,
1119 ]))
1120 .unwrap(),
1121 ),
1122 },
1123 EllCoeffs {
1124 ell_0: Fq2::new(
1125 Fq::new(U256([
1126 293947345738284310028696202770439717312,
1127 23629199470233866978708839571836323911,
1128 ]))
1129 .unwrap(),
1130 Fq::new(U256([
1131 270255405451020462647135094276398320650,
1132 10214498461032217021941670870340839535,
1133 ]))
1134 .unwrap(),
1135 ),
1136 ell_vw: Fq2::new(
1137 Fq::new(U256([
1138 159737597162744224577379609113239040296,
1139 42414292048147664393527940182644080820,
1140 ]))
1141 .unwrap(),
1142 Fq::new(U256([
1143 319166235401593060755720596880844332847,
1144 23942967675619615172318074973192451617,
1145 ]))
1146 .unwrap(),
1147 ),
1148 ell_vv: Fq2::new(
1149 Fq::new(U256([
1150 322582854267025287594765649802803266076,
1151 43815838906866149475744535388480851056,
1152 ]))
1153 .unwrap(),
1154 Fq::new(U256([
1155 194731262617323725381582694441938082298,
1156 6318043913263416116808511289860376787,
1157 ]))
1158 .unwrap(),
1159 ),
1160 },
1161 EllCoeffs {
1162 ell_0: Fq2::new(
1163 Fq::new(U256([
1164 340258202167813930211448229264749672038,
1165 49309561646299510355653200516855272117,
1166 ]))
1167 .unwrap(),
1168 Fq::new(U256([
1169 314009511129121341897071879080163927420,
1170 46733418159091100849346822998375177924,
1171 ]))
1172 .unwrap(),
1173 ),
1174 ell_vw: Fq2::new(
1175 Fq::new(U256([
1176 296127326349185873181435771941022502705,
1177 27092339993712929447599322475752229815,
1178 ]))
1179 .unwrap(),
1180 Fq::new(U256([
1181 14090774041595571810302865485069892149,
1182 9416959189726308679959984066033622764,
1183 ]))
1184 .unwrap(),
1185 ),
1186 ell_vv: Fq2::new(
1187 Fq::new(U256([
1188 331192186309261416893996962356905314610,
1189 6133490180262551399580874298514378708,
1190 ]))
1191 .unwrap(),
1192 Fq::new(U256([
1193 52146008553438513232574426823996261862,
1194 51692389190081578424424830745703412620,
1195 ]))
1196 .unwrap(),
1197 ),
1198 },
1199 EllCoeffs {
1200 ell_0: Fq2::new(
1201 Fq::new(U256([
1202 304886724958645105936240400377782311329,
1203 24452949520921718326419149662293231897,
1204 ]))
1205 .unwrap(),
1206 Fq::new(U256([
1207 191644523888771552477578834463319391872,
1208 21762407072532056308389337796258587948,
1209 ]))
1210 .unwrap(),
1211 ),
1212 ell_vw: Fq2::new(
1213 Fq::new(U256([
1214 131875657381595539531276734057336373872,
1215 46145756403556903236477737806904884925,
1216 ]))
1217 .unwrap(),
1218 Fq::new(U256([
1219 15513558811446045405402043661936649706,
1220 6164660913794769127674854991137805768,
1221 ]))
1222 .unwrap(),
1223 ),
1224 ell_vv: Fq2::new(
1225 Fq::new(U256([
1226 37628908878688989915703006228108158588,
1227 32333568458099455743134394992114761192,
1228 ]))
1229 .unwrap(),
1230 Fq::new(U256([
1231 310028653933656868572053471966984499925,
1232 50927285178735796712220443510555951806,
1233 ]))
1234 .unwrap(),
1235 ),
1236 },
1237 EllCoeffs {
1238 ell_0: Fq2::new(
1239 Fq::new(U256([
1240 323579290279633699483736616036574636320,
1241 26462458255852549637810201830373030787,
1242 ]))
1243 .unwrap(),
1244 Fq::new(U256([
1245 212356178148004645362110693008071812466,
1246 7147771462841335914859391157142419270,
1247 ]))
1248 .unwrap(),
1249 ),
1250 ell_vw: Fq2::new(
1251 Fq::new(U256([
1252 33793486114682505251748396905247663179,
1253 12971208030293312519168903516345112146,
1254 ]))
1255 .unwrap(),
1256 Fq::new(U256([
1257 105470215179403498779276452125929471612,
1258 13243999928262666388833873861601164323,
1259 ]))
1260 .unwrap(),
1261 ),
1262 ell_vv: Fq2::new(
1263 Fq::new(U256([
1264 336774965397927402479055329499391144750,
1265 14092422716202439890370586466555281245,
1266 ]))
1267 .unwrap(),
1268 Fq::new(U256([
1269 128524990965480598411024491536330888971,
1270 16339349487558512101009117692791080358,
1271 ]))
1272 .unwrap(),
1273 ),
1274 },
1275 EllCoeffs {
1276 ell_0: Fq2::new(
1277 Fq::new(U256([
1278 308807709363499650659552856561459119304,
1279 20549512613498060437905021698882254003,
1280 ]))
1281 .unwrap(),
1282 Fq::new(U256([
1283 296831825878801592442122280385770051837,
1284 12999356604250035352468537408632919011,
1285 ]))
1286 .unwrap(),
1287 ),
1288 ell_vw: Fq2::new(
1289 Fq::new(U256([
1290 6416952549311962005690662486801715420,
1291 6562024922514861810686738146979657369,
1292 ]))
1293 .unwrap(),
1294 Fq::new(U256([
1295 208034701293282569885312328681897330015,
1296 32565296199581814532888690261728578093,
1297 ]))
1298 .unwrap(),
1299 ),
1300 ell_vv: Fq2::new(
1301 Fq::new(U256([
1302 158821090683358871468006667057662171383,
1303 43639936137708212270934870661514052516,
1304 ]))
1305 .unwrap(),
1306 Fq::new(U256([
1307 273462267971100585683746592136866263017,
1308 33686004986452254374790215788772597950,
1309 ]))
1310 .unwrap(),
1311 ),
1312 },
1313 EllCoeffs {
1314 ell_0: Fq2::new(
1315 Fq::new(U256([
1316 239050458738191424179259026508283200850,
1317 59033062634877072212375745660456082761,
1318 ]))
1319 .unwrap(),
1320 Fq::new(U256([
1321 42735232027681689333255156554135804585,
1322 3645324355274008091830665999900460711,
1323 ]))
1324 .unwrap(),
1325 ),
1326 ell_vw: Fq2::new(
1327 Fq::new(U256([
1328 108736755942765297679539162065532976047,
1329 53005795603772553534072950762621113576,
1330 ]))
1331 .unwrap(),
1332 Fq::new(U256([
1333 161143215360647768117453097687908448132,
1334 47995551574176504820342605188594172079,
1335 ]))
1336 .unwrap(),
1337 ),
1338 ell_vv: Fq2::new(
1339 Fq::new(U256([
1340 6657347986892301669776633258074701543,
1341 11902481233202623619409687758723915636,
1342 ]))
1343 .unwrap(),
1344 Fq::new(U256([
1345 222956595276083444090603007056080975801,
1346 36382879863546362219365726153085767156,
1347 ]))
1348 .unwrap(),
1349 ),
1350 },
1351 EllCoeffs {
1352 ell_0: Fq2::new(
1353 Fq::new(U256([
1354 313682093040115002688525404999246872446,
1355 42956501626298358982264420981703353471,
1356 ]))
1357 .unwrap(),
1358 Fq::new(U256([
1359 16910327688907897736932577003378075753,
1360 1359671211117678708781834746493106650,
1361 ]))
1362 .unwrap(),
1363 ),
1364 ell_vw: Fq2::new(
1365 Fq::new(U256([
1366 6643221945930263241861939865579251413,
1367 53936065521860576156419486432192485437,
1368 ]))
1369 .unwrap(),
1370 Fq::new(U256([
1371 309056291241266457640134736864478816427,
1372 37247957207987268075661977484645707642,
1373 ]))
1374 .unwrap(),
1375 ),
1376 ell_vv: Fq2::new(
1377 Fq::new(U256([
1378 222157301260856896664619946160442713805,
1379 49516872999212369072183141842522894943,
1380 ]))
1381 .unwrap(),
1382 Fq::new(U256([
1383 205513791444704603844975928062124661076,
1384 57468270224470125473802906477068197830,
1385 ]))
1386 .unwrap(),
1387 ),
1388 },
1389 EllCoeffs {
1390 ell_0: Fq2::new(
1391 Fq::new(U256([
1392 8285963000933560101573593109316673578,
1393 14786122523410515396563958444109027710,
1394 ]))
1395 .unwrap(),
1396 Fq::new(U256([
1397 122158657553570962061566147876423950513,
1398 52139940048286310424786112221915773798,
1399 ]))
1400 .unwrap(),
1401 ),
1402 ell_vw: Fq2::new(
1403 Fq::new(U256([
1404 334881138980927901869290199603379387015,
1405 25426740963889929124688873103192284934,
1406 ]))
1407 .unwrap(),
1408 Fq::new(U256([
1409 15041987314727689102877759056668987416,
1410 53279076961030137249765180937167164331,
1411 ]))
1412 .unwrap(),
1413 ),
1414 ell_vv: Fq2::new(
1415 Fq::new(U256([
1416 219851721339103004718273461131600868626,
1417 36871882814964809764289908414024625695,
1418 ]))
1419 .unwrap(),
1420 Fq::new(U256([
1421 131269942067631553063094618567097759738,
1422 53556533347945713183394135477679452243,
1423 ]))
1424 .unwrap(),
1425 ),
1426 },
1427 EllCoeffs {
1428 ell_0: Fq2::new(
1429 Fq::new(U256([
1430 303322002694907044040904386256578801369,
1431 47818402373691165133570276489205539247,
1432 ]))
1433 .unwrap(),
1434 Fq::new(U256([
1435 23840328058016663665484464556433078317,
1436 57137757685631244994429644684135564308,
1437 ]))
1438 .unwrap(),
1439 ),
1440 ell_vw: Fq2::new(
1441 Fq::new(U256([
1442 313347268925459844355339673983448992252,
1443 63059125438530014597733264556246943889,
1444 ]))
1445 .unwrap(),
1446 Fq::new(U256([
1447 332951624867081114956044501931839262097,
1448 21446965953220512177611603903918604526,
1449 ]))
1450 .unwrap(),
1451 ),
1452 ell_vv: Fq2::new(
1453 Fq::new(U256([
1454 43308962429154740283739513584277671586,
1455 36726788540078024416606994278261486896,
1456 ]))
1457 .unwrap(),
1458 Fq::new(U256([
1459 201462004284693135670392448782496773481,
1460 37361169637624833127302583281977615660,
1461 ]))
1462 .unwrap(),
1463 ),
1464 },
1465 EllCoeffs {
1466 ell_0: Fq2::new(
1467 Fq::new(U256([
1468 23765318454509223469921591210222962901,
1469 44990033695398054388153021046567582164,
1470 ]))
1471 .unwrap(),
1472 Fq::new(U256([
1473 31305053791054889490552967007711680166,
1474 27103171064041391806294729422128985527,
1475 ]))
1476 .unwrap(),
1477 ),
1478 ell_vw: Fq2::new(
1479 Fq::new(U256([
1480 276126480562835962332188871122724756846,
1481 16736136826306680287985573076016202896,
1482 ]))
1483 .unwrap(),
1484 Fq::new(U256([
1485 4414319697794720805306194236550991584,
1486 62019193108561650400059767099940339027,
1487 ]))
1488 .unwrap(),
1489 ),
1490 ell_vv: Fq2::new(
1491 Fq::new(U256([
1492 264396677944255651896935058261233808058,
1493 56759185289081036894005736531633938393,
1494 ]))
1495 .unwrap(),
1496 Fq::new(U256([
1497 203628704629834831927134686796555271069,
1498 48471469187143841926703236705753907861,
1499 ]))
1500 .unwrap(),
1501 ),
1502 },
1503 EllCoeffs {
1504 ell_0: Fq2::new(
1505 Fq::new(U256([
1506 239115594351165984647685996782641428320,
1507 44545149465284571473177119694335581490,
1508 ]))
1509 .unwrap(),
1510 Fq::new(U256([
1511 213078788930221853484251159402089402698,
1512 16763897914971151155224113448725254022,
1513 ]))
1514 .unwrap(),
1515 ),
1516 ell_vw: Fq2::new(
1517 Fq::new(U256([
1518 114008097138551618719252989046711208100,
1519 59881147407771812558336453348641148192,
1520 ]))
1521 .unwrap(),
1522 Fq::new(U256([
1523 73126778233281675579715222201222232223,
1524 38826300453213723195010574430400377747,
1525 ]))
1526 .unwrap(),
1527 ),
1528 ell_vv: Fq2::new(
1529 Fq::new(U256([
1530 241042448915505783580706972981273226980,
1531 56417003146210087305012985177072964806,
1532 ]))
1533 .unwrap(),
1534 Fq::new(U256([
1535 169177487653248888684114813249577243086,
1536 32380354283087538368804702239086564787,
1537 ]))
1538 .unwrap(),
1539 ),
1540 },
1541 EllCoeffs {
1542 ell_0: Fq2::new(
1543 Fq::new(U256([
1544 158019800920508883600584012748066500495,
1545 26898142140797843980908437809386681141,
1546 ]))
1547 .unwrap(),
1548 Fq::new(U256([
1549 306502797874464726523541130582372927512,
1550 24906313146242057911294566839234262300,
1551 ]))
1552 .unwrap(),
1553 ),
1554 ell_vw: Fq2::new(
1555 Fq::new(U256([
1556 285760763932996537001129740504018931266,
1557 61805280449958461312688755177468072593,
1558 ]))
1559 .unwrap(),
1560 Fq::new(U256([
1561 135545131264687967800977791145788692523,
1562 58139772512775079850670752006123037712,
1563 ]))
1564 .unwrap(),
1565 ),
1566 ell_vv: Fq2::new(
1567 Fq::new(U256([
1568 70329035009259499088740735594160571447,
1569 39714506367478198523957872987679138518,
1570 ]))
1571 .unwrap(),
1572 Fq::new(U256([
1573 140879819390078281356249388675648473246,
1574 43854973736398482797037510623636581696,
1575 ]))
1576 .unwrap(),
1577 ),
1578 },
1579 EllCoeffs {
1580 ell_0: Fq2::new(
1581 Fq::new(U256([
1582 38618198701391964654224360704900902096,
1583 38909748519501972274789640400408937483,
1584 ]))
1585 .unwrap(),
1586 Fq::new(U256([
1587 180923031305898977193921630254659948144,
1588 27460338595509200370239569387614912648,
1589 ]))
1590 .unwrap(),
1591 ),
1592 ell_vw: Fq2::new(
1593 Fq::new(U256([
1594 70057505024221161194312385639309591716,
1595 18962666975131076741596858262806841593,
1596 ]))
1597 .unwrap(),
1598 Fq::new(U256([
1599 214987899942827030987983709303642547609,
1600 7354730872853772995022889424236171557,
1601 ]))
1602 .unwrap(),
1603 ),
1604 ell_vv: Fq2::new(
1605 Fq::new(U256([
1606 915509610432328048899540473086774484,
1607 34629556430715177067961193484853677166,
1608 ]))
1609 .unwrap(),
1610 Fq::new(U256([
1611 210548802885276746342162088554780886285,
1612 59946451357630926783981469963615555141,
1613 ]))
1614 .unwrap(),
1615 ),
1616 },
1617 EllCoeffs {
1618 ell_0: Fq2::new(
1619 Fq::new(U256([
1620 192587880731165909190755427373555634019,
1621 10976459312692912490911357520717353871,
1622 ]))
1623 .unwrap(),
1624 Fq::new(U256([
1625 167196051583193420579377374296283755878,
1626 49401460467894024879692901111127305932,
1627 ]))
1628 .unwrap(),
1629 ),
1630 ell_vw: Fq2::new(
1631 Fq::new(U256([
1632 280565789968090605174946518022513606221,
1633 37294483328987043033011583201807512274,
1634 ]))
1635 .unwrap(),
1636 Fq::new(U256([
1637 43162969061744994465193287354736460751,
1638 22121767444104992380234797550707180209,
1639 ]))
1640 .unwrap(),
1641 ),
1642 ell_vv: Fq2::new(
1643 Fq::new(U256([
1644 253802905125777094707425424576407998829,
1645 61686094369188045360896737944218403088,
1646 ]))
1647 .unwrap(),
1648 Fq::new(U256([
1649 182974256593102716284343824242596548794,
1650 7848028085342627691056691434137748535,
1651 ]))
1652 .unwrap(),
1653 ),
1654 },
1655 EllCoeffs {
1656 ell_0: Fq2::new(
1657 Fq::new(U256([
1658 84344031984214336466355469526466525167,
1659 27093607600401090432285884248864703045,
1660 ]))
1661 .unwrap(),
1662 Fq::new(U256([
1663 149328956099164822232925589118520984554,
1664 2238105695079930209978670615986667957,
1665 ]))
1666 .unwrap(),
1667 ),
1668 ell_vw: Fq2::new(
1669 Fq::new(U256([
1670 164524345257317963111443719298495629688,
1671 60976929030698527695079882388987310770,
1672 ]))
1673 .unwrap(),
1674 Fq::new(U256([
1675 306918226890341242065585311833805224781,
1676 55722896155980110701397483880645840750,
1677 ]))
1678 .unwrap(),
1679 ),
1680 ell_vv: Fq2::new(
1681 Fq::new(U256([
1682 93128913154066328529254602049518310767,
1683 33148637643432199376041913783211199036,
1684 ]))
1685 .unwrap(),
1686 Fq::new(U256([
1687 232426184416524951250597496934702636450,
1688 43720696322889678655980069182616949616,
1689 ]))
1690 .unwrap(),
1691 ),
1692 },
1693 EllCoeffs {
1694 ell_0: Fq2::new(
1695 Fq::new(U256([
1696 102654491688396809766739755399745558766,
1697 38605113922396003219627575078289843591,
1698 ]))
1699 .unwrap(),
1700 Fq::new(U256([
1701 19593962899181063954599229676070513364,
1702 60350965404501231355169027639339453296,
1703 ]))
1704 .unwrap(),
1705 ),
1706 ell_vw: Fq2::new(
1707 Fq::new(U256([
1708 159636507003615123705820979675398042179,
1709 54313579941440479276773225578829814974,
1710 ]))
1711 .unwrap(),
1712 Fq::new(U256([
1713 119356164563490256235392395335237959869,
1714 39953340372362730589797197026608570557,
1715 ]))
1716 .unwrap(),
1717 ),
1718 ell_vv: Fq2::new(
1719 Fq::new(U256([
1720 63485981942258213001157530320762394972,
1721 31200716913018312733656963741875248687,
1722 ]))
1723 .unwrap(),
1724 Fq::new(U256([
1725 12902614517986449375080893856817237357,
1726 18985985729109591831690040180758616083,
1727 ]))
1728 .unwrap(),
1729 ),
1730 },
1731 EllCoeffs {
1732 ell_0: Fq2::new(
1733 Fq::new(U256([
1734 42308655177239821867892255001741444297,
1735 48752963962065714616191625548108808,
1736 ]))
1737 .unwrap(),
1738 Fq::new(U256([
1739 128521931437576558829282023068349026555,
1740 41085812991756679343188097975462933419,
1741 ]))
1742 .unwrap(),
1743 ),
1744 ell_vw: Fq2::new(
1745 Fq::new(U256([
1746 10035402786640614748259945360125292132,
1747 38557266307605033249489727552659930268,
1748 ]))
1749 .unwrap(),
1750 Fq::new(U256([
1751 261287166540169381393014929830322479654,
1752 42514049292646924562828996896910004962,
1753 ]))
1754 .unwrap(),
1755 ),
1756 ell_vv: Fq2::new(
1757 Fq::new(U256([
1758 56319885731071444245573249522306017699,
1759 53577564523791470572591472840806985932,
1760 ]))
1761 .unwrap(),
1762 Fq::new(U256([
1763 124520094647080351085028512262335797477,
1764 34908241061842840630524194497782012074,
1765 ]))
1766 .unwrap(),
1767 ),
1768 },
1769 EllCoeffs {
1770 ell_0: Fq2::new(
1771 Fq::new(U256([
1772 126634618253919797596379978688751079772,
1773 52145187142657016821034369446677208400,
1774 ]))
1775 .unwrap(),
1776 Fq::new(U256([
1777 331622287147942589908508350657315302543,
1778 33514242158733995981408830992771427380,
1779 ]))
1780 .unwrap(),
1781 ),
1782 ell_vw: Fq2::new(
1783 Fq::new(U256([
1784 120940515437555419164907643421042686361,
1785 17509271053436215565086784812667241751,
1786 ]))
1787 .unwrap(),
1788 Fq::new(U256([
1789 115780741523467210253488502554959480585,
1790 32352495928341192491861819481034439523,
1791 ]))
1792 .unwrap(),
1793 ),
1794 ell_vv: Fq2::new(
1795 Fq::new(U256([
1796 3619315753849520875056567968398971518,
1797 24276420029996570458336249792816120452,
1798 ]))
1799 .unwrap(),
1800 Fq::new(U256([
1801 211494135803191326215038551543926917828,
1802 43184746342435212339590913052197238451,
1803 ]))
1804 .unwrap(),
1805 ),
1806 },
1807 EllCoeffs {
1808 ell_0: Fq2::new(
1809 Fq::new(U256([
1810 299074873552726234274845052736068685064,
1811 17100980781941753342716208137755315141,
1812 ]))
1813 .unwrap(),
1814 Fq::new(U256([
1815 132717845842422445158092928854959930670,
1816 44970515850781790514922204901459656647,
1817 ]))
1818 .unwrap(),
1819 ),
1820 ell_vw: Fq2::new(
1821 Fq::new(U256([
1822 216867730679061124743178802618784487478,
1823 57695717306148677588162001948381364803,
1824 ]))
1825 .unwrap(),
1826 Fq::new(U256([
1827 270218131380365097755408360718075538527,
1828 57477676726794026534017337223493668494,
1829 ]))
1830 .unwrap(),
1831 ),
1832 ell_vv: Fq2::new(
1833 Fq::new(U256([
1834 165279544895097377741304748618110436848,
1835 20425223618131822879513743747480509436,
1836 ]))
1837 .unwrap(),
1838 Fq::new(U256([
1839 74939006713979852471760437945055491248,
1840 13009460391442509409368588074771283312,
1841 ]))
1842 .unwrap(),
1843 ),
1844 },
1845 EllCoeffs {
1846 ell_0: Fq2::new(
1847 Fq::new(U256([
1848 66759827770349370888034213457290956508,
1849 9005955800938032302448930728853089346,
1850 ]))
1851 .unwrap(),
1852 Fq::new(U256([
1853 132741330683696165661450722498530220360,
1854 7366906791443646993778243377846220425,
1855 ]))
1856 .unwrap(),
1857 ),
1858 ell_vw: Fq2::new(
1859 Fq::new(U256([
1860 253540438895289112523278690834655986794,
1861 6116090159416232554407405788526490758,
1862 ]))
1863 .unwrap(),
1864 Fq::new(U256([
1865 30829083910163512740218467627901622426,
1866 55620601051021580444864016142195538972,
1867 ]))
1868 .unwrap(),
1869 ),
1870 ell_vv: Fq2::new(
1871 Fq::new(U256([
1872 250454368142865329167214266233567636554,
1873 62357304312342518984982585510065736692,
1874 ]))
1875 .unwrap(),
1876 Fq::new(U256([
1877 188759902529624961292182168219378957599,
1878 46090313440960353890072197786322881372,
1879 ]))
1880 .unwrap(),
1881 ),
1882 },
1883 EllCoeffs {
1884 ell_0: Fq2::new(
1885 Fq::new(U256([
1886 273524456438634570870477083331972978477,
1887 9134704483036112456254510849911524401,
1888 ]))
1889 .unwrap(),
1890 Fq::new(U256([
1891 67478468272116511526567438494812739067,
1892 25741563822514337717816912706935692500,
1893 ]))
1894 .unwrap(),
1895 ),
1896 ell_vw: Fq2::new(
1897 Fq::new(U256([
1898 116593352960394465976476340555861894686,
1899 41112534697095493718894382902662572752,
1900 ]))
1901 .unwrap(),
1902 Fq::new(U256([
1903 120743240887113383410964567068981375379,
1904 38598788085595749947162720656886407615,
1905 ]))
1906 .unwrap(),
1907 ),
1908 ell_vv: Fq2::new(
1909 Fq::new(U256([
1910 312187803926537773957821532171857044863,
1911 19370576499152094014450666672812249236,
1912 ]))
1913 .unwrap(),
1914 Fq::new(U256([
1915 240827398452930199439299722869808431504,
1916 49509218268486878713361004562421178491,
1917 ]))
1918 .unwrap(),
1919 ),
1920 },
1921 EllCoeffs {
1922 ell_0: Fq2::new(
1923 Fq::new(U256([
1924 290888165778751654611450374067314903262,
1925 37392757737237359968235356696866333927,
1926 ]))
1927 .unwrap(),
1928 Fq::new(U256([
1929 252204440608865557722718990121112495320,
1930 55975286037277175922442767802285953079,
1931 ]))
1932 .unwrap(),
1933 ),
1934 ell_vw: Fq2::new(
1935 Fq::new(U256([
1936 270039432299546232993592658461203399951,
1937 60656209400809596126720306545905143183,
1938 ]))
1939 .unwrap(),
1940 Fq::new(U256([
1941 285724268091089729569589544862374658568,
1942 31963711474983717334851248248346512047,
1943 ]))
1944 .unwrap(),
1945 ),
1946 ell_vv: Fq2::new(
1947 Fq::new(U256([
1948 3884505529011790540935411500477268151,
1949 13223063167340752683657032423528371760,
1950 ]))
1951 .unwrap(),
1952 Fq::new(U256([
1953 159305752483642939978115090933392332739,
1954 7151624608160356980135319367119889070,
1955 ]))
1956 .unwrap(),
1957 ),
1958 },
1959 EllCoeffs {
1960 ell_0: Fq2::new(
1961 Fq::new(U256([
1962 272676514700352082082833454466828720931,
1963 25063412692149354657238579769317314943,
1964 ]))
1965 .unwrap(),
1966 Fq::new(U256([
1967 293621566718932528694833049559922653569,
1968 45585304922174719737960365050252747127,
1969 ]))
1970 .unwrap(),
1971 ),
1972 ell_vw: Fq2::new(
1973 Fq::new(U256([
1974 54835393883782456964222308618682542993,
1975 37980634195943561261187934261099825702,
1976 ]))
1977 .unwrap(),
1978 Fq::new(U256([
1979 59974402342646963556531661011524247325,
1980 35696051147487701670582425632191066303,
1981 ]))
1982 .unwrap(),
1983 ),
1984 ell_vv: Fq2::new(
1985 Fq::new(U256([
1986 259456005420154607862207518414346338959,
1987 26130920677564288823895676956971235383,
1988 ]))
1989 .unwrap(),
1990 Fq::new(U256([
1991 116130095060524137327607346021153250193,
1992 10807286360635090367088053443993301396,
1993 ]))
1994 .unwrap(),
1995 ),
1996 },
1997 EllCoeffs {
1998 ell_0: Fq2::new(
1999 Fq::new(U256([
2000 49392952615759746255132704409838115781,
2001 47072336582571607445080612120532993304,
2002 ]))
2003 .unwrap(),
2004 Fq::new(U256([
2005 176567394438796320529775330793638953568,
2006 28322815468520297894419530294472748019,
2007 ]))
2008 .unwrap(),
2009 ),
2010 ell_vw: Fq2::new(
2011 Fq::new(U256([
2012 80922979608932498062547214350892680237,
2013 39454405473363814575369344229244849847,
2014 ]))
2015 .unwrap(),
2016 Fq::new(U256([
2017 91401220192762005776280059066692026476,
2018 15657465297119889794043496656394015039,
2019 ]))
2020 .unwrap(),
2021 ),
2022 ell_vv: Fq2::new(
2023 Fq::new(U256([
2024 66039352326985904039959490473173702089,
2025 53019684969492620390541557616482571566,
2026 ]))
2027 .unwrap(),
2028 Fq::new(U256([
2029 241714503488139707849386627025007386925,
2030 26075944201145781355709956722513636060,
2031 ]))
2032 .unwrap(),
2033 ),
2034 },
2035 EllCoeffs {
2036 ell_0: Fq2::new(
2037 Fq::new(U256([
2038 282595284318374809009793390206732488298,
2039 45748314157085313197379566607025256839,
2040 ]))
2041 .unwrap(),
2042 Fq::new(U256([
2043 270827203295353120306891953779231995484,
2044 2061164657869992110070755346638481586,
2045 ]))
2046 .unwrap(),
2047 ),
2048 ell_vw: Fq2::new(
2049 Fq::new(U256([
2050 122772591180024083766405253289036218458,
2051 22573428243213343555967649475581629995,
2052 ]))
2053 .unwrap(),
2054 Fq::new(U256([
2055 335389040951271989935196787085438096490,
2056 19801736168278388699669751501679386348,
2057 ]))
2058 .unwrap(),
2059 ),
2060 ell_vv: Fq2::new(
2061 Fq::new(U256([
2062 339013185026928567100232707644090060309,
2063 19772463825247091662201186215246641510,
2064 ]))
2065 .unwrap(),
2066 Fq::new(U256([
2067 4804384610649622501550615795150497154,
2068 23912076036945346828195974346279787457,
2069 ]))
2070 .unwrap(),
2071 ),
2072 },
2073 EllCoeffs {
2074 ell_0: Fq2::new(
2075 Fq::new(U256([
2076 214353258010296277687883233632193811097,
2077 5219474783704014986415232032947372339,
2078 ]))
2079 .unwrap(),
2080 Fq::new(U256([
2081 79624479932762034850342328421303227111,
2082 56787485322265889115274972394242117773,
2083 ]))
2084 .unwrap(),
2085 ),
2086 ell_vw: Fq2::new(
2087 Fq::new(U256([
2088 184200025840089548499823017798379240877,
2089 48381517011877532244879858559402925202,
2090 ]))
2091 .unwrap(),
2092 Fq::new(U256([
2093 107565933978602112957892502247036378430,
2094 45988606090744912079186414974711188065,
2095 ]))
2096 .unwrap(),
2097 ),
2098 ell_vv: Fq2::new(
2099 Fq::new(U256([
2100 110593764674444376346243358175616189408,
2101 35712801833060284055338218769830573236,
2102 ]))
2103 .unwrap(),
2104 Fq::new(U256([
2105 151909254176585476474604484796159407774,
2106 47158276852552318249500199498589330637,
2107 ]))
2108 .unwrap(),
2109 ),
2110 },
2111 EllCoeffs {
2112 ell_0: Fq2::new(
2113 Fq::new(U256([
2114 322742519015404082194067614300530448854,
2115 59892171075434557254836830922854923608,
2116 ]))
2117 .unwrap(),
2118 Fq::new(U256([
2119 32065386578298932256366582168915019527,
2120 26752577181504287044232901657950904669,
2121 ]))
2122 .unwrap(),
2123 ),
2124 ell_vw: Fq2::new(
2125 Fq::new(U256([
2126 174803672897784440584915958306641383601,
2127 41091446500573741637560530719439634516,
2128 ]))
2129 .unwrap(),
2130 Fq::new(U256([
2131 209867082646016733058415245870200692364,
2132 62329211607238784395268250532556435532,
2133 ]))
2134 .unwrap(),
2135 ),
2136 ell_vv: Fq2::new(
2137 Fq::new(U256([
2138 306258598889945544178464082933019504953,
2139 54721033386841216374878966418312958051,
2140 ]))
2141 .unwrap(),
2142 Fq::new(U256([
2143 60603024880089835430212078876452798438,
2144 46149383487322374768616169869877411190,
2145 ]))
2146 .unwrap(),
2147 ),
2148 },
2149 EllCoeffs {
2150 ell_0: Fq2::new(
2151 Fq::new(U256([
2152 217026022228859342220342856144348485905,
2153 57413523264998851221438276699831981764,
2154 ]))
2155 .unwrap(),
2156 Fq::new(U256([
2157 124187198815039194427087238512103681551,
2158 5443344443330946400667796667492661757,
2159 ]))
2160 .unwrap(),
2161 ),
2162 ell_vw: Fq2::new(
2163 Fq::new(U256([
2164 329826946228202959132718054863501702187,
2165 48520872455619090037740041830322500851,
2166 ]))
2167 .unwrap(),
2168 Fq::new(U256([
2169 84830400552123989859098307569998867522,
2170 48734171266537512281517863759978814030,
2171 ]))
2172 .unwrap(),
2173 ),
2174 ell_vv: Fq2::new(
2175 Fq::new(U256([
2176 223121539165880683751973996773385673012,
2177 25883364325220384256766392563193579368,
2178 ]))
2179 .unwrap(),
2180 Fq::new(U256([
2181 299825902106679285294937343573961127742,
2182 60789713632874624396137039249203910802,
2183 ]))
2184 .unwrap(),
2185 ),
2186 },
2187 EllCoeffs {
2188 ell_0: Fq2::new(
2189 Fq::new(U256([
2190 256516074149138488025765885988857744378,
2191 14065986710590565469822003697004376208,
2192 ]))
2193 .unwrap(),
2194 Fq::new(U256([
2195 234079806620020815932181140203001517322,
2196 23367862088314049165195572485764983176,
2197 ]))
2198 .unwrap(),
2199 ),
2200 ell_vw: Fq2::new(
2201 Fq::new(U256([
2202 196437028129330799836797952742061629213,
2203 48672430434915053819319219832418834574,
2204 ]))
2205 .unwrap(),
2206 Fq::new(U256([
2207 325437437809364731749456582922626432887,
2208 48166506837989600793252437510600468487,
2209 ]))
2210 .unwrap(),
2211 ),
2212 ell_vv: Fq2::new(
2213 Fq::new(U256([
2214 159308630334191903727834955555702331135,
2215 62436879262294424125843661083177310796,
2216 ]))
2217 .unwrap(),
2218 Fq::new(U256([
2219 36766573815532717355926225449599862176,
2220 45422312033048180700369981630678147962,
2221 ]))
2222 .unwrap(),
2223 ),
2224 },
2225 EllCoeffs {
2226 ell_0: Fq2::new(
2227 Fq::new(U256([
2228 242582781609674647644149440448686667005,
2229 38749506523024653240132899426202698768,
2230 ]))
2231 .unwrap(),
2232 Fq::new(U256([
2233 175781266358339061379292613713370680613,
2234 18670420110220807116103915283744134837,
2235 ]))
2236 .unwrap(),
2237 ),
2238 ell_vw: Fq2::new(
2239 Fq::new(U256([
2240 330308428247032904787707230285980997411,
2241 57858504610626027326513601505745660271,
2242 ]))
2243 .unwrap(),
2244 Fq::new(U256([
2245 137930876960001856905683673437505764610,
2246 51655613850377410017968900339454298922,
2247 ]))
2248 .unwrap(),
2249 ),
2250 ell_vv: Fq2::new(
2251 Fq::new(U256([
2252 313120701922067853802383887994976410392,
2253 45975781155280265622735990880466050470,
2254 ]))
2255 .unwrap(),
2256 Fq::new(U256([
2257 335042362116388769047290965043326509112,
2258 60559196975175152299532260702584038813,
2259 ]))
2260 .unwrap(),
2261 ),
2262 },
2263 EllCoeffs {
2264 ell_0: Fq2::new(
2265 Fq::new(U256([
2266 168129439507943874458360855948848921748,
2267 49297302702020077848733359456178701712,
2268 ]))
2269 .unwrap(),
2270 Fq::new(U256([
2271 269089028431861389215030548077466532939,
2272 39860705713699087717989916919780377864,
2273 ]))
2274 .unwrap(),
2275 ),
2276 ell_vw: Fq2::new(
2277 Fq::new(U256([
2278 13752419440807207645064267622022228455,
2279 58622973202646179187733854793315255353,
2280 ]))
2281 .unwrap(),
2282 Fq::new(U256([
2283 214305013520593573583121266790878302778,
2284 38633624705329558986475404541639527124,
2285 ]))
2286 .unwrap(),
2287 ),
2288 ell_vv: Fq2::new(
2289 Fq::new(U256([
2290 149534517263071862076005511513725705381,
2291 33923419970735724678578488530397069094,
2292 ]))
2293 .unwrap(),
2294 Fq::new(U256([
2295 52240222008682291290000393139971676649,
2296 13553337484321113195355299279586301175,
2297 ]))
2298 .unwrap(),
2299 ),
2300 },
2301 EllCoeffs {
2302 ell_0: Fq2::new(
2303 Fq::new(U256([
2304 272900340425393991345320871434898164480,
2305 38006376657960211098766747755417992280,
2306 ]))
2307 .unwrap(),
2308 Fq::new(U256([
2309 261987172512287267237176115671442326513,
2310 8128050373266945066047548013741537435,
2311 ]))
2312 .unwrap(),
2313 ),
2314 ell_vw: Fq2::new(
2315 Fq::new(U256([
2316 262663552198367871113333688806502970707,
2317 16999213382693802141971886256404278345,
2318 ]))
2319 .unwrap(),
2320 Fq::new(U256([
2321 82246501115823748400993076962512494264,
2322 9513280785331020628797944368204762745,
2323 ]))
2324 .unwrap(),
2325 ),
2326 ell_vv: Fq2::new(
2327 Fq::new(U256([
2328 68225301292307439157467124956340428751,
2329 23984526331358356113154550150873972672,
2330 ]))
2331 .unwrap(),
2332 Fq::new(U256([
2333 322267803776402446716363035932937663522,
2334 7643551605057856674267205902314118400,
2335 ]))
2336 .unwrap(),
2337 ),
2338 },
2339 EllCoeffs {
2340 ell_0: Fq2::new(
2341 Fq::new(U256([
2342 226851502497426762485425012577563658166,
2343 33899046058167810318161894461593654070,
2344 ]))
2345 .unwrap(),
2346 Fq::new(U256([
2347 106137231667287271021611800141669940221,
2348 38201180579053106362613109983520968531,
2349 ]))
2350 .unwrap(),
2351 ),
2352 ell_vw: Fq2::new(
2353 Fq::new(U256([
2354 75276265667487657641526123222570637963,
2355 18790008468742777802887427569490235644,
2356 ]))
2357 .unwrap(),
2358 Fq::new(U256([
2359 236348579709234796216705203173042603149,
2360 51488118889105930334369568118204095717,
2361 ]))
2362 .unwrap(),
2363 ),
2364 ell_vv: Fq2::new(
2365 Fq::new(U256([
2366 70847827090593073015786004614483673839,
2367 3475230874891506896203634678143642692,
2368 ]))
2369 .unwrap(),
2370 Fq::new(U256([
2371 8314731801106602343291488634630259831,
2372 3521008420700564106163167660007668706,
2373 ]))
2374 .unwrap(),
2375 ),
2376 },
2377 EllCoeffs {
2378 ell_0: Fq2::new(
2379 Fq::new(U256([
2380 92354268952660546820822603858288251059,
2381 19778715140389467112147527814081030657,
2382 ]))
2383 .unwrap(),
2384 Fq::new(U256([
2385 329385425284714431570594794971018721246,
2386 60587846563454266929636649850787073194,
2387 ]))
2388 .unwrap(),
2389 ),
2390 ell_vw: Fq2::new(
2391 Fq::new(U256([
2392 288633840471857542459144118014949000217,
2393 51605528849039220650036727626483827846,
2394 ]))
2395 .unwrap(),
2396 Fq::new(U256([
2397 251176740648089198193669671101929833609,
2398 48200613470991338988108533743364275499,
2399 ]))
2400 .unwrap(),
2401 ),
2402 ell_vv: Fq2::new(
2403 Fq::new(U256([
2404 329193234492690486040808567065220826749,
2405 21378867659438236011740749197423248550,
2406 ]))
2407 .unwrap(),
2408 Fq::new(U256([
2409 285725508694128806244839238836446595834,
2410 16111887615812423492270406970991867951,
2411 ]))
2412 .unwrap(),
2413 ),
2414 },
2415 EllCoeffs {
2416 ell_0: Fq2::new(
2417 Fq::new(U256([
2418 152431519506548878061194990588057484057,
2419 49184327280433466363535994383523121304,
2420 ]))
2421 .unwrap(),
2422 Fq::new(U256([
2423 176897083100713735838942116510311567986,
2424 37010995217032206230292299420436992452,
2425 ]))
2426 .unwrap(),
2427 ),
2428 ell_vw: Fq2::new(
2429 Fq::new(U256([
2430 130722401240365261778198584122678322362,
2431 19293082368638790806988358431355209633,
2432 ]))
2433 .unwrap(),
2434 Fq::new(U256([
2435 336032502313799023638100083369289206306,
2436 31063427179065887680551186789065013379,
2437 ]))
2438 .unwrap(),
2439 ),
2440 ell_vv: Fq2::new(
2441 Fq::new(U256([
2442 313119215174514058940660103265063450959,
2443 25103967051083955792570154250792420707,
2444 ]))
2445 .unwrap(),
2446 Fq::new(U256([
2447 31520718700780462452153016807890400365,
2448 3961179668062303572693429066523266858,
2449 ]))
2450 .unwrap(),
2451 ),
2452 },
2453 EllCoeffs {
2454 ell_0: Fq2::new(
2455 Fq::new(U256([
2456 36667789591031625960240713279402427923,
2457 5637784774941607531109129433890086293,
2458 ]))
2459 .unwrap(),
2460 Fq::new(U256([
2461 286537786902526732905389646221547183400,
2462 56733382321156059969864849624810202662,
2463 ]))
2464 .unwrap(),
2465 ),
2466 ell_vw: Fq2::new(
2467 Fq::new(U256([
2468 318803650206508773198520172514605937449,
2469 26727846312556415159035648438885744059,
2470 ]))
2471 .unwrap(),
2472 Fq::new(U256([
2473 296466727057750056890238712141155450998,
2474 27938872020780344351123790536034462604,
2475 ]))
2476 .unwrap(),
2477 ),
2478 ell_vv: Fq2::new(
2479 Fq::new(U256([
2480 324800882000687209140271724886698306645,
2481 44039571306759586933457684739133508444,
2482 ]))
2483 .unwrap(),
2484 Fq::new(U256([
2485 47608245752536926992583482090528259005,
2486 47831283599118732387313994410846427415,
2487 ]))
2488 .unwrap(),
2489 ),
2490 },
2491 EllCoeffs {
2492 ell_0: Fq2::new(
2493 Fq::new(U256([
2494 234409386597337888556308771844488457344,
2495 12956567414802650084616113864217789370,
2496 ]))
2497 .unwrap(),
2498 Fq::new(U256([
2499 54897214305565100948138138335662741789,
2500 15577398627840234231085370089137424292,
2501 ]))
2502 .unwrap(),
2503 ),
2504 ell_vw: Fq2::new(
2505 Fq::new(U256([
2506 133034516621699526624516176710921958663,
2507 21900941110792896857560826682314104825,
2508 ]))
2509 .unwrap(),
2510 Fq::new(U256([
2511 91786723574963827227124861422083359642,
2512 15631994703072556950984703411138300334,
2513 ]))
2514 .unwrap(),
2515 ),
2516 ell_vv: Fq2::new(
2517 Fq::new(U256([
2518 61994842824519647915165015802348883298,
2519 3606506510538278544457628965895793792,
2520 ]))
2521 .unwrap(),
2522 Fq::new(U256([
2523 176676927874382884508332121131239871282,
2524 40115823781693004388411447312641595826,
2525 ]))
2526 .unwrap(),
2527 ),
2528 },
2529 EllCoeffs {
2530 ell_0: Fq2::new(
2531 Fq::new(U256([
2532 16486756791893393092802670694010735350,
2533 51213785425023838862657045286249924761,
2534 ]))
2535 .unwrap(),
2536 Fq::new(U256([
2537 127374475998848055784786954745585192546,
2538 61927128032062116041960763307324749312,
2539 ]))
2540 .unwrap(),
2541 ),
2542 ell_vw: Fq2::new(
2543 Fq::new(U256([
2544 57390628646817442883586335851238696952,
2545 1896752620999083872406878608493454725,
2546 ]))
2547 .unwrap(),
2548 Fq::new(U256([
2549 221112496886805666932828220912733522283,
2550 2796002105546343313342619098780470642,
2551 ]))
2552 .unwrap(),
2553 ),
2554 ell_vv: Fq2::new(
2555 Fq::new(U256([
2556 126113866998638086000522716026151108800,
2557 58788515162206661637618804912085907736,
2558 ]))
2559 .unwrap(),
2560 Fq::new(U256([
2561 19079621171649876430748555077055696995,
2562 46826087543975014201271501761421031441,
2563 ]))
2564 .unwrap(),
2565 ),
2566 },
2567 EllCoeffs {
2568 ell_0: Fq2::new(
2569 Fq::new(U256([
2570 287527947651847089840085422221128698763,
2571 3282429064220775329203352366444259855,
2572 ]))
2573 .unwrap(),
2574 Fq::new(U256([
2575 307065141447870398567299540185758941637,
2576 48193280250277647112409463651594786821,
2577 ]))
2578 .unwrap(),
2579 ),
2580 ell_vw: Fq2::new(
2581 Fq::new(U256([
2582 39874018308944266937776827490734641649,
2583 37791912819895325896728519088674532352,
2584 ]))
2585 .unwrap(),
2586 Fq::new(U256([
2587 11619188332176047954604673895207823813,
2588 12983193006960451462302777892755566431,
2589 ]))
2590 .unwrap(),
2591 ),
2592 ell_vv: Fq2::new(
2593 Fq::new(U256([
2594 76045219079383487030610001932731241273,
2595 16472513195230803643409094386807276517,
2596 ]))
2597 .unwrap(),
2598 Fq::new(U256([
2599 244195048886093761135684126358283143738,
2600 19479715688038787901591036330200598003,
2601 ]))
2602 .unwrap(),
2603 ),
2604 },
2605 EllCoeffs {
2606 ell_0: Fq2::new(
2607 Fq::new(U256([
2608 10563934263428977131610186732868968998,
2609 14179527485555674710937849675581267906,
2610 ]))
2611 .unwrap(),
2612 Fq::new(U256([
2613 257836314204976892854269567329818300595,
2614 50763620022812667001295845381267741649,
2615 ]))
2616 .unwrap(),
2617 ),
2618 ell_vw: Fq2::new(
2619 Fq::new(U256([
2620 160125271831790681583846356333205971645,
2621 38979573670559551140762745448476278558,
2622 ]))
2623 .unwrap(),
2624 Fq::new(U256([
2625 258822435332825467396267733276444939733,
2626 19361127335094998017975714923507638644,
2627 ]))
2628 .unwrap(),
2629 ),
2630 ell_vv: Fq2::new(
2631 Fq::new(U256([
2632 5086484109635987997951722709219418410,
2633 11993539151823720275736182499510363133,
2634 ]))
2635 .unwrap(),
2636 Fq::new(U256([
2637 171423009691627362399764794909459189507,
2638 20404136165000279368092981943358482669,
2639 ]))
2640 .unwrap(),
2641 ),
2642 },
2643 EllCoeffs {
2644 ell_0: Fq2::new(
2645 Fq::new(U256([
2646 249500614137833023351305910264605008487,
2647 42310425481082032237299673828774704531,
2648 ]))
2649 .unwrap(),
2650 Fq::new(U256([
2651 253496613223900195266106558972296162241,
2652 19046240361322320039639197826388768369,
2653 ]))
2654 .unwrap(),
2655 ),
2656 ell_vw: Fq2::new(
2657 Fq::new(U256([
2658 72263736846331351747703353269055941107,
2659 19969702258117494907412570199791763548,
2660 ]))
2661 .unwrap(),
2662 Fq::new(U256([
2663 126173921786290239044307538655562024455,
2664 18006158804314393556918633600879748967,
2665 ]))
2666 .unwrap(),
2667 ),
2668 ell_vv: Fq2::new(
2669 Fq::new(U256([
2670 16201000244836956196708576962189993382,
2671 32135871927111623648702296852432295139,
2672 ]))
2673 .unwrap(),
2674 Fq::new(U256([
2675 186963801770492707056456887595022261993,
2676 2392014174637078162701730926122882282,
2677 ]))
2678 .unwrap(),
2679 ),
2680 },
2681 EllCoeffs {
2682 ell_0: Fq2::new(
2683 Fq::new(U256([
2684 8922998024015454766590940715881630670,
2685 55567280047347356367358986337109964651,
2686 ]))
2687 .unwrap(),
2688 Fq::new(U256([
2689 313173491437683437471834863194199707492,
2690 3438176908844635046641649505356812159,
2691 ]))
2692 .unwrap(),
2693 ),
2694 ell_vw: Fq2::new(
2695 Fq::new(U256([
2696 276513541262028309851175912267910407247,
2697 11212571122829858982221117734299851084,
2698 ]))
2699 .unwrap(),
2700 Fq::new(U256([
2701 259509606552160006313745402323745013955,
2702 43114059504717558659877851383190095613,
2703 ]))
2704 .unwrap(),
2705 ),
2706 ell_vv: Fq2::new(
2707 Fq::new(U256([
2708 28098698558455079499553496395853067214,
2709 2999821831816440733771768849050005165,
2710 ]))
2711 .unwrap(),
2712 Fq::new(U256([
2713 334260605709723946550826958885726232933,
2714 11843826148467149350077605819950881153,
2715 ]))
2716 .unwrap(),
2717 ),
2718 },
2719 EllCoeffs {
2720 ell_0: Fq2::new(
2721 Fq::new(U256([
2722 283455530950531157108702282345810919101,
2723 52521643621580203161269969006017546759,
2724 ]))
2725 .unwrap(),
2726 Fq::new(U256([
2727 118200123115287742628646618978307449884,
2728 14795263733303838767894982171654042612,
2729 ]))
2730 .unwrap(),
2731 ),
2732 ell_vw: Fq2::new(
2733 Fq::new(U256([
2734 132641709504834974317245159550618583253,
2735 28570895840581787308435502085893978558,
2736 ]))
2737 .unwrap(),
2738 Fq::new(U256([
2739 229949535634549796967397304164923056337,
2740 42352202734287711800564772982472784839,
2741 ]))
2742 .unwrap(),
2743 ),
2744 ell_vv: Fq2::new(
2745 Fq::new(U256([
2746 128199924683494278990710814519750517837,
2747 58638050185358930355922065483565476451,
2748 ]))
2749 .unwrap(),
2750 Fq::new(U256([
2751 4192016302378839786647752861109219112,
2752 61114929591783829703998838288847230811,
2753 ]))
2754 .unwrap(),
2755 ),
2756 },
2757 EllCoeffs {
2758 ell_0: Fq2::new(
2759 Fq::new(U256([
2760 113754079486581376183180167710451964178,
2761 25998717875687967363117010408717972365,
2762 ]))
2763 .unwrap(),
2764 Fq::new(U256([
2765 133697001740616163002906224555636440440,
2766 23546896556625148713807775573505304385,
2767 ]))
2768 .unwrap(),
2769 ),
2770 ell_vw: Fq2::new(
2771 Fq::new(U256([
2772 227150749988479615370826356819617461792,
2773 41368715815045829029754124051658999245,
2774 ]))
2775 .unwrap(),
2776 Fq::new(U256([
2777 222514455614853854819390285868145864687,
2778 27579121989432504016710179821357885225,
2779 ]))
2780 .unwrap(),
2781 ),
2782 ell_vv: Fq2::new(
2783 Fq::new(U256([
2784 128433415390196263739951350076595027296,
2785 55636438757722652255615208065796848545,
2786 ]))
2787 .unwrap(),
2788 Fq::new(U256([
2789 94671524825895380554049635623924644741,
2790 9791488862788864605119131922310440121,
2791 ]))
2792 .unwrap(),
2793 ),
2794 },
2795 EllCoeffs {
2796 ell_0: Fq2::new(
2797 Fq::new(U256([
2798 153881172058568095361353223261899310845,
2799 17156484263879687903526208855029043640,
2800 ]))
2801 .unwrap(),
2802 Fq::new(U256([
2803 192077265925835218260989605323461142787,
2804 32318605747689071742310867751273886645,
2805 ]))
2806 .unwrap(),
2807 ),
2808 ell_vw: Fq2::new(
2809 Fq::new(U256([
2810 317408271159096505221916390262196469787,
2811 49717575675851229633286204770028665263,
2812 ]))
2813 .unwrap(),
2814 Fq::new(U256([
2815 230095008714744652782426759714312292445,
2816 34768179553549400629211217553610554586,
2817 ]))
2818 .unwrap(),
2819 ),
2820 ell_vv: Fq2::new(
2821 Fq::new(U256([
2822 259609023305192462223688164733847327699,
2823 55498873698881710203435569648274404478,
2824 ]))
2825 .unwrap(),
2826 Fq::new(U256([
2827 256325550082466559964506871761831536884,
2828 46357653853657184428683736043713888406,
2829 ]))
2830 .unwrap(),
2831 ),
2832 },
2833 EllCoeffs {
2834 ell_0: Fq2::new(
2835 Fq::new(U256([
2836 174577378801081039438668831531067795857,
2837 53157547858752109585449689851969780390,
2838 ]))
2839 .unwrap(),
2840 Fq::new(U256([
2841 82151408345597494862089436182070514285,
2842 16466308473185906030465208465158400278,
2843 ]))
2844 .unwrap(),
2845 ),
2846 ell_vw: Fq2::new(
2847 Fq::new(U256([
2848 245839213042247079917412337301921026922,
2849 22457019238909031929740892448482221879,
2850 ]))
2851 .unwrap(),
2852 Fq::new(U256([
2853 109513130235370254599453293800543710331,
2854 47936140417415756744920707247895308699,
2855 ]))
2856 .unwrap(),
2857 ),
2858 ell_vv: Fq2::new(
2859 Fq::new(U256([
2860 10776161146456696103487000724300150234,
2861 21638563281306406703950273508675616623,
2862 ]))
2863 .unwrap(),
2864 Fq::new(U256([
2865 207085916216710302318982426148546767798,
2866 7534717897684081051796825732586695012,
2867 ]))
2868 .unwrap(),
2869 ),
2870 },
2871 EllCoeffs {
2872 ell_0: Fq2::new(
2873 Fq::new(U256([
2874 155690435801319682239901337205468120840,
2875 57696234800836220244083348626584391674,
2876 ]))
2877 .unwrap(),
2878 Fq::new(U256([
2879 126757665472044690642504190674454727065,
2880 27689844381974512633117281405461511493,
2881 ]))
2882 .unwrap(),
2883 ),
2884 ell_vw: Fq2::new(
2885 Fq::new(U256([
2886 111371524430469273469505773333501881358,
2887 41915381107432591576214180621073813739,
2888 ]))
2889 .unwrap(),
2890 Fq::new(U256([
2891 8591307386286176660318558848651389629,
2892 19322060932256059989553597776338707006,
2893 ]))
2894 .unwrap(),
2895 ),
2896 ell_vv: Fq2::new(
2897 Fq::new(U256([
2898 34843642275668259465089406915935512474,
2899 25199006933559492770352887141455099490,
2900 ]))
2901 .unwrap(),
2902 Fq::new(U256([
2903 10645844381812821922686446509476566858,
2904 35688555865712593739042131731320400759,
2905 ]))
2906 .unwrap(),
2907 ),
2908 },
2909 EllCoeffs {
2910 ell_0: Fq2::new(
2911 Fq::new(U256([
2912 189947043026848705532544415056376972054,
2913 16798314122488336019972329871173393651,
2914 ]))
2915 .unwrap(),
2916 Fq::new(U256([
2917 308591971026665862143792543801958855960,
2918 31580607213628921122716343407923691193,
2919 ]))
2920 .unwrap(),
2921 ),
2922 ell_vw: Fq2::new(
2923 Fq::new(U256([
2924 163093806147198705684115256712150030567,
2925 61044717475711501197927838344963107641,
2926 ]))
2927 .unwrap(),
2928 Fq::new(U256([
2929 307478741843426518207523544103444625011,
2930 32813498165003357356133773951397928550,
2931 ]))
2932 .unwrap(),
2933 ),
2934 ell_vv: Fq2::new(
2935 Fq::new(U256([
2936 95291548361985054080716711033104720817,
2937 32740343556226865497613504752972186774,
2938 ]))
2939 .unwrap(),
2940 Fq::new(U256([
2941 99656074525833092595857684423204299816,
2942 52556239373424263650635019541397500598,
2943 ]))
2944 .unwrap(),
2945 ),
2946 },
2947 EllCoeffs {
2948 ell_0: Fq2::new(
2949 Fq::new(U256([
2950 131443621763425639580622258813874957855,
2951 17694455882904396881053896673232601550,
2952 ]))
2953 .unwrap(),
2954 Fq::new(U256([
2955 57787363176533727883752817750279248594,
2956 1322856562657561354884935596241784834,
2957 ]))
2958 .unwrap(),
2959 ),
2960 ell_vw: Fq2::new(
2961 Fq::new(U256([
2962 41788280636884607828680584839495219344,
2963 51762903848994175839707598487572362464,
2964 ]))
2965 .unwrap(),
2966 Fq::new(U256([
2967 327908654890111464339978492292915303796,
2968 47344360741808824501224988176645616993,
2969 ]))
2970 .unwrap(),
2971 ),
2972 ell_vv: Fq2::new(
2973 Fq::new(U256([
2974 263873593879772810642440946076120656306,
2975 60210233792451977377881584251511840173,
2976 ]))
2977 .unwrap(),
2978 Fq::new(U256([
2979 77405826008973124400288647208797749719,
2980 53019697808811506999139211676029205579,
2981 ]))
2982 .unwrap(),
2983 ),
2984 },
2985 EllCoeffs {
2986 ell_0: Fq2::new(
2987 Fq::new(U256([
2988 254578463202394703187741702356839561011,
2989 21096342408485278014732435848864790919,
2990 ]))
2991 .unwrap(),
2992 Fq::new(U256([
2993 230473548197181635567135409745417796610,
2994 22147822186055995413422331229074559071,
2995 ]))
2996 .unwrap(),
2997 ),
2998 ell_vw: Fq2::new(
2999 Fq::new(U256([
3000 336878015160301245042116518989872047941,
3001 3472301140759760061593082376347546380,
3002 ]))
3003 .unwrap(),
3004 Fq::new(U256([
3005 16684778019642037346902548590480489922,
3006 63174559216409847644418505532384053845,
3007 ]))
3008 .unwrap(),
3009 ),
3010 ell_vv: Fq2::new(
3011 Fq::new(U256([
3012 7942031074055265340884029455787976403,
3013 46511448608441944387405531466341650044,
3014 ]))
3015 .unwrap(),
3016 Fq::new(U256([
3017 201615416576767918339868727158350994412,
3018 64255187168173681561527383354144167567,
3019 ]))
3020 .unwrap(),
3021 ),
3022 },
3023 EllCoeffs {
3024 ell_0: Fq2::new(
3025 Fq::new(U256([
3026 243308496406996226443557446925779452296,
3027 45849597498959240205941430238383669623,
3028 ]))
3029 .unwrap(),
3030 Fq::new(U256([
3031 48147614977633577164856356428453305437,
3032 24480032415168951986931189038013914221,
3033 ]))
3034 .unwrap(),
3035 ),
3036 ell_vw: Fq2::new(
3037 Fq::new(U256([
3038 74830884455458736654394458059429787198,
3039 19093844097308332947749289150298249126,
3040 ]))
3041 .unwrap(),
3042 Fq::new(U256([
3043 33643899737753431509498018706471379301,
3044 1054576208141392093174173023229894557,
3045 ]))
3046 .unwrap(),
3047 ),
3048 ell_vv: Fq2::new(
3049 Fq::new(U256([
3050 25010096200987042473393926604632958161,
3051 36666296164531908118513449509789076579,
3052 ]))
3053 .unwrap(),
3054 Fq::new(U256([
3055 33471717379111372311065514803349918045,
3056 39155528164590001712332400960607038189,
3057 ]))
3058 .unwrap(),
3059 ),
3060 },
3061 EllCoeffs {
3062 ell_0: Fq2::new(
3063 Fq::new(U256([
3064 130247467451091212947023092388792369109,
3065 5581090585326037371051920053369586280,
3066 ]))
3067 .unwrap(),
3068 Fq::new(U256([
3069 322360327312842929444256001314179239601,
3070 39584478520709259399389327249557202594,
3071 ]))
3072 .unwrap(),
3073 ),
3074 ell_vw: Fq2::new(
3075 Fq::new(U256([
3076 109138162516199992788447200019766811785,
3077 47525457821584643247627414608651841972,
3078 ]))
3079 .unwrap(),
3080 Fq::new(U256([
3081 76309968110600274074720854748516338453,
3082 54739068402347163521228676077893779893,
3083 ]))
3084 .unwrap(),
3085 ),
3086 ell_vv: Fq2::new(
3087 Fq::new(U256([
3088 42180409310074737345249452446852603163,
3089 4374831491626595184699821621506201010,
3090 ]))
3091 .unwrap(),
3092 Fq::new(U256([
3093 130057601620482713644106051600317093239,
3094 12010679381934251249551375242240386988,
3095 ]))
3096 .unwrap(),
3097 ),
3098 },
3099 EllCoeffs {
3100 ell_0: Fq2::new(
3101 Fq::new(U256([
3102 203271863519350650976092478448210829293,
3103 52275506975977654460248547356331731574,
3104 ]))
3105 .unwrap(),
3106 Fq::new(U256([
3107 87019891938199989232789187109647269328,
3108 44030460834732836505939430240249354505,
3109 ]))
3110 .unwrap(),
3111 ),
3112 ell_vw: Fq2::new(
3113 Fq::new(U256([
3114 110171920943726136564495503552694726540,
3115 18110786866783187141705660513534498930,
3116 ]))
3117 .unwrap(),
3118 Fq::new(U256([
3119 86561692963802460817471572747090778194,
3120 16449770553500671507593674575394564582,
3121 ]))
3122 .unwrap(),
3123 ),
3124 ell_vv: Fq2::new(
3125 Fq::new(U256([
3126 221876651023252602014468911202182579931,
3127 20555077542463658872780769250687782117,
3128 ]))
3129 .unwrap(),
3130 Fq::new(U256([
3131 121263539082468326970413896423548540112,
3132 61907715120666399953423277772754945448,
3133 ]))
3134 .unwrap(),
3135 ),
3136 },
3137 EllCoeffs {
3138 ell_0: Fq2::new(
3139 Fq::new(U256([
3140 290357192776207049084050762947655748975,
3141 57738753410091871200747406135207764151,
3142 ]))
3143 .unwrap(),
3144 Fq::new(U256([
3145 135358190114239175182066780052123869069,
3146 56081507988571629614406051210751609147,
3147 ]))
3148 .unwrap(),
3149 ),
3150 ell_vw: Fq2::new(
3151 Fq::new(U256([
3152 195622544431419990666685034787625747326,
3153 54874770374981417815900652767969731611,
3154 ]))
3155 .unwrap(),
3156 Fq::new(U256([
3157 6243075893789260529022348241785972764,
3158 56521196313521047823704039910006760241,
3159 ]))
3160 .unwrap(),
3161 ),
3162 ell_vv: Fq2::new(
3163 Fq::new(U256([
3164 243495103440406073534289072917982313090,
3165 57589106164518822864160786869003317813,
3166 ]))
3167 .unwrap(),
3168 Fq::new(U256([
3169 235848100009165241948327269818774314127,
3170 37511141642844469126769577281189903937,
3171 ]))
3172 .unwrap(),
3173 ),
3174 },
3175 EllCoeffs {
3176 ell_0: Fq2::new(
3177 Fq::new(U256([
3178 78592775623001882471215007061407141105,
3179 34941191764695857355641077076235001298,
3180 ]))
3181 .unwrap(),
3182 Fq::new(U256([
3183 267356444067983260493350102628306009780,
3184 28391440678450825886400816194304466425,
3185 ]))
3186 .unwrap(),
3187 ),
3188 ell_vw: Fq2::new(
3189 Fq::new(U256([
3190 315751120363918319477358949808863604966,
3191 2531298718421943078485957285990819438,
3192 ]))
3193 .unwrap(),
3194 Fq::new(U256([
3195 242692025957487623878146464744369629015,
3196 52949313651228011397330521709355671746,
3197 ]))
3198 .unwrap(),
3199 ),
3200 ell_vv: Fq2::new(
3201 Fq::new(U256([
3202 223701370913329345484604486557612973051,
3203 34658421329859066183602046886271845301,
3204 ]))
3205 .unwrap(),
3206 Fq::new(U256([
3207 239281725801587867757289553693045231533,
3208 14055606950515704853984812857124180593,
3209 ]))
3210 .unwrap(),
3211 ),
3212 },
3213 EllCoeffs {
3214 ell_0: Fq2::new(
3215 Fq::new(U256([
3216 321292144065398009067550865125623060600,
3217 18828918489183113618746569726487918435,
3218 ]))
3219 .unwrap(),
3220 Fq::new(U256([
3221 44953266506250560322305758112518632685,
3222 12818035770624926325618902943072758802,
3223 ]))
3224 .unwrap(),
3225 ),
3226 ell_vw: Fq2::new(
3227 Fq::new(U256([
3228 198712001500603483304766131655796332238,
3229 37755493054877351200992330081944773222,
3230 ]))
3231 .unwrap(),
3232 Fq::new(U256([
3233 203494901390506520787336076745404879355,
3234 9719695048988798612029815523720059188,
3235 ]))
3236 .unwrap(),
3237 ),
3238 ell_vv: Fq2::new(
3239 Fq::new(U256([
3240 324082713664478232334150476671698670935,
3241 57968755532718074766231332303127747698,
3242 ]))
3243 .unwrap(),
3244 Fq::new(U256([
3245 172967914786650717580471091827836918517,
3246 39836011047291872323399953583350854813,
3247 ]))
3248 .unwrap(),
3249 ),
3250 },
3251 EllCoeffs {
3252 ell_0: Fq2::new(
3253 Fq::new(U256([
3254 104693003047177326696685168159983773290,
3255 21362453846755563999603040010467525220,
3256 ]))
3257 .unwrap(),
3258 Fq::new(U256([
3259 56374029098225126238873495696162227687,
3260 61374137561202742141169238350854689065,
3261 ]))
3262 .unwrap(),
3263 ),
3264 ell_vw: Fq2::new(
3265 Fq::new(U256([
3266 158941255788517659316631775720407312680,
3267 2477940982651390357755438379586767771,
3268 ]))
3269 .unwrap(),
3270 Fq::new(U256([
3271 212374631437158170731256215648153937637,
3272 51786402687200191668238627015343248084,
3273 ]))
3274 .unwrap(),
3275 ),
3276 ell_vv: Fq2::new(
3277 Fq::new(U256([
3278 67431426417348416607065438525684723676,
3279 59371917376780773574999923335758781547,
3280 ]))
3281 .unwrap(),
3282 Fq::new(U256([
3283 329921395426288970367695061271959172005,
3284 18586382421107856878975478269722973139,
3285 ]))
3286 .unwrap(),
3287 ),
3288 },
3289 EllCoeffs {
3290 ell_0: Fq2::new(
3291 Fq::new(U256([
3292 207312856868420470351121539398556490708,
3293 6749469271717320482346458817170377645,
3294 ]))
3295 .unwrap(),
3296 Fq::new(U256([
3297 297463942398989836675066926378547228117,
3298 42180709737629195771943741993025816145,
3299 ]))
3300 .unwrap(),
3301 ),
3302 ell_vw: Fq2::new(
3303 Fq::new(U256([
3304 294946811578231549301710677543341218799,
3305 20992621396953319301177509266206083412,
3306 ]))
3307 .unwrap(),
3308 Fq::new(U256([
3309 334489506001987366917405458471890123881,
3310 5644882162624043756459843063788196004,
3311 ]))
3312 .unwrap(),
3313 ),
3314 ell_vv: Fq2::new(
3315 Fq::new(U256([
3316 339439573540481749394421794993912483199,
3317 45246606008318294125455064627263238236,
3318 ]))
3319 .unwrap(),
3320 Fq::new(U256([
3321 270454941633781906426514756020454116063,
3322 13672349860189847846584888881208438638,
3323 ]))
3324 .unwrap(),
3325 ),
3326 },
3327 EllCoeffs {
3328 ell_0: Fq2::new(
3329 Fq::new(U256([
3330 184109810967303467375292693011959132443,
3331 22047527326459095654736206729881706277,
3332 ]))
3333 .unwrap(),
3334 Fq::new(U256([
3335 306855976122543936818762044270256507301,
3336 13817693020515802987708208420701920996,
3337 ]))
3338 .unwrap(),
3339 ),
3340 ell_vw: Fq2::new(
3341 Fq::new(U256([
3342 18944943876649574380290951381571111173,
3343 54681599103691370082120691137707858843,
3344 ]))
3345 .unwrap(),
3346 Fq::new(U256([
3347 274481158071926596330090943889570839876,
3348 27656594457831811691825162550052997369,
3349 ]))
3350 .unwrap(),
3351 ),
3352 ell_vv: Fq2::new(
3353 Fq::new(U256([
3354 72068179718393541085353916977402777797,
3355 23085120169523399820600846468009840798,
3356 ]))
3357 .unwrap(),
3358 Fq::new(U256([
3359 39623239893391127442673085065505018616,
3360 49714238177847283522861975755429582165,
3361 ]))
3362 .unwrap(),
3363 ),
3364 },
3365 EllCoeffs {
3366 ell_0: Fq2::new(
3367 Fq::new(U256([
3368 326109292257788796875387755492793672492,
3369 38017828106840559651298055936334805586,
3370 ]))
3371 .unwrap(),
3372 Fq::new(U256([
3373 300970874956733001966255469483871058465,
3374 61693366793354972449623979259561628170,
3375 ]))
3376 .unwrap(),
3377 ),
3378 ell_vw: Fq2::new(
3379 Fq::new(U256([
3380 247117608403708963869106314083852845952,
3381 6270392892469923670893298889464309224,
3382 ]))
3383 .unwrap(),
3384 Fq::new(U256([
3385 85229127169148541816114014402805254942,
3386 23692121466582475015916841187427174063,
3387 ]))
3388 .unwrap(),
3389 ),
3390 ell_vv: Fq2::new(
3391 Fq::new(U256([
3392 322377160078698123442118813943355848949,
3393 44790955831224275605828973863316334451,
3394 ]))
3395 .unwrap(),
3396 Fq::new(U256([
3397 246121457999548771204074791900055840778,
3398 36237050391238930724599650306620108395,
3399 ]))
3400 .unwrap(),
3401 ),
3402 },
3403 EllCoeffs {
3404 ell_0: Fq2::new(
3405 Fq::new(U256([
3406 6479203335512729615298164829455402801,
3407 18899857059703106109444283718983930606,
3408 ]))
3409 .unwrap(),
3410 Fq::new(U256([
3411 307909459343553081188134777979054198524,
3412 23104930848877581327335450138633822165,
3413 ]))
3414 .unwrap(),
3415 ),
3416 ell_vw: Fq2::new(
3417 Fq::new(U256([
3418 117408687141894236273811591312978416850,
3419 27064268635283187986411799061361560149,
3420 ]))
3421 .unwrap(),
3422 Fq::new(U256([
3423 89156958054425667145216654832344296184,
3424 28498155840544447742658664925302722255,
3425 ]))
3426 .unwrap(),
3427 ),
3428 ell_vv: Fq2::new(
3429 Fq::new(U256([
3430 264148561516468171084137463578412456470,
3431 56169366101528802291286278394614323282,
3432 ]))
3433 .unwrap(),
3434 Fq::new(U256([
3435 80748178838045963455037482306103002135,
3436 31627837956246452962075717178352705444,
3437 ]))
3438 .unwrap(),
3439 ),
3440 },
3441 EllCoeffs {
3442 ell_0: Fq2::new(
3443 Fq::new(U256([
3444 228462396223758741175275124462032775241,
3445 541217865154375519097785562072294622,
3446 ]))
3447 .unwrap(),
3448 Fq::new(U256([
3449 147690209661782719555035340726175029695,
3450 47332569057322758675859735205860987883,
3451 ]))
3452 .unwrap(),
3453 ),
3454 ell_vw: Fq2::new(
3455 Fq::new(U256([
3456 332785070356059610611838282826287767824,
3457 28411804506527712891888004500289036321,
3458 ]))
3459 .unwrap(),
3460 Fq::new(U256([
3461 80347503246503526995863756906237840538,
3462 40694963808412110626720215103350226072,
3463 ]))
3464 .unwrap(),
3465 ),
3466 ell_vv: Fq2::new(
3467 Fq::new(U256([
3468 73246772632733278293170183313248743910,
3469 51739954405360462951359314934075204478,
3470 ]))
3471 .unwrap(),
3472 Fq::new(U256([
3473 323288654986485051471927026636004277374,
3474 55328786519754064217639655113348868700,
3475 ]))
3476 .unwrap(),
3477 ),
3478 },
3479 EllCoeffs {
3480 ell_0: Fq2::new(
3481 Fq::new(U256([
3482 107183915141555030394480811055835932411,
3483 28743337205734819613101267731330261274,
3484 ]))
3485 .unwrap(),
3486 Fq::new(U256([
3487 265627562010734120334801493421007962860,
3488 21113833505065027987742094370311235794,
3489 ]))
3490 .unwrap(),
3491 ),
3492 ell_vw: Fq2::new(
3493 Fq::new(U256([
3494 145390576010968264278778301175950417032,
3495 25603093564950634850451680305056487937,
3496 ]))
3497 .unwrap(),
3498 Fq::new(U256([
3499 171224041010792018070371064846900704811,
3500 50628689539088695975060303147297926726,
3501 ]))
3502 .unwrap(),
3503 ),
3504 ell_vv: Fq2::new(
3505 Fq::new(U256([
3506 181636860313080877557100227907605412643,
3507 19106550849436726002022081116470620327,
3508 ]))
3509 .unwrap(),
3510 Fq::new(U256([
3511 97037887458346176230370696042525047476,
3512 38315199704917257726469887714210863756,
3513 ]))
3514 .unwrap(),
3515 ),
3516 },
3517 EllCoeffs {
3518 ell_0: Fq2::new(
3519 Fq::new(U256([
3520 165755565692898412861884552154775259871,
3521 23293168176203049828541858307098176114,
3522 ]))
3523 .unwrap(),
3524 Fq::new(U256([
3525 111579679857180892572143097811395790681,
3526 21526844626039124934190021704344618627,
3527 ]))
3528 .unwrap(),
3529 ),
3530 ell_vw: Fq2::new(
3531 Fq::new(U256([
3532 335258764315672309726009417334449368453,
3533 103404408330729181499563204707141002,
3534 ]))
3535 .unwrap(),
3536 Fq::new(U256([
3537 191071126894978514432059671553769626880,
3538 5078535341242500657674641815850178322,
3539 ]))
3540 .unwrap(),
3541 ),
3542 ell_vv: Fq2::new(
3543 Fq::new(U256([
3544 72579254643315478022492189073789591450,
3545 44167090301255006150406576419615402343,
3546 ]))
3547 .unwrap(),
3548 Fq::new(U256([
3549 183377394594390630206602640102963629039,
3550 23990882412966103396841140729654425350,
3551 ]))
3552 .unwrap(),
3553 ),
3554 },
3555 EllCoeffs {
3556 ell_0: Fq2::new(
3557 Fq::new(U256([
3558 66679892701097417538832992488778691458,
3559 58183623071000462877229489086029090922,
3560 ]))
3561 .unwrap(),
3562 Fq::new(U256([
3563 294287188350011499287443971281382798030,
3564 18151493196929461249661140690411179165,
3565 ]))
3566 .unwrap(),
3567 ),
3568 ell_vw: Fq2::new(
3569 Fq::new(U256([
3570 74805142807574287323605988196524192535,
3571 18100483139591925759594156937304667397,
3572 ]))
3573 .unwrap(),
3574 Fq::new(U256([
3575 139120256621259665435015294709846943744,
3576 33412960622211929574259219789625651855,
3577 ]))
3578 .unwrap(),
3579 ),
3580 ell_vv: Fq2::new(
3581 Fq::new(U256([
3582 220224993980394484792559335583346867939,
3583 59970476024877867633551960552156066815,
3584 ]))
3585 .unwrap(),
3586 Fq::new(U256([
3587 165016476912320413641798011850430383400,
3588 40087637389842239140931509158661317913,
3589 ]))
3590 .unwrap(),
3591 ),
3592 },
3593 EllCoeffs {
3594 ell_0: Fq2::new(
3595 Fq::new(U256([
3596 26669149284356063486638395246213038984,
3597 48932308059862148467989673144064276455,
3598 ]))
3599 .unwrap(),
3600 Fq::new(U256([
3601 112017260916309235481572722060511554523,
3602 1292432061742789600481111238179731344,
3603 ]))
3604 .unwrap(),
3605 ),
3606 ell_vw: Fq2::new(
3607 Fq::new(U256([
3608 162967204317649679020730851544536806310,
3609 32746563765578881184210706548921981702,
3610 ]))
3611 .unwrap(),
3612 Fq::new(U256([
3613 337655071624981772776297963145482993016,
3614 33145701869840355692613219913227327224,
3615 ]))
3616 .unwrap(),
3617 ),
3618 ell_vv: Fq2::new(
3619 Fq::new(U256([
3620 116821007696021810040981824168902376385,
3621 46826353416371587869648603174437608629,
3622 ]))
3623 .unwrap(),
3624 Fq::new(U256([
3625 286148963257224477643539266261574758187,
3626 20903220425259595580283778435979469601,
3627 ]))
3628 .unwrap(),
3629 ),
3630 },
3631 EllCoeffs {
3632 ell_0: Fq2::new(
3633 Fq::new(U256([
3634 265822762895337622674318289864003560145,
3635 62593533822281897460585212079268870737,
3636 ]))
3637 .unwrap(),
3638 Fq::new(U256([
3639 180099245396770402139578639916315358651,
3640 5289891249371566111607452004558281256,
3641 ]))
3642 .unwrap(),
3643 ),
3644 ell_vw: Fq2::new(
3645 Fq::new(U256([
3646 215101732208902323596827687492609836402,
3647 60151379040875297433910120987825047988,
3648 ]))
3649 .unwrap(),
3650 Fq::new(U256([
3651 200376206977547885622799626268846642009,
3652 36107786828287031009478318323095814795,
3653 ]))
3654 .unwrap(),
3655 ),
3656 ell_vv: Fq2::new(
3657 Fq::new(U256([
3658 228632312969356396843036040954049410317,
3659 29609317291386275502321244693464627541,
3660 ]))
3661 .unwrap(),
3662 Fq::new(U256([
3663 250663071554126685512943663183005740350,
3664 26707628083885320745488595167117920892,
3665 ]))
3666 .unwrap(),
3667 ),
3668 },
3669 EllCoeffs {
3670 ell_0: Fq2::new(
3671 Fq::new(U256([
3672 167686658731994607869572641962208584698,
3673 32951815034866853047881968952398296677,
3674 ]))
3675 .unwrap(),
3676 Fq::new(U256([
3677 59732843077777643290110085014121270991,
3678 19690792480201713304572701985281652804,
3679 ]))
3680 .unwrap(),
3681 ),
3682 ell_vw: Fq2::new(
3683 Fq::new(U256([
3684 231501326469976058677041937508913323742,
3685 58052555179693233540250119022219467367,
3686 ]))
3687 .unwrap(),
3688 Fq::new(U256([
3689 268839178939407644460103390562050250791,
3690 51244123519915889574699519125947948433,
3691 ]))
3692 .unwrap(),
3693 ),
3694 ell_vv: Fq2::new(
3695 Fq::new(U256([
3696 15335721378364717505397406493265760457,
3697 50543654003772338617069451450467156120,
3698 ]))
3699 .unwrap(),
3700 Fq::new(U256([
3701 147668560194510325215853847922114742688,
3702 63436405408432434981818242494869996954,
3703 ]))
3704 .unwrap(),
3705 ),
3706 },
3707 EllCoeffs {
3708 ell_0: Fq2::new(
3709 Fq::new(U256([
3710 324251215335356818847634371978327094047,
3711 53597895382917031159515977918983297046,
3712 ]))
3713 .unwrap(),
3714 Fq::new(U256([
3715 336456284126450597413571076848285070208,
3716 9834107003348358663468869495065030828,
3717 ]))
3718 .unwrap(),
3719 ),
3720 ell_vw: Fq2::new(
3721 Fq::new(U256([
3722 4893147365574829346121011245181836636,
3723 48500338802265501645481354399443896938,
3724 ]))
3725 .unwrap(),
3726 Fq::new(U256([
3727 242843203647079174857073639694991742532,
3728 39587639177217829196831837775949647839,
3729 ]))
3730 .unwrap(),
3731 ),
3732 ell_vv: Fq2::new(
3733 Fq::new(U256([
3734 260649755517395052354543412976006056345,
3735 41595453161552128661866319661777368912,
3736 ]))
3737 .unwrap(),
3738 Fq::new(U256([
3739 186473459113497941493205881377276393540,
3740 10232971634855792150439771169030969984,
3741 ]))
3742 .unwrap(),
3743 ),
3744 },
3745 EllCoeffs {
3746 ell_0: Fq2::new(
3747 Fq::new(U256([
3748 153156583597535672033657311231041916285,
3749 12870713391441384499488044032601826356,
3750 ]))
3751 .unwrap(),
3752 Fq::new(U256([
3753 160011046903032247780660416127755862604,
3754 59740658966179967701258870119449151446,
3755 ]))
3756 .unwrap(),
3757 ),
3758 ell_vw: Fq2::new(
3759 Fq::new(U256([
3760 53781592683706300755113958689829175735,
3761 5160246898475719650527746461036900035,
3762 ]))
3763 .unwrap(),
3764 Fq::new(U256([
3765 127406077100448076503048857464807666048,
3766 5027357614298608514576108334690214373,
3767 ]))
3768 .unwrap(),
3769 ),
3770 ell_vv: Fq2::new(
3771 Fq::new(U256([
3772 123323183388079598137911866134337668968,
3773 30831375761327507469744048674597209517,
3774 ]))
3775 .unwrap(),
3776 Fq::new(U256([
3777 282757148554018853521114389661374143994,
3778 41725892078174834143829265912887863334,
3779 ]))
3780 .unwrap(),
3781 ),
3782 },
3783 EllCoeffs {
3784 ell_0: Fq2::new(
3785 Fq::new(U256([
3786 231142251602796484920728141361531696801,
3787 43369687276260799996121293373394088506,
3788 ]))
3789 .unwrap(),
3790 Fq::new(U256([
3791 193386979673076292922455602081629373614,
3792 13517077812823754339540367661413555482,
3793 ]))
3794 .unwrap(),
3795 ),
3796 ell_vw: Fq2::new(
3797 Fq::new(U256([
3798 32945933209167472962271089890685376310,
3799 23645956766949617286909797728539496219,
3800 ]))
3801 .unwrap(),
3802 Fq::new(U256([
3803 128873344219688070096765758438736759675,
3804 54069131826062143440208582926638727688,
3805 ]))
3806 .unwrap(),
3807 ),
3808 ell_vv: Fq2::new(
3809 Fq::new(U256([
3810 307107650784744827303698892877513591771,
3811 60627460508970098579939906160617347629,
3812 ]))
3813 .unwrap(),
3814 Fq::new(U256([
3815 12937320851881845879608263929438137281,
3816 2854427512588805421842219517935335360,
3817 ]))
3818 .unwrap(),
3819 ),
3820 },
3821 EllCoeffs {
3822 ell_0: Fq2::new(
3823 Fq::new(U256([
3824 262645642925640470181426114122199935672,
3825 23413555848620303130105885294683582394,
3826 ]))
3827 .unwrap(),
3828 Fq::new(U256([
3829 23944562046020585348174388998952320194,
3830 45084472027505841447432550475379032518,
3831 ]))
3832 .unwrap(),
3833 ),
3834 ell_vw: Fq2::new(
3835 Fq::new(U256([
3836 270949855981998457946423634423510659239,
3837 52707980377915683827433393510154134085,
3838 ]))
3839 .unwrap(),
3840 Fq::new(U256([
3841 171166926104504281831828631675145047352,
3842 56745888676097625411354427758332611365,
3843 ]))
3844 .unwrap(),
3845 ),
3846 ell_vv: Fq2::new(
3847 Fq::new(U256([
3848 185108543406354812098225836322332681649,
3849 38838551534016041901193249287881822376,
3850 ]))
3851 .unwrap(),
3852 Fq::new(U256([
3853 220861944829798693206584739921489268335,
3854 13318922669002030127185287983351463417,
3855 ]))
3856 .unwrap(),
3857 ),
3858 },
3859 EllCoeffs {
3860 ell_0: Fq2::new(
3861 Fq::new(U256([
3862 262922874647306006405720155830997014046,
3863 60319938491997842161822791958118330349,
3864 ]))
3865 .unwrap(),
3866 Fq::new(U256([
3867 267514688756785010198929321975858316586,
3868 13431251784763107399729556927577885114,
3869 ]))
3870 .unwrap(),
3871 ),
3872 ell_vw: Fq2::new(
3873 Fq::new(U256([
3874 305051645126359797430782278231595423685,
3875 47480212315012773203275805598650271426,
3876 ]))
3877 .unwrap(),
3878 Fq::new(U256([
3879 61134576323692903306240935503639110628,
3880 44357224521089864059608299955085658945,
3881 ]))
3882 .unwrap(),
3883 ),
3884 ell_vv: Fq2::new(
3885 Fq::new(U256([
3886 288996190497897556231840221598596395445,
3887 7566958477031738465971309099100507442,
3888 ]))
3889 .unwrap(),
3890 Fq::new(U256([
3891 133814060971580680876860604680251720534,
3892 59538638355154696335532006425868258220,
3893 ]))
3894 .unwrap(),
3895 ),
3896 },
3897 EllCoeffs {
3898 ell_0: Fq2::new(
3899 Fq::new(U256([
3900 255893828824714285725760712618255298338,
3901 62054226651551009305279711173141456137,
3902 ]))
3903 .unwrap(),
3904 Fq::new(U256([
3905 278488875745654026562827558863613836490,
3906 21008509582420141439141693540430274581,
3907 ]))
3908 .unwrap(),
3909 ),
3910 ell_vw: Fq2::new(
3911 Fq::new(U256([
3912 275369357162135051507223962619748317962,
3913 42306683939383379782070254815636483252,
3914 ]))
3915 .unwrap(),
3916 Fq::new(U256([
3917 33692084190064829046021773249716169044,
3918 16341905693988596015816579527114077079,
3919 ]))
3920 .unwrap(),
3921 ),
3922 ell_vv: Fq2::new(
3923 Fq::new(U256([
3924 50744916563901235043837175537752247974,
3925 10172930551818555335663216915059687204,
3926 ]))
3927 .unwrap(),
3928 Fq::new(U256([
3929 130434124352272975884189586048532260990,
3930 23515228462564504103971218058319726320,
3931 ]))
3932 .unwrap(),
3933 ),
3934 },
3935 EllCoeffs {
3936 ell_0: Fq2::new(
3937 Fq::new(U256([
3938 315580665939248091007437797584737352150,
3939 29708290546079112870849940807626622733,
3940 ]))
3941 .unwrap(),
3942 Fq::new(U256([
3943 74442409874403535705044740324158268395,
3944 1505199293980260993350511103843027993,
3945 ]))
3946 .unwrap(),
3947 ),
3948 ell_vw: Fq2::new(
3949 Fq::new(U256([
3950 250928935731107472086814134230515792409,
3951 5910959187805062997477270179924851551,
3952 ]))
3953 .unwrap(),
3954 Fq::new(U256([
3955 280398933657384735588696583124789483429,
3956 54783439113329460653893087793006061735,
3957 ]))
3958 .unwrap(),
3959 ),
3960 ell_vv: Fq2::new(
3961 Fq::new(U256([
3962 251724005393716093632013371894721049773,
3963 58848512269437108583523559065211202801,
3964 ]))
3965 .unwrap(),
3966 Fq::new(U256([
3967 31822195116686689031909059702809975955,
3968 24789755710735999475756589726034740758,
3969 ]))
3970 .unwrap(),
3971 ),
3972 },
3973 EllCoeffs {
3974 ell_0: Fq2::new(
3975 Fq::new(U256([
3976 311444467767445140793669110935330311306,
3977 49680899512402416135008064018078765713,
3978 ]))
3979 .unwrap(),
3980 Fq::new(U256([
3981 260075513883026034919987130520464438138,
3982 71886459212490540714376620236740887,
3983 ]))
3984 .unwrap(),
3985 ),
3986 ell_vw: Fq2::new(
3987 Fq::new(U256([
3988 218811104197169142519581806122315915406,
3989 2003975639040616906277810278389252752,
3990 ]))
3991 .unwrap(),
3992 Fq::new(U256([
3993 162449781759514417953768678035934414521,
3994 20826616094394726852079185751274539294,
3995 ]))
3996 .unwrap(),
3997 ),
3998 ell_vv: Fq2::new(
3999 Fq::new(U256([
4000 50122791277121629311774878848574398797,
4001 41715208027917549489096484827508261925,
4002 ]))
4003 .unwrap(),
4004 Fq::new(U256([
4005 61219715357759165032395798940008313361,
4006 55168729445645977375765036089053114792,
4007 ]))
4008 .unwrap(),
4009 ),
4010 },
4011 EllCoeffs {
4012 ell_0: Fq2::new(
4013 Fq::new(U256([
4014 79415664581913745231517567945561341244,
4015 19961313692291707660858657690356279927,
4016 ]))
4017 .unwrap(),
4018 Fq::new(U256([
4019 169697929611525566517558862344260578764,
4020 32844991405556424161021671060175948696,
4021 ]))
4022 .unwrap(),
4023 ),
4024 ell_vw: Fq2::new(
4025 Fq::new(U256([
4026 97951068758528710273694591785781637499,
4027 18749313896215455583118043227454839626,
4028 ]))
4029 .unwrap(),
4030 Fq::new(U256([
4031 86416223342992670848217929911878122430,
4032 45508713650090104780284816480988042321,
4033 ]))
4034 .unwrap(),
4035 ),
4036 ell_vv: Fq2::new(
4037 Fq::new(U256([
4038 205166366708889542887913296220698256110,
4039 64283667930878381361054417761490454821,
4040 ]))
4041 .unwrap(),
4042 Fq::new(U256([
4043 127337780289640176933683040648197123026,
4044 45189848010560984741741084451460237213,
4045 ]))
4046 .unwrap(),
4047 ),
4048 },
4049 EllCoeffs {
4050 ell_0: Fq2::new(
4051 Fq::new(U256([
4052 339284773562100413239152438122508204497,
4053 50631498218339719105248005011418978450,
4054 ]))
4055 .unwrap(),
4056 Fq::new(U256([
4057 33417073692493560040015373020490319634,
4058 35461627756915585142929292352046627148,
4059 ]))
4060 .unwrap(),
4061 ),
4062 ell_vw: Fq2::new(
4063 Fq::new(U256([
4064 65706590332479893819786959846945487398,
4065 49780412881756049082474794087182699607,
4066 ]))
4067 .unwrap(),
4068 Fq::new(U256([
4069 52838637386752308153448355705238086197,
4070 25418435995504719731730063829115376943,
4071 ]))
4072 .unwrap(),
4073 ),
4074 ell_vv: Fq2::new(
4075 Fq::new(U256([
4076 272342513391057040499052435082268704444,
4077 40734611488359738470851428580967866388,
4078 ]))
4079 .unwrap(),
4080 Fq::new(U256([
4081 195464905670800875597868841505577455579,
4082 4567343913211817054294335942572391310,
4083 ]))
4084 .unwrap(),
4085 ),
4086 },
4087 EllCoeffs {
4088 ell_0: Fq2::new(
4089 Fq::new(U256([
4090 116585277318795490267488822790585572050,
4091 60535270002127930300661104257194060095,
4092 ]))
4093 .unwrap(),
4094 Fq::new(U256([
4095 60938698090087736292473391678184666708,
4096 13034546647626058553077909902189865751,
4097 ]))
4098 .unwrap(),
4099 ),
4100 ell_vw: Fq2::new(
4101 Fq::new(U256([
4102 173096860849358760769153772521753734944,
4103 46051492674049147015395144791836438516,
4104 ]))
4105 .unwrap(),
4106 Fq::new(U256([
4107 217847244022302146556080020387033222160,
4108 3714600728561149832835084325311638745,
4109 ]))
4110 .unwrap(),
4111 ),
4112 ell_vv: Fq2::new(
4113 Fq::new(U256([
4114 86749998713441153819371623717671780463,
4115 22072421598347798931100735874660737662,
4116 ]))
4117 .unwrap(),
4118 Fq::new(U256([
4119 318879363093875678699747171034610586590,
4120 20824335590094416898946169150944599166,
4121 ]))
4122 .unwrap(),
4123 ),
4124 },
4125 EllCoeffs {
4126 ell_0: Fq2::new(
4127 Fq::new(U256([
4128 64488889092438538888826783837043953900,
4129 37184887689753051095864638902885179863,
4130 ]))
4131 .unwrap(),
4132 Fq::new(U256([
4133 30545663928156310707528798028105042841,
4134 35594636889744346303301050561815356233,
4135 ]))
4136 .unwrap(),
4137 ),
4138 ell_vw: Fq2::new(
4139 Fq::new(U256([
4140 25983064025798529721395241242693795182,
4141 8818840193887973907465639723423785685,
4142 ]))
4143 .unwrap(),
4144 Fq::new(U256([
4145 258083038864362618956338229292791076964,
4146 59924965332411444209484507096908691451,
4147 ]))
4148 .unwrap(),
4149 ),
4150 ell_vv: Fq2::new(
4151 Fq::new(U256([
4152 220038260912754873591576914680586914279,
4153 13066051346629987308799710602199271472,
4154 ]))
4155 .unwrap(),
4156 Fq::new(U256([
4157 145490690982645862542497983334649610263,
4158 61905193484912278316593689230425266660,
4159 ]))
4160 .unwrap(),
4161 ),
4162 },
4163 EllCoeffs {
4164 ell_0: Fq2::new(
4165 Fq::new(U256([
4166 91140715068468329987534450751429662322,
4167 19286363177619277557153390898202185703,
4168 ]))
4169 .unwrap(),
4170 Fq::new(U256([
4171 93820352751188715792914230189639637744,
4172 34108640942617057347076989500332659863,
4173 ]))
4174 .unwrap(),
4175 ),
4176 ell_vw: Fq2::new(
4177 Fq::new(U256([
4178 64028159517497609933876978072339213461,
4179 15242545675596643010631683990284567829,
4180 ]))
4181 .unwrap(),
4182 Fq::new(U256([
4183 196818140250582584748747602707707107768,
4184 19674391967426090834762688793787807910,
4185 ]))
4186 .unwrap(),
4187 ),
4188 ell_vv: Fq2::new(
4189 Fq::new(U256([
4190 240272916169613868056785616677104041776,
4191 43506134861603450917738367078393340621,
4192 ]))
4193 .unwrap(),
4194 Fq::new(U256([
4195 4195648020339163006604321850508278540,
4196 4672904647050343041579830671683109182,
4197 ]))
4198 .unwrap(),
4199 ),
4200 },
4201 EllCoeffs {
4202 ell_0: Fq2::new(
4203 Fq::new(U256([
4204 76224289879065773445423898190273853011,
4205 29552147447995384759425668183293749353,
4206 ]))
4207 .unwrap(),
4208 Fq::new(U256([
4209 131775855227043960655312514543203001277,
4210 11525949759137095338012468817574456927,
4211 ]))
4212 .unwrap(),
4213 ),
4214 ell_vw: Fq2::new(
4215 Fq::new(U256([
4216 24164999216876611682317527533876599098,
4217 1468136824339634997687523096410027135,
4218 ]))
4219 .unwrap(),
4220 Fq::new(U256([
4221 287955683679784091578386069448645460818,
4222 42392463637589581183769087503942163916,
4223 ]))
4224 .unwrap(),
4225 ),
4226 ell_vv: Fq2::new(
4227 Fq::new(U256([
4228 277415168387483520146499744266583303231,
4229 43682907322954483721445867111493680565,
4230 ]))
4231 .unwrap(),
4232 Fq::new(U256([
4233 231497467135626786731515493713118585761,
4234 56904388641135605566397108514408579757,
4235 ]))
4236 .unwrap(),
4237 ),
4238 },
4239 ]),
4240 };
4241
4242 assert!(expected_g2_p == g2_p);
4243 assert!(expected_g2_p.coeffs.len() == 87);
4244}
4245
4246pub fn pairing(p: &G1, q: &G2) -> Fq12 {
4247 match (p.to_affine(), q.to_affine()) {
4248 (None, _) | (_, None) => Fq12::one(),
4249 (Some(p), Some(q)) => q
4250 .precompute()
4251 .miller_loop(&p)
4252 .final_exponentiation()
4253 .expect("miller loop cannot produce zero"),
4254 }
4255}
4256
4257pub fn pairing_batch(ps: &[G1], qs: &[G2]) -> Fq12 {
4258 let mut p_affines: Vec<AffineG<G1Params>> = Vec::new();
4259 let mut q_precomputes: Vec<G2Precomp> = Vec::new();
4260 for (p, q) in ps.into_iter().zip(qs.into_iter()) {
4261 let p_affine = p.to_affine();
4262 let q_affine = q.to_affine();
4263 let exists = match (p_affine, q_affine) {
4264 (None, _) | (_, None) => false,
4265 (Some(_p_affine), Some(_q_affine)) => true,
4266 };
4267
4268 if exists {
4269 p_affines.push(p.to_affine().unwrap());
4270 q_precomputes.push(q.to_affine().unwrap().precompute());
4271 }
4272 }
4273 if q_precomputes.len() == 0 {
4274 return Fq12::one();
4275 }
4276 miller_loop_batch(&q_precomputes, &p_affines)
4277 .final_exponentiation()
4278 .expect("miller loop cannot produce zero")
4279}
4280
4281#[test]
4282fn test_reduced_pairing() {
4283 use crate::fields::Fq6;
4284
4285 let g1 = G1::one()
4286 * Fr::from_str(
4287 "18097487326282793650237947474982649264364522469319914492172746413872781676",
4288 )
4289 .unwrap();
4290 let g2 = G2::one()
4291 * Fr::from_str(
4292 "20390255904278144451778773028944684152769293537511418234311120800877067946",
4293 )
4294 .unwrap();
4295
4296 let gt = pairing(&g1, &g2);
4297
4298 let expected = Fq12::new(
4299 Fq6::new(
4300 Fq2::new(
4301 Fq::from_str(
4302 "7520311483001723614143802378045727372643587653754534704390832890681688842501",
4303 )
4304 .unwrap(),
4305 Fq::from_str(
4306 "20265650864814324826731498061022229653175757397078253377158157137251452249882",
4307 )
4308 .unwrap(),
4309 ),
4310 Fq2::new(
4311 Fq::from_str(
4312 "11942254371042183455193243679791334797733902728447312943687767053513298221130",
4313 )
4314 .unwrap(),
4315 Fq::from_str(
4316 "759657045325139626991751731924144629256296901790485373000297868065176843620",
4317 )
4318 .unwrap(),
4319 ),
4320 Fq2::new(
4321 Fq::from_str(
4322 "16045761475400271697821392803010234478356356448940805056528536884493606035236",
4323 )
4324 .unwrap(),
4325 Fq::from_str(
4326 "4715626119252431692316067698189337228571577552724976915822652894333558784086",
4327 )
4328 .unwrap(),
4329 ),
4330 ),
4331 Fq6::new(
4332 Fq2::new(
4333 Fq::from_str(
4334 "14901948363362882981706797068611719724999331551064314004234728272909570402962",
4335 )
4336 .unwrap(),
4337 Fq::from_str(
4338 "11093203747077241090565767003969726435272313921345853819385060670210834379103",
4339 )
4340 .unwrap(),
4341 ),
4342 Fq2::new(
4343 Fq::from_str(
4344 "17897835398184801202802503586172351707502775171934235751219763553166796820753",
4345 )
4346 .unwrap(),
4347 Fq::from_str(
4348 "1344517825169318161285758374052722008806261739116142912817807653057880346554",
4349 )
4350 .unwrap(),
4351 ),
4352 Fq2::new(
4353 Fq::from_str(
4354 "11123896897251094532909582772961906225000817992624500900708432321664085800838",
4355 )
4356 .unwrap(),
4357 Fq::from_str(
4358 "17453370448280081813275586256976217762629631160552329276585874071364454854650",
4359 )
4360 .unwrap(),
4361 ),
4362 ),
4363 );
4364
4365 assert_eq!(expected, gt);
4366}
4367
4368#[test]
4369fn predefined_pair() {
4370 let g1 = AffineG1::new(
4371 Fq::from_str("1").expect("Fq(1) should exist"),
4372 Fq::from_str("2").expect("Fq(2) should exist"),
4373 )
4374 .expect("Point (1,2) should exist in G1")
4375 .to_jacobian();
4376
4377 let g2 = AffineG2::new(
4378 Fq2::new(
4379 Fq::from_str("10857046999023057135944570762232829481370756359578518086990519993285655852781")
4380 .expect("a-coeff of g2 x generator is of the right order"),
4381 Fq::from_str("11559732032986387107991004021392285783925812861821192530917403151452391805634")
4382 .expect("b-coeff of g2 x generator is of the right order"),
4383 ),
4384 Fq2::new(
4385 Fq::from_str("8495653923123431417604973247489272438418190587263600148770280649306958101930")
4386 .expect("a-coeff of g2 y generator is of the right order"),
4387 Fq::from_str("4082367875863433681332203403145435568316851327593401208105741076214120093531")
4388 .expect("b-coeff of g2 y generator is of the right order"),
4389 ),
4390 ).expect("Point(11559732032986387107991004021392285783925812861821192530917403151452391805634 * i + 10857046999023057135944570762232829481370756359578518086990519993285655852781, 4082367875863433681332203403145435568316851327593401208105741076214120093531 * i + 8495653923123431417604973247489272438418190587263600148770280649306958101930) is a valid generator for G2")
4391 .to_jacobian();
4392
4393 let p = pairing(&g1, &g2);
4394
4395 let g1_vec: Vec<G1> = Vec::from([g1, g1]);
4396 let g2_vec: Vec<G2> = Vec::from([g2, g2]);
4397 let p2 = pairing_batch(&g1_vec, &g2_vec);
4398 assert!(!p2.is_zero());
4399 assert!(!p.is_zero());
4400}
4401
4402#[test]
4403fn test_batch_bilinearity_empty() {
4404 let p_vec: Vec<G1> = Vec::new();
4405 let q_vec: Vec<G2> = Vec::new();
4406 let r = pairing_batch(&p_vec, &q_vec);
4407 assert_eq!(r, Fq12::one());
4408}
4409
4410#[test]
4411fn test_batch_bilinearity_one() {
4412 use rand::{SeedableRng, rngs::StdRng};
4413 let seed = [
4414 0, 0, 0, 0, 0, 0, 64, 13, 0, 0, 0, 0, 0, 0, 176, 2, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 96, 7u8, ];
4419 let mut rng = StdRng::from_seed(seed);
4420 let p_vec: Vec<G1> = Vec::from([G1::random(&mut rng)]);
4421 let q_vec: Vec<G2> = Vec::from([G2::random(&mut rng)]);
4422 let s = Fr::random(&mut rng);
4423 let sp_vec: Vec<G1> = Vec::from([p_vec[0] * s]);
4424 let sq_vec: Vec<G2> = Vec::from([q_vec[0] * s]);
4425 let b = pairing_batch(&sp_vec, &q_vec);
4426 let c = pairing_batch(&p_vec, &sq_vec);
4427 assert_eq!(b, c);
4428}
4429
4430#[test]
4431fn test_batch_bilinearity_fifty() {
4432 use rand::{SeedableRng, rngs::StdRng};
4433 let seed = [
4434 0, 0, 0, 0, 0, 0, 64, 13, 0, 0, 0, 0, 0, 0, 176, 2, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 96, 7u8, ];
4439 let mut rng = StdRng::from_seed(seed);
4440
4441 let mut p_vec: Vec<G1> = Vec::new();
4442 let mut q_vec: Vec<G2> = Vec::new();
4443 let mut sp_vec: Vec<G1> = Vec::new();
4444 let mut sq_vec: Vec<G2> = Vec::new();
4445
4446 for _ in 0..50 {
4447 let p = G1::random(&mut rng);
4448 let q = G2::random(&mut rng);
4449 let s = Fr::random(&mut rng);
4450 let sp = p * s;
4451 let sq = q * s;
4452 sp_vec.push(sp);
4453 q_vec.push(q);
4454 sq_vec.push(sq);
4455 p_vec.push(p);
4456 }
4457 let b_batch = pairing_batch(&sp_vec, &q_vec);
4458 let c_batch = pairing_batch(&p_vec, &sq_vec);
4459 assert_eq!(b_batch, c_batch);
4460}
4461
4462#[test]
4463fn test_bilinearity() {
4464 use rand::{SeedableRng, rngs::StdRng};
4465 let seed = [
4466 0, 0, 0, 0, 0, 0, 64, 13, 0, 0, 0, 0, 0, 0, 176, 2, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 96, 7u8, ];
4471 let mut rng = StdRng::from_seed(seed);
4472
4473 for _ in 0..50 {
4474 let p = G1::random(&mut rng);
4475 let q = G2::random(&mut rng);
4476 let s = Fr::random(&mut rng);
4477 let sp = p * s;
4478 let sq = q * s;
4479
4480 let a = pairing(&p, &q).pow(s);
4481 let b = pairing(&sp, &q);
4482 let c = pairing(&p, &sq);
4483
4484 assert_eq!(a, b);
4485 assert_eq!(b, c);
4486
4487 let t = -Fr::one();
4488
4489 assert!(a != Fq12::one());
4490 assert_eq!((a.pow(t)) * a, Fq12::one());
4491 }
4492}
4493
4494#[test]
4495fn internals() {
4496 let test_p = G1::one();
4497
4498 let val = G1::new(test_p.x().clone(), test_p.y().clone(), test_p.z().clone());
4499
4500 let affine = val
4501 .to_affine()
4502 .expect("There should be affine coords for (0, 0)");
4503
4504 assert_eq!(affine.x(), &Fq::one());
4505}
4506
4507#[test]
4508fn affine_fail() {
4509 let res = AffineG1::new(Fq::one(), Fq::one());
4510 assert!(
4511 res.is_err(),
4512 "Affine initialization should fail because the point is not on curve"
4513 );
4514}
4515
4516#[test]
4517fn affine_ok() {
4518 let res = AffineG1::new(Fq::one(), G1Params::coeff_b());
4519 assert!(
4520 res.is_err(),
4521 "Affine initialization should be ok because the point is on the curve"
4522 );
4523}
4524
4525#[test]
4526fn test_y_at_point_at_infinity() {
4527 assert!(G1::zero().y == Fq::one());
4528 assert!((-G1::zero()).y == Fq::one());
4529
4530 assert!(G2::zero().y == Fq2::one());
4531 assert!((-G2::zero()).y == Fq2::one());
4532}