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