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