ark_ec/models/mnt4/
g2.rs

1use ark_std::ops::Neg;
2
3use crate::{
4    mnt4::MNT4Config,
5    models::mnt4::MNT4,
6    short_weierstrass::{Affine, Projective},
7    AffineRepr, CurveGroup,
8};
9use ark_ff::fields::{Field, Fp2};
10use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
11use ark_std::{vec, vec::*};
12use educe::Educe;
13use num_traits::One;
14
15pub type G2Affine<P> = Affine<<P as MNT4Config>::G2Config>;
16pub type G2Projective<P> = Projective<<P as MNT4Config>::G2Config>;
17
18#[derive(Educe, CanonicalSerialize, CanonicalDeserialize)]
19#[educe(Clone, Debug, PartialEq, Eq)]
20pub struct G2Prepared<P: MNT4Config> {
21    pub x: Fp2<P::Fp2Config>,
22    pub y: Fp2<P::Fp2Config>,
23    pub x_over_twist: Fp2<P::Fp2Config>,
24    pub y_over_twist: Fp2<P::Fp2Config>,
25    pub double_coefficients: Vec<AteDoubleCoefficients<P>>,
26    pub addition_coefficients: Vec<AteAdditionCoefficients<P>>,
27}
28
29impl<P: MNT4Config> Default for G2Prepared<P> {
30    fn default() -> Self {
31        Self::from(G2Affine::<P>::generator())
32    }
33}
34
35impl<P: MNT4Config> From<G2Affine<P>> for G2Prepared<P> {
36    fn from(g: G2Affine<P>) -> Self {
37        let twist_inv = P::TWIST.inverse().unwrap();
38
39        let mut g_prep = G2Prepared {
40            x: g.x,
41            y: g.y,
42            x_over_twist: g.x * &twist_inv,
43            y_over_twist: g.y * &twist_inv,
44            double_coefficients: vec![],
45            addition_coefficients: vec![],
46        };
47
48        let mut r = G2ProjectiveExtended {
49            x: g.x,
50            y: g.y,
51            z: <Fp2<P::Fp2Config>>::one(),
52            t: <Fp2<P::Fp2Config>>::one(),
53        };
54
55        let neg_g = g.neg();
56        for bit in P::ATE_LOOP_COUNT.iter().skip(1) {
57            let (r2, coeff) = MNT4::<P>::doubling_for_flipped_miller_loop(&r);
58            g_prep.double_coefficients.push(coeff);
59            r = r2;
60
61            let (r_temp, add_coeff) = match bit {
62                1 => MNT4::<P>::mixed_addition_for_flipped_miller_loop(&g.x, &g.y, &r),
63                -1 => MNT4::<P>::mixed_addition_for_flipped_miller_loop(&neg_g.x, &neg_g.y, &r),
64                0 => continue,
65                _ => unreachable!(),
66            };
67            g_prep.addition_coefficients.push(add_coeff);
68            r = r_temp;
69        }
70
71        if P::ATE_IS_LOOP_COUNT_NEG {
72            let rz_inv = r.z.inverse().unwrap();
73            let rz2_inv = rz_inv.square();
74            let rz3_inv = rz_inv * &rz2_inv;
75
76            let minus_r_affine_x = r.x * &rz2_inv;
77            let minus_r_affine_y = -r.y * &rz3_inv;
78
79            let add_result = MNT4::<P>::mixed_addition_for_flipped_miller_loop(
80                &minus_r_affine_x,
81                &minus_r_affine_y,
82                &r,
83            );
84            g_prep.addition_coefficients.push(add_result.1);
85        }
86
87        g_prep
88    }
89}
90
91impl<'a, P: MNT4Config> From<&'a G2Affine<P>> for G2Prepared<P> {
92    fn from(g2: &'a G2Affine<P>) -> Self {
93        (*g2).into()
94    }
95}
96
97impl<P: MNT4Config> From<G2Projective<P>> for G2Prepared<P> {
98    fn from(g2: G2Projective<P>) -> Self {
99        g2.into_affine().into()
100    }
101}
102impl<'a, P: MNT4Config> From<&'a G2Projective<P>> for G2Prepared<P> {
103    fn from(g2: &'a G2Projective<P>) -> Self {
104        (*g2).into()
105    }
106}
107
108pub struct G2ProjectiveExtended<P: MNT4Config> {
109    pub x: Fp2<P::Fp2Config>,
110    pub y: Fp2<P::Fp2Config>,
111    pub z: Fp2<P::Fp2Config>,
112    pub t: Fp2<P::Fp2Config>,
113}
114
115#[derive(Educe, CanonicalSerialize, CanonicalDeserialize)]
116#[educe(Clone, Debug, PartialEq, Eq)]
117pub struct AteDoubleCoefficients<P: MNT4Config> {
118    pub c_h: Fp2<P::Fp2Config>,
119    pub c_4c: Fp2<P::Fp2Config>,
120    pub c_j: Fp2<P::Fp2Config>,
121    pub c_l: Fp2<P::Fp2Config>,
122}
123
124#[derive(Educe, CanonicalSerialize, CanonicalDeserialize)]
125#[educe(Clone, Debug, PartialEq, Eq)]
126pub struct AteAdditionCoefficients<P: MNT4Config> {
127    pub c_l1: Fp2<P::Fp2Config>,
128    pub c_rz: Fp2<P::Fp2Config>,
129}