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