2 *****************************************************************************
3 Implementation of arithmetic in the finite field F[p^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 *****************************************************************************/
13 #include <libff/algebra/fields/field_utils.hpp>
18 template<mp_size_t n, const bigint<n> &modulus>
19 Fp3_model<n, modulus> Fp3_model<n, modulus>::zero()
21 return Fp3_model<n, modulus>(my_Fp::zero(), my_Fp::zero(), my_Fp::zero());
24 template<mp_size_t n, const bigint<n> &modulus>
25 Fp3_model<n, modulus> Fp3_model<n, modulus>::one()
27 return Fp3_model<n, modulus>(my_Fp::one(), my_Fp::zero(), my_Fp::zero());
30 template<mp_size_t n, const bigint<n> &modulus>
31 Fp3_model<n, modulus> Fp3_model<n, modulus>::random_element()
33 Fp3_model<n, modulus> r;
34 r.coeffs[0] = my_Fp::random_element();
35 r.coeffs[1] = my_Fp::random_element();
36 r.coeffs[2] = my_Fp::random_element();
41 template<mp_size_t n, const bigint<n> &modulus>
42 bool Fp3_model<n, modulus>::operator==(const Fp3_model<n, modulus> &other) const
45 this->coeffs[0] == other.coeffs[0] &&
46 this->coeffs[1] == other.coeffs[1] &&
47 this->coeffs[2] == other.coeffs[2]);
50 template<mp_size_t n, const bigint<n> &modulus>
51 bool Fp3_model<n, modulus>::operator!=(const Fp3_model<n, modulus> &other) const
53 return !(operator==(other));
56 template<mp_size_t n, const bigint<n> &modulus>
57 Fp3_model<n, modulus> Fp3_model<n, modulus>::operator+(
58 const Fp3_model<n, modulus> &other) const
60 return Fp3_model<n, modulus>(
61 this->coeffs[0] + other.coeffs[0],
62 this->coeffs[1] + other.coeffs[1],
63 this->coeffs[2] + other.coeffs[2]);
66 template<mp_size_t n, const bigint<n> &modulus>
67 Fp3_model<n, modulus> Fp3_model<n, modulus>::operator-(
68 const Fp3_model<n, modulus> &other) const
70 return Fp3_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 Fp3_model<n, modulus> operator*(
78 const Fp_model<n, modulus> &lhs, const Fp3_model<n, modulus> &rhs)
80 return Fp3_model<n, modulus>(
81 lhs * rhs.coeffs[0], lhs * rhs.coeffs[1], lhs * rhs.coeffs[2]);
84 template<mp_size_t n, const bigint<n> &modulus>
85 Fp3_model<n, modulus> Fp3_model<n, modulus>::operator*(
86 const Fp3_model<n, modulus> &other) const
88 /* Devegili OhEig Scott Dahab --- Multiplication and Squaring on
89 * Pairing-Friendly Fields.pdf; Section 4 (Karatsuba) */
90 const my_Fp &A = other.coeffs[0], &B = other.coeffs[1],
91 &C = other.coeffs[2], &a = this->coeffs[0],
92 &b = this->coeffs[1], &c = this->coeffs[2];
93 const my_Fp aA = a * A;
94 const my_Fp bB = b * B;
95 const my_Fp cC = c * C;
97 return Fp3_model<n, modulus>(
98 aA + non_residue * ((b + c) * (B + C) - bB - cC),
99 (a + b) * (A + B) - aA - bB + non_residue * cC,
100 (a + c) * (A + C) - aA + bB - cC);
103 template<mp_size_t n, const bigint<n> &modulus>
104 Fp3_model<n, modulus> Fp3_model<n, modulus>::operator-() const
106 return Fp3_model<n, modulus>(
107 -this->coeffs[0], -this->coeffs[1], -this->coeffs[2]);
110 template<mp_size_t n, const bigint<n> &modulus>
111 Fp3_model<n, modulus> Fp3_model<n, modulus>::squared() const
113 /* Devegili OhEig Scott Dahab --- Multiplication and Squaring on
114 * Pairing-Friendly Fields.pdf; Section 4 (CH-SQR2) */
115 const my_Fp &a = this->coeffs[0], &b = this->coeffs[1],
116 &c = this->coeffs[2];
117 const my_Fp s0 = a.squared();
118 const my_Fp ab = a * b;
119 const my_Fp s1 = ab + ab;
120 const my_Fp s2 = (a - b + c).squared();
121 const my_Fp bc = b * c;
122 const my_Fp s3 = bc + bc;
123 const my_Fp s4 = c.squared();
125 return Fp3_model<n, modulus>(
126 s0 + non_residue * s3, s1 + non_residue * s4, s1 + s2 + s3 - s0 - s4);
129 template<mp_size_t n, const bigint<n> &modulus>
130 Fp3_model<n, modulus> Fp3_model<n, modulus>::inverse() const
132 const my_Fp &a = this->coeffs[0], &b = this->coeffs[1],
133 &c = this->coeffs[2];
135 /* From "High-Speed Software Implementation of the Optimal Ate Pairing over
136 * Barreto-Naehrig Curves"; Algorithm 17 */
137 const my_Fp t0 = a.squared();
138 const my_Fp t1 = b.squared();
139 const my_Fp t2 = c.squared();
140 const my_Fp t3 = a * b;
141 const my_Fp t4 = a * c;
142 const my_Fp t5 = b * c;
143 const my_Fp c0 = t0 - non_residue * t5;
144 const my_Fp c1 = non_residue * t2 - t3;
145 const my_Fp c2 = t1 - t4; // typo in paper referenced above. should be "-"
146 // as per Scott, but is "*"
147 const my_Fp t6 = (a * c0 + non_residue * (c * c1 + b * c2)).inverse();
148 return Fp3_model<n, modulus>(t6 * c0, t6 * c1, t6 * c2);
151 template<mp_size_t n, const bigint<n> &modulus>
152 Fp3_model<n, modulus> Fp3_model<n, modulus>::Frobenius_map(
153 unsigned long power) const
155 return Fp3_model<n, modulus>(
157 Frobenius_coeffs_c1[power % 3] * coeffs[1],
158 Frobenius_coeffs_c2[power % 3] * coeffs[2]);
161 template<mp_size_t n, const bigint<n> &modulus>
162 Fp3_model<n, modulus> Fp3_model<n, modulus>::sqrt() const
164 Fp3_model<n, modulus> one = Fp3_model<n, modulus>::one();
166 size_t v = Fp3_model<n, modulus>::s;
167 Fp3_model<n, modulus> z = Fp3_model<n, modulus>::nqr_to_t;
168 Fp3_model<n, modulus> w = (*this) ^ Fp3_model<n, modulus>::t_minus_1_over_2;
169 Fp3_model<n, modulus> x = (*this) * w;
170 Fp3_model<n, modulus> b = x * w; // b = (*this)^t
173 // check if square with euler's criterion
174 Fp3_model<n, modulus> check = b;
175 for (size_t i = 0; i < v - 1; ++i) {
176 check = check.squared();
183 // compute square root with Tonelli--Shanks
184 // (does not terminate if not a square!)
188 Fp3_model<n, modulus> b2m = b;
190 /* invariant: b2m = b^(2^m) after entering this loop */
211 template<mp_size_t n, const bigint<n> &modulus>
212 template<mp_size_t m>
213 Fp3_model<n, modulus> Fp3_model<n, modulus>::operator^(
214 const bigint<m> &pow) const
216 return power<Fp3_model<n, modulus>>(*this, pow);
219 template<mp_size_t n, const bigint<n> &modulus>
220 std::ostream &operator<<(std::ostream &out, const Fp3_model<n, modulus> &el)
222 out << el.coeffs[0] << OUTPUT_SEPARATOR << el.coeffs[1] << OUTPUT_SEPARATOR
227 template<mp_size_t n, const bigint<n> &modulus>
228 std::istream &operator>>(std::istream &in, Fp3_model<n, modulus> &el)
230 in >> el.coeffs[0] >> el.coeffs[1] >> el.coeffs[2];
234 template<mp_size_t n, const bigint<n> &modulus>
235 std::ostream &operator<<(
236 std::ostream &out, const std::vector<Fp3_model<n, modulus>> &v)
238 out << v.size() << "\n";
239 for (const Fp3_model<n, modulus> &t : v) {
240 out << t << OUTPUT_NEWLINE;
246 template<mp_size_t n, const bigint<n> &modulus>
247 std::istream &operator>>(
248 std::istream &in, std::vector<Fp3_model<n, modulus>> &v)
260 for (size_t i = 0; i < s; ++i) {
261 Fp3_model<n, modulus> el;