ark_ff/fields/models/
fp6_3over2.rs

1use super::cubic_extension::*;
2use crate::fields::*;
3use core::marker::PhantomData;
4
5pub trait Fp6Config: 'static + Send + Sync + Copy {
6    type Fp2Config: Fp2Config;
7
8    const NONRESIDUE: Fp2<Self::Fp2Config>;
9
10    /// Determines the algorithm for computing square roots.
11    const SQRT_PRECOMP: Option<SqrtPrecomputation<Fp6<Self>>> = None;
12
13    /// Coefficients for the Frobenius automorphism.
14    const FROBENIUS_COEFF_FP6_C1: &'static [Fp2<Self::Fp2Config>];
15    const FROBENIUS_COEFF_FP6_C2: &'static [Fp2<Self::Fp2Config>];
16
17    #[inline(always)]
18    fn mul_fp2_by_nonresidue_in_place(fe: &mut Fp2<Self::Fp2Config>) -> &mut Fp2<Self::Fp2Config> {
19        *fe *= &Self::NONRESIDUE;
20        fe
21    }
22    #[inline(always)]
23    fn mul_fp2_by_nonresidue(mut fe: Fp2<Self::Fp2Config>) -> Fp2<Self::Fp2Config> {
24        Self::mul_fp2_by_nonresidue_in_place(&mut fe);
25        fe
26    }
27}
28
29pub struct Fp6ConfigWrapper<P: Fp6Config>(PhantomData<P>);
30
31impl<P: Fp6Config> CubicExtConfig for Fp6ConfigWrapper<P> {
32    type BasePrimeField = <P::Fp2Config as Fp2Config>::Fp;
33    type BaseField = Fp2<P::Fp2Config>;
34    type FrobCoeff = Fp2<P::Fp2Config>;
35
36    const SQRT_PRECOMP: Option<SqrtPrecomputation<CubicExtField<Self>>> = P::SQRT_PRECOMP;
37
38    const DEGREE_OVER_BASE_PRIME_FIELD: usize = 6;
39
40    const NONRESIDUE: Self::BaseField = P::NONRESIDUE;
41
42    const FROBENIUS_COEFF_C1: &'static [Self::FrobCoeff] = P::FROBENIUS_COEFF_FP6_C1;
43    const FROBENIUS_COEFF_C2: &'static [Self::FrobCoeff] = P::FROBENIUS_COEFF_FP6_C2;
44
45    #[inline(always)]
46    fn mul_base_field_by_nonresidue_in_place(fe: &mut Self::BaseField) -> &mut Self::BaseField {
47        P::mul_fp2_by_nonresidue_in_place(fe)
48    }
49
50    fn mul_base_field_by_frob_coeff(
51        c1: &mut Self::BaseField,
52        c2: &mut Self::BaseField,
53        power: usize,
54    ) {
55        *c1 *= &Self::FROBENIUS_COEFF_C1[power % Self::DEGREE_OVER_BASE_PRIME_FIELD];
56        *c2 *= &Self::FROBENIUS_COEFF_C2[power % Self::DEGREE_OVER_BASE_PRIME_FIELD];
57    }
58}
59
60pub type Fp6<P> = CubicExtField<Fp6ConfigWrapper<P>>;
61
62impl<P: Fp6Config> Fp6<P> {
63    pub fn mul_assign_by_fp2(&mut self, other: Fp2<P::Fp2Config>) {
64        self.c0 *= &other;
65        self.c1 *= &other;
66        self.c2 *= &other;
67    }
68
69    pub fn mul_by_fp(&mut self, element: &<P::Fp2Config as Fp2Config>::Fp) {
70        self.c0.mul_assign_by_fp(element);
71        self.c1.mul_assign_by_fp(element);
72        self.c2.mul_assign_by_fp(element);
73    }
74
75    pub fn mul_by_fp2(&mut self, element: &Fp2<P::Fp2Config>) {
76        self.c0.mul_assign(element);
77        self.c1.mul_assign(element);
78        self.c2.mul_assign(element);
79    }
80
81    pub fn mul_by_1(&mut self, c1: &Fp2<P::Fp2Config>) {
82        let mut b_b = self.c1;
83        b_b.mul_assign(c1);
84
85        let mut t1 = *c1;
86        {
87            let mut tmp = self.c1;
88            tmp.add_assign(&self.c2);
89
90            t1.mul_assign(&tmp);
91            t1.sub_assign(&b_b);
92            P::mul_fp2_by_nonresidue_in_place(&mut t1);
93        }
94
95        let mut t2 = *c1;
96        {
97            let mut tmp = self.c0;
98            tmp.add_assign(&self.c1);
99
100            t2.mul_assign(&tmp);
101            t2.sub_assign(&b_b);
102        }
103
104        self.c0 = t1;
105        self.c1 = t2;
106        self.c2 = b_b;
107    }
108
109    pub fn mul_by_01(&mut self, c0: &Fp2<P::Fp2Config>, c1: &Fp2<P::Fp2Config>) {
110        let mut a_a = self.c0;
111        let mut b_b = self.c1;
112        a_a.mul_assign(c0);
113        b_b.mul_assign(c1);
114
115        let mut t1 = *c1;
116        {
117            let mut tmp = self.c1;
118            tmp.add_assign(&self.c2);
119
120            t1.mul_assign(&tmp);
121            t1.sub_assign(&b_b);
122            P::mul_fp2_by_nonresidue_in_place(&mut t1);
123            t1.add_assign(&a_a);
124        }
125
126        let mut t3 = *c0;
127        {
128            let mut tmp = self.c0;
129            tmp.add_assign(&self.c2);
130
131            t3.mul_assign(&tmp);
132            t3.sub_assign(&a_a);
133            t3.add_assign(&b_b);
134        }
135
136        let mut t2 = *c0;
137        t2.add_assign(c1);
138        {
139            let mut tmp = self.c0;
140            tmp.add_assign(&self.c1);
141
142            t2.mul_assign(&tmp);
143            t2.sub_assign(&a_a);
144            t2.sub_assign(&b_b);
145        }
146
147        self.c0 = t1;
148        self.c1 = t2;
149        self.c2 = t3;
150    }
151}
152
153// We just use the default algorithms; there don't seem to be any faster ones.
154impl<P: Fp6Config> CyclotomicMultSubgroup for Fp6<P> {}