2 *****************************************************************************
3 Implementation of arithmetic in the finite field F[(p^2)^3].
4 *****************************************************************************
5 * @author This file is part of libff, developed by SCIPR Lab
6 * and contributors (see AUTHORS).
7 * @copyright MIT license (see LICENSE file)
8 *****************************************************************************/
10 #ifndef FP6_3OVER2_TCC_
11 #define FP6_3OVER2_TCC_
12 #include <libff/algebra/fields/field_utils.hpp>
17 template<mp_size_t n, const bigint<n> &modulus>
18 Fp2_model<n, modulus> Fp6_3over2_model<n, modulus>::mul_by_non_residue(
19 const Fp2_model<n, modulus> &elt)
21 return Fp2_model<n, modulus>(non_residue * elt);
24 template<mp_size_t n, const bigint<n> &modulus>
25 Fp6_3over2_model<n, modulus> Fp6_3over2_model<n, modulus>::zero()
27 return Fp6_3over2_model<n, modulus>(
28 my_Fp2::zero(), my_Fp2::zero(), my_Fp2::zero());
31 template<mp_size_t n, const bigint<n> &modulus>
32 Fp6_3over2_model<n, modulus> Fp6_3over2_model<n, modulus>::one()
34 return Fp6_3over2_model<n, modulus>(
35 my_Fp2::one(), my_Fp2::zero(), my_Fp2::zero());
38 template<mp_size_t n, const bigint<n> &modulus>
39 Fp6_3over2_model<n, modulus> Fp6_3over2_model<n, modulus>::random_element()
41 Fp6_3over2_model<n, modulus> r;
42 r.coeffs[0] = my_Fp2::random_element();
43 r.coeffs[1] = my_Fp2::random_element();
44 r.coeffs[2] = my_Fp2::random_element();
49 template<mp_size_t n, const bigint<n> &modulus>
50 bool Fp6_3over2_model<n, modulus>::operator==(
51 const Fp6_3over2_model<n, modulus> &other) const
54 this->coeffs[0] == other.coeffs[0] &&
55 this->coeffs[1] == other.coeffs[1] &&
56 this->coeffs[2] == other.coeffs[2]);
59 template<mp_size_t n, const bigint<n> &modulus>
60 bool Fp6_3over2_model<n, modulus>::operator!=(
61 const Fp6_3over2_model<n, modulus> &other) const
63 return !(operator==(other));
66 template<mp_size_t n, const bigint<n> &modulus>
67 Fp6_3over2_model<n, modulus> Fp6_3over2_model<n, modulus>::operator+(
68 const Fp6_3over2_model<n, modulus> &other) const
70 return Fp6_3over2_model<n, modulus>(
71 this->coeffs[0] + other.coeffs[0],
72 this->coeffs[1] + other.coeffs[1],
73 this->coeffs[2] + other.coeffs[2]);
76 template<mp_size_t n, const bigint<n> &modulus>
77 Fp6_3over2_model<n, modulus> Fp6_3over2_model<n, modulus>::operator-(
78 const Fp6_3over2_model<n, modulus> &other) const
80 return Fp6_3over2_model<n, modulus>(
81 this->coeffs[0] - other.coeffs[0],
82 this->coeffs[1] - other.coeffs[1],
83 this->coeffs[2] - other.coeffs[2]);
86 template<mp_size_t n, const bigint<n> &modulus>
87 Fp6_3over2_model<n, modulus> operator*(
88 const Fp_model<n, modulus> &lhs, const Fp6_3over2_model<n, modulus> &rhs)
90 return Fp6_3over2_model<n, modulus>(
91 lhs * rhs.coeffs[0], lhs * rhs.coeffs[1], lhs * rhs.coeffs[2]);
94 template<mp_size_t n, const bigint<n> &modulus>
95 Fp6_3over2_model<n, modulus> operator*(
96 const Fp2_model<n, modulus> &lhs, const Fp6_3over2_model<n, modulus> &rhs)
98 return Fp6_3over2_model<n, modulus>(
99 lhs * rhs.coeffs[0], lhs * rhs.coeffs[1], lhs * rhs.coeffs[2]);
102 template<mp_size_t n, const bigint<n> &modulus>
103 Fp6_3over2_model<n, modulus> Fp6_3over2_model<n, modulus>::operator*(
104 const Fp6_3over2_model<n, modulus> &other) const
106 // Devegili OhEig Scott Dahab --- Multiplication and Squaring on
107 // Pairing-Friendly Fields.pdf; Section 4 (Karatsuba)
109 const my_Fp2 &A = other.coeffs[0], &B = other.coeffs[1],
110 &C = other.coeffs[2], &a = this->coeffs[0],
111 &b = this->coeffs[1], &c = this->coeffs[2];
112 const my_Fp2 aA = a * A;
113 const my_Fp2 bB = b * B;
114 const my_Fp2 cC = c * C;
116 return Fp6_3over2_model<n, modulus>(
117 aA + Fp6_3over2_model<n, modulus>::mul_by_non_residue(
118 (b + c) * (B + C) - bB - cC),
119 (a + b) * (A + B) - aA - bB +
120 Fp6_3over2_model<n, modulus>::mul_by_non_residue(cC),
121 (a + c) * (A + C) - aA + bB - cC);
124 template<mp_size_t n, const bigint<n> &modulus>
125 Fp6_3over2_model<n, modulus> Fp6_3over2_model<n, modulus>::operator-() const
127 return Fp6_3over2_model<n, modulus>(
128 -this->coeffs[0], -this->coeffs[1], -this->coeffs[2]);
131 template<mp_size_t n, const bigint<n> &modulus>
132 Fp6_3over2_model<n, modulus> Fp6_3over2_model<n, modulus>::squared() const
134 // Devegili OhEig Scott Dahab --- Multiplication and Squaring on
135 // Pairing-Friendly Fields.pdf; Section 4 (CH-SQR2)
137 const my_Fp2 &a = this->coeffs[0], &b = this->coeffs[1],
138 &c = this->coeffs[2];
139 const my_Fp2 s0 = a.squared();
140 const my_Fp2 ab = a * b;
141 const my_Fp2 s1 = ab + ab;
142 const my_Fp2 s2 = (a - b + c).squared();
143 const my_Fp2 bc = b * c;
144 const my_Fp2 s3 = bc + bc;
145 const my_Fp2 s4 = c.squared();
147 return Fp6_3over2_model<n, modulus>(
148 s0 + Fp6_3over2_model<n, modulus>::mul_by_non_residue(s3),
149 s1 + Fp6_3over2_model<n, modulus>::mul_by_non_residue(s4),
150 s1 + s2 + s3 - s0 - s4);
153 template<mp_size_t n, const bigint<n> &modulus>
154 Fp6_3over2_model<n, modulus> Fp6_3over2_model<n, modulus>::inverse() const
156 // From "High-Speed Software Implementation of the Optimal Ate Pairing over
157 // Barreto-Naehrig Curves"; Algorithm 17
159 const my_Fp2 &a = this->coeffs[0], &b = this->coeffs[1],
160 &c = this->coeffs[2];
161 const my_Fp2 t0 = a.squared();
162 const my_Fp2 t1 = b.squared();
163 const my_Fp2 t2 = c.squared();
164 const my_Fp2 t3 = a * b;
165 const my_Fp2 t4 = a * c;
166 const my_Fp2 t5 = b * c;
167 const my_Fp2 c0 = t0 - Fp6_3over2_model<n, modulus>::mul_by_non_residue(t5);
168 const my_Fp2 c1 = Fp6_3over2_model<n, modulus>::mul_by_non_residue(t2) - t3;
169 // typo in paper referenced above. should be "-" as per Scott, but is "*"
170 const my_Fp2 c2 = t1 - t4;
173 Fp6_3over2_model<n, modulus>::mul_by_non_residue((c * c1 + b * c2)))
175 return Fp6_3over2_model<n, modulus>(t6 * c0, t6 * c1, t6 * c2);
178 template<mp_size_t n, const bigint<n> &modulus>
179 Fp6_3over2_model<n, modulus> Fp6_3over2_model<n, modulus>::Frobenius_map(
180 unsigned long power) const
182 return Fp6_3over2_model<n, modulus>(
183 coeffs[0].Frobenius_map(power),
184 Frobenius_coeffs_c1[power % 6] * coeffs[1].Frobenius_map(power),
185 Frobenius_coeffs_c2[power % 6] * coeffs[2].Frobenius_map(power));
188 template<mp_size_t n, const bigint<n> &modulus>
189 template<mp_size_t m>
190 Fp6_3over2_model<n, modulus> Fp6_3over2_model<n, modulus>::operator^(
191 const bigint<m> &pow) const
193 return power<Fp6_3over2_model<n, modulus>, m>(*this, pow);
196 template<mp_size_t n, const bigint<n> &modulus>
197 std::ostream &operator<<(
198 std::ostream &out, const Fp6_3over2_model<n, modulus> &el)
200 out << el.coeffs[0] << OUTPUT_SEPARATOR << el.coeffs[1] << OUTPUT_SEPARATOR
205 template<mp_size_t n, const bigint<n> &modulus>
206 std::istream &operator>>(std::istream &in, Fp6_3over2_model<n, modulus> &el)
208 in >> el.coeffs[0] >> el.coeffs[1] >> el.coeffs[2];
212 template<mp_size_t n, const bigint<n> &modulus>
213 std::ostream &operator<<(
214 std::ostream &out, const std::vector<Fp6_3over2_model<n, modulus>> &v)
216 out << v.size() << "\n";
217 for (const Fp6_3over2_model<n, modulus> &t : v) {
218 out << t << OUTPUT_NEWLINE;
224 template<mp_size_t n, const bigint<n> &modulus>
225 std::istream &operator>>(
226 std::istream &in, std::vector<Fp6_3over2_model<n, modulus>> &v)
238 for (size_t i = 0; i < s; ++i) {
239 Fp6_3over2_model<n, modulus> el;
249 #endif // FP6_3_OVER_2_TCC_