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