1use core::marker::PhantomData;
10
11use crate::{
12    constants::{GATE_WIDTH, N_MUL_SELECTORS},
13    gates::Gate,
14};
15use ark_ec::twisted_edwards::TECurveConfig as Config;
16use ark_ff::PrimeField;
17use derive_where::derive_where;
18
19#[inline]
20fn edwards_coeff_d<P: Config>() -> P::BaseField {
21    P::COEFF_D
22}
23
24#[derive_where(Clone; P: Config)]
26pub struct EdwardsCurveEquationGate<P: Config> {
27    pub(crate) _phantom: PhantomData<P>,
28}
29
30impl<F, P> Gate<F> for EdwardsCurveEquationGate<P>
31where
32    F: PrimeField,
33    P: Config<BaseField = F>,
34{
35    fn name(&self) -> &'static str {
36        "Curve Equation Gate"
37    }
38    fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
39        [-P::COEFF_A, -F::one()]
43    }
44    fn q_c(&self) -> F {
45        F::one()
46    }
47    fn q_ecc(&self) -> F {
48        edwards_coeff_d::<P>()
49    }
50}
51
52#[derive_where(Clone; P: Config)]
54pub struct CurvePointXAdditionGate<P: Config> {
55    pub(crate) _phantom: PhantomData<P>,
56}
57
58impl<F, P> Gate<F> for CurvePointXAdditionGate<P>
59where
60    F: PrimeField,
61    P: Config<BaseField = F>,
62{
63    fn name(&self) -> &'static str {
64        "Point Addition X-coordinate Gate"
65    }
66    fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
67        [F::one(), F::one()]
68    }
69    fn q_o(&self) -> F {
70        F::one()
71    }
72    fn q_ecc(&self) -> F {
73        let d: F = edwards_coeff_d::<P>();
74        -d
75    }
76}
77
78#[derive_where(Clone; P: Config)]
80pub struct CurvePointYAdditionGate<P: Config> {
81    pub(crate) _phantom: PhantomData<P>,
82}
83
84impl<F, P> Gate<F> for CurvePointYAdditionGate<P>
85where
86    F: PrimeField,
87    P: Config<BaseField = F>,
88{
89    fn name(&self) -> &'static str {
90        "Point Addition Y-coordinate Gate"
91    }
92    fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
93        [-P::COEFF_A, F::one()]
94    }
95    fn q_o(&self) -> F {
96        F::one()
97    }
98    fn q_ecc(&self) -> F {
99        edwards_coeff_d::<P>()
100    }
101}
102
103#[derive(Clone)]
107pub struct QuaternaryPointSelectXGate<F: PrimeField> {
108    pub(crate) x1: F,
109    pub(crate) x2: F,
110    pub(crate) x3: F,
111}
112
113impl<F> Gate<F> for QuaternaryPointSelectXGate<F>
114where
115    F: PrimeField,
116{
117    fn name(&self) -> &'static str {
118        "4-ary Point Selection X-coordinate Gate"
119    }
120    fn q_lc(&self) -> [F; GATE_WIDTH] {
121        [self.x1, self.x2, F::zero(), F::zero()]
122    }
123    fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
124        [self.x3 - self.x2 - self.x1, F::zero()]
125    }
126    fn q_o(&self) -> F {
127        F::one()
128    }
129}
130
131#[derive(Clone)]
135pub struct QuaternaryPointSelectYGate<F: PrimeField> {
136    pub(crate) y1: F,
137    pub(crate) y2: F,
138    pub(crate) y3: F,
139}
140
141impl<F> Gate<F> for QuaternaryPointSelectYGate<F>
142where
143    F: PrimeField,
144{
145    fn name(&self) -> &'static str {
146        "4-ary Point Selection Y-coordinate Gate"
147    }
148    fn q_lc(&self) -> [F; GATE_WIDTH] {
149        [self.y1 - F::one(), self.y2 - F::one(), F::zero(), F::zero()]
150    }
151    fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
152        [self.y3 - self.y2 - self.y1 + F::one(), F::zero()]
153    }
154    fn q_c(&self) -> F {
155        F::one()
156    }
157    fn q_o(&self) -> F {
158        F::one()
159    }
160}