ark_ff/fields/models/
fp6_3over2.rs1use 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 const SQRT_PRECOMP: Option<SqrtPrecomputation<Fp6<Self>>> = None;
12
13 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
153impl<P: Fp6Config> CyclotomicMultSubgroup for Fp6<P> {}