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
use super::quadratic_extension::*;
use core::marker::PhantomData;
use crate::fields::{Fp2, Fp2Parameters};
pub trait Fp4Parameters: 'static + Send + Sync {
type Fp2Params: Fp2Parameters;
const NONRESIDUE: Fp2<Self::Fp2Params>;
const FROBENIUS_COEFF_FP4_C1: &'static [<Self::Fp2Params as Fp2Parameters>::Fp];
#[inline(always)]
fn mul_fp2_by_nonresidue(fe: &Fp2<Self::Fp2Params>) -> Fp2<Self::Fp2Params> {
Fp2::new(
<Self::Fp2Params as Fp2Parameters>::NONRESIDUE * &fe.c1,
fe.c0,
)
}
}
pub struct Fp4ParamsWrapper<P: Fp4Parameters>(PhantomData<P>);
impl<P: Fp4Parameters> QuadExtParameters for Fp4ParamsWrapper<P> {
type BasePrimeField = <P::Fp2Params as Fp2Parameters>::Fp;
type BaseField = Fp2<P::Fp2Params>;
type FrobCoeff = Self::BasePrimeField;
const DEGREE_OVER_BASE_PRIME_FIELD: usize = 4;
const NONRESIDUE: Self::BaseField = P::NONRESIDUE;
const FROBENIUS_COEFF_C1: &'static [Self::FrobCoeff] = P::FROBENIUS_COEFF_FP4_C1;
#[inline(always)]
fn mul_base_field_by_nonresidue(fe: &Self::BaseField) -> Self::BaseField {
P::mul_fp2_by_nonresidue(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 Fp4<P> = QuadExtField<Fp4ParamsWrapper<P>>;
impl<P: Fp4Parameters> Fp4<P> {
pub fn mul_by_fp(&mut self, element: &<P::Fp2Params as Fp2Parameters>::Fp) {
self.c0.mul_assign_by_fp(element);
self.c1.mul_assign_by_fp(element);
}
pub fn mul_by_fp2(&mut self, element: &Fp2<P::Fp2Params>) {
self.c0 *= element;
self.c1 *= element;
}
}