witnet_bn/groups/
mod.rs

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