Clearmatics Libff  0.1
C++ library for Finite Fields and Elliptic Curves
fp3.tcc
Go to the documentation of this file.
1 /** @file
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  *****************************************************************************/
9 
10 #ifndef FP3_TCC_
11 #define FP3_TCC_
12 
13 #include <libff/algebra/fields/field_utils.hpp>
14 
15 namespace libff
16 {
17 
18 template<mp_size_t n, const bigint<n> &modulus>
19 Fp3_model<n, modulus> Fp3_model<n, modulus>::zero()
20 {
21  return Fp3_model<n, modulus>(my_Fp::zero(), my_Fp::zero(), my_Fp::zero());
22 }
23 
24 template<mp_size_t n, const bigint<n> &modulus>
25 Fp3_model<n, modulus> Fp3_model<n, modulus>::one()
26 {
27  return Fp3_model<n, modulus>(my_Fp::one(), my_Fp::zero(), my_Fp::zero());
28 }
29 
30 template<mp_size_t n, const bigint<n> &modulus>
31 Fp3_model<n, modulus> Fp3_model<n, modulus>::random_element()
32 {
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();
37 
38  return r;
39 }
40 
41 template<mp_size_t n, const bigint<n> &modulus>
42 bool Fp3_model<n, modulus>::operator==(const Fp3_model<n, modulus> &other) const
43 {
44  return (
45  this->coeffs[0] == other.coeffs[0] &&
46  this->coeffs[1] == other.coeffs[1] &&
47  this->coeffs[2] == other.coeffs[2]);
48 }
49 
50 template<mp_size_t n, const bigint<n> &modulus>
51 bool Fp3_model<n, modulus>::operator!=(const Fp3_model<n, modulus> &other) const
52 {
53  return !(operator==(other));
54 }
55 
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
59 {
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]);
64 }
65 
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
69 {
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]);
74 }
75 
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)
79 {
80  return Fp3_model<n, modulus>(
81  lhs * rhs.coeffs[0], lhs * rhs.coeffs[1], lhs * rhs.coeffs[2]);
82 }
83 
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
87 {
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;
96 
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);
101 }
102 
103 template<mp_size_t n, const bigint<n> &modulus>
104 Fp3_model<n, modulus> Fp3_model<n, modulus>::operator-() const
105 {
106  return Fp3_model<n, modulus>(
107  -this->coeffs[0], -this->coeffs[1], -this->coeffs[2]);
108 }
109 
110 template<mp_size_t n, const bigint<n> &modulus>
111 Fp3_model<n, modulus> Fp3_model<n, modulus>::squared() const
112 {
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();
124 
125  return Fp3_model<n, modulus>(
126  s0 + non_residue * s3, s1 + non_residue * s4, s1 + s2 + s3 - s0 - s4);
127 }
128 
129 template<mp_size_t n, const bigint<n> &modulus>
130 Fp3_model<n, modulus> Fp3_model<n, modulus>::inverse() const
131 {
132  const my_Fp &a = this->coeffs[0], &b = this->coeffs[1],
133  &c = this->coeffs[2];
134 
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);
149 }
150 
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
154 {
155  return Fp3_model<n, modulus>(
156  coeffs[0],
157  Frobenius_coeffs_c1[power % 3] * coeffs[1],
158  Frobenius_coeffs_c2[power % 3] * coeffs[2]);
159 }
160 
161 template<mp_size_t n, const bigint<n> &modulus>
162 Fp3_model<n, modulus> Fp3_model<n, modulus>::sqrt() const
163 {
164  Fp3_model<n, modulus> one = Fp3_model<n, modulus>::one();
165 
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
171 
172 #if DEBUG
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();
177  }
178  if (check != one) {
179  assert(0);
180  }
181 #endif
182 
183  // compute square root with Tonelli--Shanks
184  // (does not terminate if not a square!)
185 
186  while (b != one) {
187  size_t m = 0;
188  Fp3_model<n, modulus> b2m = b;
189  while (b2m != one) {
190  /* invariant: b2m = b^(2^m) after entering this loop */
191  b2m = b2m.squared();
192  m += 1;
193  }
194 
195  int j = v - m - 1;
196  w = z;
197  while (j > 0) {
198  w = w.squared();
199  --j;
200  } // w = z^2^(v-m-1)
201 
202  z = w.squared();
203  b = b * z;
204  x = x * w;
205  v = m;
206  }
207 
208  return x;
209 }
210 
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
215 {
216  return power<Fp3_model<n, modulus>>(*this, pow);
217 }
218 
219 template<mp_size_t n, const bigint<n> &modulus>
220 std::ostream &operator<<(std::ostream &out, const Fp3_model<n, modulus> &el)
221 {
222  out << el.coeffs[0] << OUTPUT_SEPARATOR << el.coeffs[1] << OUTPUT_SEPARATOR
223  << el.coeffs[2];
224  return out;
225 }
226 
227 template<mp_size_t n, const bigint<n> &modulus>
228 std::istream &operator>>(std::istream &in, Fp3_model<n, modulus> &el)
229 {
230  in >> el.coeffs[0] >> el.coeffs[1] >> el.coeffs[2];
231  return in;
232 }
233 
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)
237 {
238  out << v.size() << "\n";
239  for (const Fp3_model<n, modulus> &t : v) {
240  out << t << OUTPUT_NEWLINE;
241  }
242 
243  return out;
244 }
245 
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)
249 {
250  v.clear();
251 
252  size_t s;
253  in >> s;
254 
255  char b;
256  in.read(&b, 1);
257 
258  v.reserve(s);
259 
260  for (size_t i = 0; i < s; ++i) {
261  Fp3_model<n, modulus> el;
262  in >> el;
263  v.emplace_back(el);
264  }
265 
266  return in;
267 }
268 
269 } // namespace libff
270 #endif // FP3_TCC_