2 *****************************************************************************
3 Implementation of arithmetic in the finite field F[((p^2)^3)^2].
4 *****************************************************************************
5 * @author This file is part of libsnark, developed by SCIPR Lab
6 * and contributors (see AUTHORS).
7 * @copyright MIT license (see LICENSE file)
8 *****************************************************************************/
10 #ifndef FP12_2OVER3OVER2_TCC_
11 #define FP12_2OVER3OVER2_TCC_
15 template<mp_size_t n, const bigint<n>& modulus>
16 Fp6_3over2_model<n, modulus> Fp12_2over3over2_model<n,modulus>::mul_by_non_residue(const Fp6_3over2_model<n, modulus> &elt)
18 return Fp6_3over2_model<n, modulus>(non_residue * elt.c2, elt.c0, elt.c1);
21 template<mp_size_t n, const bigint<n>& modulus>
22 Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::zero()
24 return Fp12_2over3over2_model<n, modulus>(my_Fp6::zero(), my_Fp6::zero());
27 template<mp_size_t n, const bigint<n>& modulus>
28 Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::one()
30 return Fp12_2over3over2_model<n, modulus>(my_Fp6::one(), my_Fp6::zero());
33 template<mp_size_t n, const bigint<n>& modulus>
34 Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::random_element()
36 Fp12_2over3over2_model<n, modulus> r;
37 r.c0 = my_Fp6::random_element();
38 r.c1 = my_Fp6::random_element();
43 template<mp_size_t n, const bigint<n>& modulus>
44 bool Fp12_2over3over2_model<n,modulus>::operator==(const Fp12_2over3over2_model<n,modulus> &other) const
46 return (this->c0 == other.c0 && this->c1 == other.c1);
49 template<mp_size_t n, const bigint<n>& modulus>
50 bool Fp12_2over3over2_model<n,modulus>::operator!=(const Fp12_2over3over2_model<n,modulus> &other) const
52 return !(operator==(other));
55 template<mp_size_t n, const bigint<n>& modulus>
56 Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::operator+(const Fp12_2over3over2_model<n,modulus> &other) const
58 return Fp12_2over3over2_model<n,modulus>(this->c0 + other.c0,
62 template<mp_size_t n, const bigint<n>& modulus>
63 Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::operator-(const Fp12_2over3over2_model<n,modulus> &other) const
65 return Fp12_2over3over2_model<n,modulus>(this->c0 - other.c0,
69 template<mp_size_t n, const bigint<n>& modulus>
70 Fp12_2over3over2_model<n, modulus> operator*(const Fp_model<n, modulus> &lhs, const Fp12_2over3over2_model<n, modulus> &rhs)
72 return Fp12_2over3over2_model<n,modulus>(lhs*rhs.c0,
76 template<mp_size_t n, const bigint<n>& modulus>
77 Fp12_2over3over2_model<n, modulus> operator*(const Fp2_model<n, modulus> &lhs, const Fp12_2over3over2_model<n, modulus> &rhs)
79 return Fp12_2over3over2_model<n,modulus>(lhs*rhs.c0,
83 template<mp_size_t n, const bigint<n>& modulus>
84 Fp12_2over3over2_model<n, modulus> operator*(const Fp6_3over2_model<n, modulus> &lhs, const Fp12_2over3over2_model<n, modulus> &rhs)
86 return Fp12_2over3over2_model<n,modulus>(lhs*rhs.c0,
90 template<mp_size_t n, const bigint<n>& modulus>
91 Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::operator*(const Fp12_2over3over2_model<n,modulus> &other) const
93 /* Devegili OhEig Scott Dahab --- Multiplication and Squaring on Pairing-Friendly Fields.pdf; Section 3 (Karatsuba) */
95 const my_Fp6 &A = other.c0, &B = other.c1,
96 &a = this->c0, &b = this->c1;
97 const my_Fp6 aA = a * A;
98 const my_Fp6 bB = b * B;
100 return Fp12_2over3over2_model<n,modulus>(aA + Fp12_2over3over2_model<n, modulus>::mul_by_non_residue(bB),
101 (a + b)*(A+B) - aA - bB);
104 template<mp_size_t n, const bigint<n>& modulus>
105 Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::operator-() const
107 return Fp12_2over3over2_model<n,modulus>(-this->c0,
111 template<mp_size_t n, const bigint<n>& modulus>
112 Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::squared() const
114 return squared_complex();
117 template<mp_size_t n, const bigint<n>& modulus>
118 Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::squared_karatsuba() const
120 /* Devegili OhEig Scott Dahab --- Multiplication and Squaring on Pairing-Friendly Fields.pdf; Section 3 (Karatsuba squaring) */
122 const my_Fp6 &a = this->c0, &b = this->c1;
123 const my_Fp6 asq = a.squared();
124 const my_Fp6 bsq = b.squared();
126 return Fp12_2over3over2_model<n,modulus>(asq + Fp12_2over3over2_model<n, modulus>::mul_by_non_residue(bsq),
127 (a + b).squared() - asq - bsq);
130 template<mp_size_t n, const bigint<n>& modulus>
131 Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::squared_complex() const
133 /* Devegili OhEig Scott Dahab --- Multiplication and Squaring on Pairing-Friendly Fields.pdf; Section 3 (Complex squaring) */
135 const my_Fp6 &a = this->c0, &b = this->c1;
136 const my_Fp6 ab = a * b;
138 return Fp12_2over3over2_model<n,modulus>((a + b) * (a + Fp12_2over3over2_model<n, modulus>::mul_by_non_residue(b)) - ab - Fp12_2over3over2_model<n, modulus>::mul_by_non_residue(ab),
142 template<mp_size_t n, const bigint<n>& modulus>
143 Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::inverse() const
145 /* From "High-Speed Software Implementation of the Optimal Ate Pairing over Barreto-Naehrig Curves"; Algorithm 8 */
147 const my_Fp6 &a = this->c0, &b = this->c1;
148 const my_Fp6 t0 = a.squared();
149 const my_Fp6 t1 = b.squared();
150 const my_Fp6 t2 = t0 - Fp12_2over3over2_model<n, modulus>::mul_by_non_residue(t1);
151 const my_Fp6 t3 = t2.inverse();
152 const my_Fp6 c0 = a * t3;
153 const my_Fp6 c1 = - (b * t3);
155 return Fp12_2over3over2_model<n,modulus>(c0, c1);
158 template<mp_size_t n, const bigint<n>& modulus>
159 Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::Frobenius_map(unsigned long power) const
161 return Fp12_2over3over2_model<n,modulus>(c0.Frobenius_map(power),
162 Frobenius_coeffs_c1[power % 12] * c1.Frobenius_map(power));
165 template<mp_size_t n, const bigint<n>& modulus>
166 Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::unitary_inverse() const
168 return Fp12_2over3over2_model<n,modulus>(this->c0,
172 template<mp_size_t n, const bigint<n>& modulus>
173 Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::cyclotomic_squared() const
175 /* OLD: naive implementation
176 return (*this).squared();
178 my_Fp2 z0 = this->c0.c0;
179 my_Fp2 z4 = this->c0.c1;
180 my_Fp2 z3 = this->c0.c2;
181 my_Fp2 z2 = this->c1.c0;
182 my_Fp2 z1 = this->c1.c1;
183 my_Fp2 z5 = this->c1.c2;
185 my_Fp2 t0, t1, t2, t3, t4, t5, tmp;
187 // t0 + t1*y = (z0 + z1*y)^2 = a^2
189 t0 = (z0 + z1) * (z0 + my_Fp6::non_residue * z1) - tmp - my_Fp6::non_residue * tmp;
191 // t2 + t3*y = (z2 + z3*y)^2 = b^2
193 t2 = (z2 + z3) * (z2 + my_Fp6::non_residue * z3) - tmp - my_Fp6::non_residue * tmp;
195 // t4 + t5*y = (z4 + z5*y)^2 = c^2
197 t4 = (z4 + z5) * (z4 + my_Fp6::non_residue * z5) - tmp - my_Fp6::non_residue * tmp;
202 // z0 = 3 * t0 - 2 * z0
206 // z1 = 3 * t1 + 2 * z1
213 // z2 = 3 * (xi * t5) + 2 * z2
214 tmp = my_Fp6::non_residue * t5;
219 // z3 = 3 * t4 - 2 * z3
226 // z4 = 3 * t2 - 2 * z4
231 // z5 = 3 * t3 + 2 * z5
236 return Fp12_2over3over2_model<n,modulus>(my_Fp6(z0,z4,z3),my_Fp6(z2,z1,z5));
239 template<mp_size_t n, const bigint<n>& modulus>
240 Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::mul_by_024(const Fp2_model<n, modulus> &ell_0,
241 const Fp2_model<n, modulus> &ell_VW,
242 const Fp2_model<n, modulus> &ell_VV) const
244 /* OLD: naive implementation
245 Fp12_2over3over2_model<n,modulus> a(my_Fp6(ell_0, my_Fp2::zero(), ell_VV),
246 my_Fp6(my_Fp2::zero(), ell_VW, my_Fp2::zero()));
250 my_Fp2 z0 = this->c0.c0;
251 my_Fp2 z1 = this->c0.c1;
252 my_Fp2 z2 = this->c0.c2;
253 my_Fp2 z3 = this->c1.c0;
254 my_Fp2 z4 = this->c1.c1;
255 my_Fp2 z5 = this->c1.c2;
261 my_Fp2 t0, t1, t2, s0, T3, T4, D0, D2, D4, S1;
273 T4 = my_Fp6::non_residue * T3 + D0;
280 T4 = my_Fp6::non_residue * T3;
288 T3 = t1 * t0 - D0 - D2;
293 // For z.b_.a_ = z3 (z3 needs z2)
297 T3 = t0 * t1 - D2 - D4;
298 T4 = my_Fp6::non_residue * T3;
307 T4 = my_Fp6::non_residue * T3;
309 T3 = t2 * t0 - D0 - D4;
318 return Fp12_2over3over2_model<n,modulus>(my_Fp6(z0,z1,z2),my_Fp6(z3,z4,z5));
322 template<mp_size_t n, const bigint<n>& modulus, mp_size_t m>
323 Fp12_2over3over2_model<n, modulus> operator^(const Fp12_2over3over2_model<n, modulus> &self, const bigint<m> &exponent)
325 return power<Fp12_2over3over2_model<n, modulus> >(self, exponent);
328 template<mp_size_t n, const bigint<n>& modulus, mp_size_t m, const bigint<m>& exp_modulus>
329 Fp12_2over3over2_model<n, modulus> operator^(const Fp12_2over3over2_model<n, modulus> &self, const Fp_model<m, exp_modulus> &exponent)
331 return self^(exponent.as_bigint());
335 template<mp_size_t n, const bigint<n>& modulus>
336 template<mp_size_t m>
337 Fp12_2over3over2_model<n, modulus> Fp12_2over3over2_model<n,modulus>::cyclotomic_exp(const bigint<m> &exponent) const
339 Fp12_2over3over2_model<n,modulus> res = Fp12_2over3over2_model<n,modulus>::one();
341 bool found_one = false;
342 for (long i = m-1; i >= 0; --i)
344 for (long j = GMP_NUMB_BITS - 1; j >= 0; --j)
348 res = res.cyclotomic_squared();
351 if (exponent.data[i] & (1ul<<j))
362 template<mp_size_t n, const bigint<n>& modulus>
363 std::ostream& operator<<(std::ostream &out, const Fp12_2over3over2_model<n, modulus> &el)
365 out << el.c0 << OUTPUT_SEPARATOR << el.c1;
369 template<mp_size_t n, const bigint<n>& modulus>
370 std::istream& operator>>(std::istream &in, Fp12_2over3over2_model<n, modulus> &el)
372 in >> el.c0 >> el.c1;
376 template<mp_size_t n, const bigint<n>& modulus>
377 std::ostream& operator<<(std::ostream& out, const std::vector<Fp12_2over3over2_model<n, modulus> > &v)
379 out << v.size() << "\n";
380 for (const Fp12_2over3over2_model<n, modulus>& t : v)
382 out << t << OUTPUT_NEWLINE;
388 template<mp_size_t n, const bigint<n>& modulus>
389 std::istream& operator>>(std::istream& in, std::vector<Fp12_2over3over2_model<n, modulus> > &v)
401 for (size_t i = 0; i < s; ++i)
403 Fp12_2over3over2_model<n, modulus> el;
412 #endif // FP12_2OVER3OVER2_TCC_