2 *****************************************************************************
3 * @author This file is part of libsnark, developed by Clearmatics Ltd
4 * (originally developed by SCIPR Lab) and contributors
6 * @copyright MIT license (see LICENSE file)
7 *****************************************************************************/
9 #ifndef LIBSNARK_GADGETLIB1_GADGETS_FIELDS_FP6_3OVER2_GADGETS_TCC_
10 #define LIBSNARK_GADGETLIB1_GADGETS_FIELDS_FP6_3OVER2_GADGETS_TCC_
12 #include "libsnark/gadgetlib1/gadgets/fields/fp6_3over2_gadgets.hpp"
17 // Fp6_3over2_variable methods
19 template<typename Fp6T>
20 Fp6_3over2_variable<Fp6T>::Fp6_3over2_variable(
21 protoboard<FieldT> &pb, const std::string &annotation_prefix)
22 : gadget<FieldT>(pb, annotation_prefix)
23 , _c0(pb, FMT(annotation_prefix, " c0"))
24 , _c1(pb, FMT(annotation_prefix, " c1"))
25 , _c2(pb, FMT(annotation_prefix, " c2"))
29 template<typename Fp6T>
30 Fp6_3over2_variable<Fp6T>::Fp6_3over2_variable(
31 protoboard<FieldT> &pb,
32 const Fp6_3over2_variable<Fp6T> &el,
33 const std::string &annotation_prefix)
34 : gadget<FieldT>(pb, annotation_prefix)
41 template<typename Fp6T>
42 Fp6_3over2_variable<Fp6T>::Fp6_3over2_variable(
43 protoboard<FieldT> &pb,
45 const std::string &annotation_prefix)
46 : gadget<FieldT>(pb, annotation_prefix)
47 , _c0(pb, el.coeffs[0], FMT(annotation_prefix, " c0"))
48 , _c1(pb, el.coeffs[1], FMT(annotation_prefix, " c1"))
49 , _c2(pb, el.coeffs[2], FMT(annotation_prefix, " c2"))
53 template<typename Fp6T>
54 Fp6_3over2_variable<Fp6T>::Fp6_3over2_variable(
55 protoboard<FieldT> &pb,
56 const Fp2_variable<Fp2T> &c0,
57 const Fp2_variable<Fp2T> &c1,
58 const Fp2_variable<Fp2T> &c2,
59 const std::string &annotation_prefix)
60 : gadget<FieldT>(pb, annotation_prefix), _c0(c0), _c1(c1), _c2(c2)
64 template<typename Fp6T>
65 Fp6_3over2_variable<Fp6T> Fp6_3over2_variable<Fp6T>::operator*(
66 const FieldT &scalar) const
68 return Fp6_3over2_variable<Fp6T>(
73 FMT(this->annotation_prefix, " fp6_var*scalar"));
76 template<typename Fp6T>
77 Fp6_3over2_variable<Fp6T> Fp6_3over2_variable<Fp6T>::operator*(
78 const Fp2T &fp2_const) const
80 return Fp6_3over2_variable<Fp6T>(
85 FMT(this->annotation_prefix, " fp6_var*fp2_const"));
88 template<typename Fp6T>
89 Fp6_3over2_variable<Fp6T> Fp6_3over2_variable<Fp6T>::operator*(
90 const Fp6T &fp6_const) const
92 // c0 = a0*b0 + non_residue * (a1*b2 + a2*b1)
93 // c1 = a0*b1 + a1*b0 + non_residue * a2*b2
94 // c3 = a0*b2 + a1*b1 + a2*b0
95 return Fp6_3over2_variable<Fp6T>(
97 _c0 * fp6_const.coeffs[0] +
98 (_c1 * fp6_const.coeffs[2] + _c2 * fp6_const.coeffs[1]) *
100 _c0 * fp6_const.coeffs[1] + _c1 * fp6_const.coeffs[0] +
101 _c2 * fp6_const.coeffs[2] * Fp6T::non_residue,
102 _c0 * fp6_const.coeffs[2] + _c1 * fp6_const.coeffs[1] +
103 _c2 * fp6_const.coeffs[0],
104 FMT(this->annotation_prefix, " fp6_var*fp6_const"));
107 template<typename Fp6T>
108 Fp6_3over2_variable<Fp6T> Fp6_3over2_variable<Fp6T>::operator+(
109 const Fp6_3over2_variable<Fp6T> &other) const
111 return Fp6_3over2_variable<Fp6T>(
116 FMT(this->annotation_prefix.c_str(), " +other"));
119 template<typename Fp6T>
120 Fp6_3over2_variable<Fp6T> Fp6_3over2_variable<Fp6T>::operator-(
121 const Fp6_3over2_variable<Fp6T> &other) const
123 return Fp6_3over2_variable<Fp6T>(
128 FMT(this->annotation_prefix, " -other"));
131 template<typename Fp6T>
132 Fp6_3over2_variable<Fp6T> Fp6_3over2_variable<Fp6T>::operator-() const
134 return Fp6_3over2_variable<Fp6T>(
139 FMT(this->annotation_prefix, " fp6_negate"));
142 template<typename Fp6T>
143 Fp6_3over2_variable<Fp6T> Fp6_3over2_variable<Fp6T>::frobenius_map(
146 return Fp6_3over2_variable<Fp6T>(
148 _c0.frobenius_map(power),
149 _c1.frobenius_map(power) * Fp6T::Frobenius_coeffs_c1[power % 6],
150 _c2.frobenius_map(power) * Fp6T::Frobenius_coeffs_c2[power % 6],
151 FMT(this->annotation_prefix, " fp6_frobenius_map"));
154 template<typename Fp6T> void Fp6_3over2_variable<Fp6T>::evaluate() const
161 template<typename Fp6T>
162 void Fp6_3over2_variable<Fp6T>::generate_r1cs_witness(const Fp6T &el)
164 _c0.generate_r1cs_witness(el.coeffs[0]);
165 _c1.generate_r1cs_witness(el.coeffs[1]);
166 _c2.generate_r1cs_witness(el.coeffs[2]);
169 template<typename Fp6T> Fp6T Fp6_3over2_variable<Fp6T>::get_element() const
171 return Fp6T(_c0.get_element(), _c1.get_element(), _c2.get_element());
174 // Fp6_3over2_mul_gadget methods
176 template<typename Fp6T>
177 Fp6_3over2_mul_gadget<Fp6T>::Fp6_3over2_mul_gadget(
178 protoboard<FieldT> &pb,
179 const Fp6_3over2_variable<Fp6T> &A,
180 const Fp6_3over2_variable<Fp6T> &B,
181 const Fp6_3over2_variable<Fp6T> &result,
182 const std::string &annotation_prefix)
183 : gadget<FieldT>(pb, annotation_prefix)
191 Fp2_variable<Fp2T>(pb, FMT(annotation_prefix, " v1")),
192 FMT(annotation_prefix, " _compute_v1"))
197 Fp2_variable<Fp2T>(pb, FMT(annotation_prefix, " v2")),
198 FMT(annotation_prefix, " _compute_v2"))
199 , _compute_a1a2_times_b1b2(
203 Fp2_variable<Fp2T>(pb, FMT(annotation_prefix, " (a1+a2)*(b1+b2)")),
204 FMT(annotation_prefix, " _compute_a1a2_times_b1b2"))
205 // c0 = a0*b0 + non_residue*((a1 + a2)(b1 + b2) - a1*b1 - a2*b2)
210 _result._c0 - (_compute_a1a2_times_b1b2.result - _compute_v1.result -
211 _compute_v2.result) *
213 FMT(annotation_prefix, " _compute_v0"))
214 // c1 = (a0 + a1)(b0 + b1) - a0*b0 - a1*b1 + non_residue * a2*b2
215 , _compute_a0a1_times_b0b1(
219 _result._c1 + _compute_v0.result + _compute_v1.result -
220 _compute_v2.result * Fp6T::non_residue,
221 FMT(annotation_prefix, " _compute_a0a1_times_b0b1"))
222 // c2 = (a0 + a2)(b0 + b2) - a0*b0 - a2*b2 + a1*b1
223 , _compute_a0a2_times_b0b2(
227 _result._c2 + _compute_v0.result + _compute_v2.result -
229 FMT(annotation_prefix, " _compute_a0a2_times_b0b2"))
233 template<typename Fp6T>
234 void Fp6_3over2_mul_gadget<Fp6T>::generate_r1cs_constraints()
236 _compute_v1.generate_r1cs_constraints();
237 _compute_v2.generate_r1cs_constraints();
238 _compute_a1a2_times_b1b2.generate_r1cs_constraints();
239 _compute_v0.generate_r1cs_constraints();
240 _compute_a0a1_times_b0b1.generate_r1cs_constraints();
241 _compute_a0a2_times_b0b2.generate_r1cs_constraints();
244 template<typename Fp6T>
245 void Fp6_3over2_mul_gadget<Fp6T>::generate_r1cs_witness()
247 const Fp2T a0 = _A._c0.get_element();
248 const Fp2T a1 = _A._c1.get_element();
249 const Fp2T a2 = _A._c2.get_element();
250 const Fp2T b0 = _B._c0.get_element();
251 const Fp2T b1 = _B._c1.get_element();
252 const Fp2T b2 = _B._c2.get_element();
254 // c0 = v1 + non_residue*((a1 + a2)(b1 + b2) - v1 - v2)
255 _compute_v1.generate_r1cs_witness();
256 const Fp2T v1 = _compute_v1.result.get_element();
257 _compute_v2.generate_r1cs_witness();
258 const Fp2T v2 = _compute_v2.result.get_element();
259 _compute_a1a2_times_b1b2.A.evaluate();
260 _compute_a1a2_times_b1b2.B.evaluate();
261 _compute_a1a2_times_b1b2.generate_r1cs_witness();
262 const Fp2T a1a2_times_b1b2 = _compute_a1a2_times_b1b2.result.get_element();
263 const Fp2T v0 = a0 * b0;
264 _result._c0.generate_r1cs_witness(
265 v0 + Fp6T::mul_by_non_residue(a1a2_times_b1b2 - v1 - v2));
266 _compute_v0.generate_r1cs_witness();
268 // c1 = (a0 + a1)(b0 + b1) - v1 - v1 + non_residue * v2
269 const Fp2T a0a1_times_b0b1 = (a0 + a1) * (b0 + b1);
270 _result._c1.generate_r1cs_witness(
271 a0a1_times_b0b1 - v0 - v1 + Fp6T::mul_by_non_residue(v2));
272 _compute_a0a1_times_b0b1.A.evaluate();
273 _compute_a0a1_times_b0b1.B.evaluate();
274 _compute_a0a1_times_b0b1.generate_r1cs_witness();
276 // c2 = (a0 + a2)(b0 + b2) - v1 - v2 + v1
277 const Fp2T a0a2_times_b0b2 = (a0 + a2) * (b0 + b2);
278 _result._c2.generate_r1cs_witness(a0a2_times_b0b2 - v0 - v2 + v1);
279 _compute_a0a2_times_b0b2.A.evaluate();
280 _compute_a0a2_times_b0b2.B.evaluate();
281 _compute_a0a2_times_b0b2.generate_r1cs_witness();
284 } // namespace libsnark
286 #endif // LIBSNARK_GADGETLIB1_GADGETS_FIELDS_FP6_3OVER2_GADGETS_TCC_