zeropool_bn/groups/
mod.rs

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
16// This is the NAF version of ate_loop_count. Entries are all mod 4, so 3 = -1
17// n.b. ate_loop_count = 0x19d797039be763ba8
18//                     = 11001110101111001011100000011100110111110011101100011101110101000
19//       (naf version) = 11010003030003010300300000100301003000030100030300100030030101000
20// We skip the first element (1) as we would need to skip over it in the main loop
21const 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    // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl
430    fn add(mut self, other: AffineG<P>) -> Self::Output {
431        if self.is_zero() {
432            return other.to_jacobian();
433        }
434
435        // Z1Z1 = Z1^2
436        let z1z1 = self.z.squared();
437
438        // U2 = X2*Z1Z1
439        let u2 = other.x * z1z1;
440
441        // S2 = Y2*Z1*Z1Z1
442        let s2 = other.y * self.z * z1z1;
443
444        if self.x == u2 && self.y == s2 {
445            // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#mdbl-2007-bl
446            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            // H = U2-X1
458            let h = u2 - self.x;
459
460            // HH = H^2
461            let hh = h.squared();
462
463            // I = 4*HH
464            let i = field_double(field_double(hh));
465
466            // J = H*I
467            let j = h * i;
468
469            // r = 2*(S2-Y1)
470            let r = field_double(s2 - self.y);
471
472            // V = X1*I
473            let v = self.x * i;
474
475            // X3 = r^2 - J - 2*V
476            self.x = r.squared() - j - field_double(v);
477
478            // Y3 = r*(V-X3)-2*Y1*J
479            self.y = r * (v - self.x) - field_double(self.y * j);
480
481            // Z3 = (Z1+H)^2-Z1Z1-HH
482            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, // 103245
4553        0, 0, 0, 0, 0, 0, 176, 2, // 191922
4554        0, 0, 0, 0, 0, 0, 0, 13, // 1293
4555        0, 0, 0, 0, 0, 0, 96, 7u8, // 192103
4556    ];
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, // 103245
4573        0, 0, 0, 0, 0, 0, 176, 2, // 191922
4574        0, 0, 0, 0, 0, 0, 0, 13, // 1293
4575        0, 0, 0, 0, 0, 0, 96, 7u8, // 192103
4576    ];
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, // 103245
4604        0, 0, 0, 0, 0, 0, 176, 2, // 191922
4605        0, 0, 0, 0, 0, 0, 0, 13, // 1293
4606        0, 0, 0, 0, 0, 0, 96, 7u8, // 192103
4607    ];
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, // 103245
4636        0, 0, 0, 0, 0, 0, 176, 2, // 191922
4637        0, 0, 0, 0, 0, 0, 0, 13, // 1293
4638        0, 0, 0, 0, 0, 0, 96, 7u8, // 192103
4639    ];
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}