ark_ff/fields/models/
fp6_2over3.rs

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