Skip to main content

ark_ff/fields/models/
fp6_2over3.rs

1use super::quadratic_extension::{QuadExtConfig, QuadExtField};
2use crate::{
3    fields::{Fp3, Fp3Config},
4    CyclotomicMultSubgroup, Zero,
5};
6use core::{marker::PhantomData, ops::Not};
7
8pub trait Fp6Config: 'static + Send + Sync {
9    type Fp3Config: Fp3Config;
10
11    const NONRESIDUE: Fp3<Self::Fp3Config>;
12
13    /// Coefficients for the Frobenius automorphism.
14    const FROBENIUS_COEFF_FP6_C1: &[<Self::Fp3Config as Fp3Config>::Fp];
15
16    #[inline(always)]
17    fn mul_fp3_by_nonresidue_in_place(fe: &mut Fp3<Self::Fp3Config>) -> &mut Fp3<Self::Fp3Config> {
18        let old_c1 = fe.c1;
19        fe.c1 = fe.c0;
20        fe.c0 = fe.c2;
21        <Self::Fp3Config as Fp3Config>::mul_fp_by_nonresidue_in_place(&mut fe.c0);
22        fe.c2 = old_c1;
23        fe
24    }
25}
26
27pub struct Fp6ConfigWrapper<P: Fp6Config>(PhantomData<P>);
28
29impl<P: Fp6Config> QuadExtConfig for Fp6ConfigWrapper<P> {
30    type BasePrimeField = <P::Fp3Config as Fp3Config>::Fp;
31    type BaseField = Fp3<P::Fp3Config>;
32    type FrobCoeff = Self::BasePrimeField;
33
34    const DEGREE_OVER_BASE_PRIME_FIELD: usize = 6;
35
36    const NONRESIDUE: Self::BaseField = P::NONRESIDUE;
37
38    const FROBENIUS_COEFF_C1: &[Self::FrobCoeff] = P::FROBENIUS_COEFF_FP6_C1;
39
40    #[inline(always)]
41    fn mul_base_field_by_nonresidue_in_place(fe: &mut Self::BaseField) -> &mut Self::BaseField {
42        P::mul_fp3_by_nonresidue_in_place(fe);
43        fe
44    }
45
46    fn mul_base_field_by_frob_coeff(fe: &mut Self::BaseField, power: usize) {
47        fe.mul_assign_by_fp(&Self::FROBENIUS_COEFF_C1[power % Self::DEGREE_OVER_BASE_PRIME_FIELD]);
48    }
49}
50
51pub type Fp6<P> = QuadExtField<Fp6ConfigWrapper<P>>;
52
53impl<P: Fp6Config> Fp6<P> {
54    pub fn mul_by_034(
55        &mut self,
56        c0: &<P::Fp3Config as Fp3Config>::Fp,
57        c3: &<P::Fp3Config as Fp3Config>::Fp,
58        c4: &<P::Fp3Config as Fp3Config>::Fp,
59    ) {
60        let z0 = self.c0.c0;
61        let z1 = self.c0.c1;
62        let z2 = self.c0.c2;
63        let z3 = self.c1.c0;
64        let z4 = self.c1.c1;
65        let z5 = self.c1.c2;
66
67        let x0 = *c0;
68        let x3 = *c3;
69        let x4 = *c4;
70
71        let mut tmp1 = x3;
72        tmp1 *= &<P::Fp3Config as Fp3Config>::NONRESIDUE;
73        let mut tmp2 = x4;
74        tmp2 *= &<P::Fp3Config as Fp3Config>::NONRESIDUE;
75
76        self.c0.c0 = x0 * &z0 + &(tmp1 * &z5) + &(tmp2 * &z4);
77        self.c0.c1 = x0 * &z1 + &(x3 * &z3) + &(tmp2 * &z5);
78        self.c0.c2 = x0 * &z2 + &(x3 * &z4) + &(x4 * &z3);
79        self.c1.c0 = x0 * &z3 + &(x3 * &z0) + &(tmp2 * &z2);
80        self.c1.c1 = x0 * &z4 + &(x3 * &z1) + &(x4 * &z0);
81        self.c1.c2 = x0 * &z5 + &(x3 * &z2) + &(x4 * &z1);
82    }
83
84    pub fn mul_by_014(
85        &mut self,
86        c0: &<P::Fp3Config as Fp3Config>::Fp,
87        c1: &<P::Fp3Config as Fp3Config>::Fp,
88        c4: &<P::Fp3Config as Fp3Config>::Fp,
89    ) {
90        let z0 = self.c0.c0;
91        let z1 = self.c0.c1;
92        let z2 = self.c0.c2;
93        let z3 = self.c1.c0;
94        let z4 = self.c1.c1;
95        let z5 = self.c1.c2;
96
97        let x0 = *c0;
98        let x1 = *c1;
99        let x4 = *c4;
100
101        let mut tmp1 = x1;
102        tmp1 *= &<P::Fp3Config as Fp3Config>::NONRESIDUE;
103        let mut tmp2 = x4;
104        tmp2 *= &<P::Fp3Config as Fp3Config>::NONRESIDUE;
105
106        self.c0.c0 = x0 * &z0 + &(tmp1 * &z2) + &(tmp2 * &z4);
107        self.c0.c1 = x0 * &z1 + &(x1 * &z0) + &(tmp2 * &z5);
108        self.c0.c2 = x0 * &z2 + &(x1 * &z1) + &(x4 * &z3);
109        self.c1.c0 = x0 * &z3 + &(tmp1 * &z5) + &(tmp2 * &z2);
110        self.c1.c1 = x0 * &z4 + &(x1 * &z3) + &(x4 * &z0);
111        self.c1.c2 = x0 * &z5 + &(x1 * &z4) + &(x4 * &z1);
112    }
113}
114
115impl<P: Fp6Config> CyclotomicMultSubgroup for Fp6<P> {
116    const INVERSE_IS_FAST: bool = true;
117    fn cyclotomic_inverse_in_place(&mut self) -> Option<&mut Self> {
118        self.is_zero().not().then(|| {
119            self.conjugate_in_place();
120            self
121        })
122    }
123}