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