arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/r1cs-std/src/fields/fp6_3over2.rs
r1cs-std/src/fields/fp6_3over2.rsRaw
 1use crate::fields::{cubic_extension::*, fp2::*};
 2use algebra::fields::{fp6_3over2::*, CubicExtParameters, Fp2};
 3use core::ops::MulAssign;
 4use r1cs_core::SynthesisError;
 5
 6/// A sextic extension field constructed as the tower of a
 7/// cubic extension over a quadratic extension field.
 8/// This is the R1CS equivalent of `algebra_core::fp6_3over3::Fp6<P>`.
 9pub type Fp6Var<P> = CubicExtVar<Fp2Var<<P as Fp6Parameters>::Fp2Params>, Fp6ParamsWrapper<P>>;
10
11impl<P: Fp6Parameters> CubicExtVarParams<Fp2Var<P::Fp2Params>> for Fp6ParamsWrapper<P> {
12    fn mul_base_field_vars_by_frob_coeff(
13        c1: &mut Fp2Var<P::Fp2Params>,
14        c2: &mut Fp2Var<P::Fp2Params>,
15        power: usize,
16    ) {
17        *c1 *= Self::FROBENIUS_COEFF_C1[power % Self::DEGREE_OVER_BASE_PRIME_FIELD];
18        *c2 *= Self::FROBENIUS_COEFF_C2[power % Self::DEGREE_OVER_BASE_PRIME_FIELD];
19    }
20}
21
22impl<P: Fp6Parameters> Fp6Var<P> {
23    /// Multiplies `self` by a sparse element which has `c0 == c2 == zero`.
24    pub fn mul_by_0_c1_0(&self, c1: &Fp2Var<P::Fp2Params>) -> Result<Self, SynthesisError> {
25        // Karatsuba multiplication
26        // v0 = a0 * b0 = 0
27
28        // v1 = a1 * b1
29        let v1 = &self.c1 * c1;
30
31        // v2 = a2 * b2 = 0
32
33        let a1_plus_a2 = &self.c1 + &self.c2;
34        let b1_plus_b2 = c1.clone();
35
36        let a0_plus_a1 = &self.c0 + &self.c1;
37
38        // c0 = (NONRESIDUE * ((a1 + a2)*(b1 + b2) - v1 - v2)) + v0
39        //    = NONRESIDUE * ((a1 + a2) * b1 - v1)
40        let c0 = &(a1_plus_a2 * &b1_plus_b2 - &v1) * P::NONRESIDUE;
41
42        // c1 = (a0 + a1) * (b0 + b1) - v0 - v1 + NONRESIDUE * v2
43        //    = (a0 + a1) * b1 - v1
44        let c1 = a0_plus_a1 * c1 - &v1;
45        // c2 = (a0 + a2) * (b0 + b2) - v0 - v2 + v1
46        //    = v1
47        let c2 = v1;
48        Ok(Self::new(c0, c1, c2))
49    }
50
51    /// Multiplies `self` by a sparse element which has `c2 == zero`.
52    pub fn mul_by_c0_c1_0(
53        &self,
54        c0: &Fp2Var<P::Fp2Params>,
55        c1: &Fp2Var<P::Fp2Params>,
56    ) -> Result<Self, SynthesisError> {
57        let v0 = &self.c0 * c0;
58        let v1 = &self.c1 * c1;
59        // v2 = 0.
60
61        let a1_plus_a2 = &self.c1 + &self.c2;
62        let a0_plus_a1 = &self.c0 + &self.c1;
63        let a0_plus_a2 = &self.c0 + &self.c2;
64
65        let b1_plus_b2 = c1.clone();
66        let b0_plus_b1 = c0 + c1;
67        let b0_plus_b2 = c0.clone();
68
69        let c0 = (&a1_plus_a2 * &b1_plus_b2 - &v1) * P::NONRESIDUE + &v0;
70
71        let c1 = a0_plus_a1 * &b0_plus_b1 - &v0 - &v1;
72
73        let c2 = a0_plus_a2 * &b0_plus_b2 - &v0 + &v1;
74
75        Ok(Self::new(c0, c1, c2))
76    }
77}
78
79impl<P: Fp6Parameters> MulAssign<Fp2<P::Fp2Params>> for Fp6Var<P> {
80    fn mul_assign(&mut self, other: Fp2<P::Fp2Params>) {
81        self.c0 *= other;
82        self.c1 *= other;
83        self.c2 *= other;
84    }
85}