Clearmatics Libff  0.1
C++ library for Finite Fields and Elliptic Curves
fp6_3over2.tcc
Go to the documentation of this file.
1 /** @file
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  *****************************************************************************/
9 
10 #ifndef FP6_3OVER2_TCC_
11 #define FP6_3OVER2_TCC_
12 #include <libff/algebra/fields/field_utils.hpp>
13 
14 namespace libff
15 {
16 
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)
20 {
21  return Fp2_model<n, modulus>(non_residue * elt);
22 }
23 
24 template<mp_size_t n, const bigint<n> &modulus>
25 Fp6_3over2_model<n, modulus> Fp6_3over2_model<n, modulus>::zero()
26 {
27  return Fp6_3over2_model<n, modulus>(
28  my_Fp2::zero(), my_Fp2::zero(), my_Fp2::zero());
29 }
30 
31 template<mp_size_t n, const bigint<n> &modulus>
32 Fp6_3over2_model<n, modulus> Fp6_3over2_model<n, modulus>::one()
33 {
34  return Fp6_3over2_model<n, modulus>(
35  my_Fp2::one(), my_Fp2::zero(), my_Fp2::zero());
36 }
37 
38 template<mp_size_t n, const bigint<n> &modulus>
39 Fp6_3over2_model<n, modulus> Fp6_3over2_model<n, modulus>::random_element()
40 {
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();
45 
46  return r;
47 }
48 
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
52 {
53  return (
54  this->coeffs[0] == other.coeffs[0] &&
55  this->coeffs[1] == other.coeffs[1] &&
56  this->coeffs[2] == other.coeffs[2]);
57 }
58 
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
62 {
63  return !(operator==(other));
64 }
65 
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
69 {
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]);
74 }
75 
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
79 {
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]);
84 }
85 
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)
89 {
90  return Fp6_3over2_model<n, modulus>(
91  lhs * rhs.coeffs[0], lhs * rhs.coeffs[1], lhs * rhs.coeffs[2]);
92 }
93 
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)
97 {
98  return Fp6_3over2_model<n, modulus>(
99  lhs * rhs.coeffs[0], lhs * rhs.coeffs[1], lhs * rhs.coeffs[2]);
100 }
101 
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
105 {
106  // Devegili OhEig Scott Dahab --- Multiplication and Squaring on
107  // Pairing-Friendly Fields.pdf; Section 4 (Karatsuba)
108 
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;
115 
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);
122 }
123 
124 template<mp_size_t n, const bigint<n> &modulus>
125 Fp6_3over2_model<n, modulus> Fp6_3over2_model<n, modulus>::operator-() const
126 {
127  return Fp6_3over2_model<n, modulus>(
128  -this->coeffs[0], -this->coeffs[1], -this->coeffs[2]);
129 }
130 
131 template<mp_size_t n, const bigint<n> &modulus>
132 Fp6_3over2_model<n, modulus> Fp6_3over2_model<n, modulus>::squared() const
133 {
134  // Devegili OhEig Scott Dahab --- Multiplication and Squaring on
135  // Pairing-Friendly Fields.pdf; Section 4 (CH-SQR2)
136 
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();
146 
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);
151 }
152 
153 template<mp_size_t n, const bigint<n> &modulus>
154 Fp6_3over2_model<n, modulus> Fp6_3over2_model<n, modulus>::inverse() const
155 {
156  // From "High-Speed Software Implementation of the Optimal Ate Pairing over
157  // Barreto-Naehrig Curves"; Algorithm 17
158 
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;
171  const my_Fp2 t6 =
172  (a * c0 +
173  Fp6_3over2_model<n, modulus>::mul_by_non_residue((c * c1 + b * c2)))
174  .inverse();
175  return Fp6_3over2_model<n, modulus>(t6 * c0, t6 * c1, t6 * c2);
176 }
177 
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
181 {
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));
186 }
187 
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
192 {
193  return power<Fp6_3over2_model<n, modulus>, m>(*this, pow);
194 }
195 
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)
199 {
200  out << el.coeffs[0] << OUTPUT_SEPARATOR << el.coeffs[1] << OUTPUT_SEPARATOR
201  << el.coeffs[2];
202  return out;
203 }
204 
205 template<mp_size_t n, const bigint<n> &modulus>
206 std::istream &operator>>(std::istream &in, Fp6_3over2_model<n, modulus> &el)
207 {
208  in >> el.coeffs[0] >> el.coeffs[1] >> el.coeffs[2];
209  return in;
210 }
211 
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)
215 {
216  out << v.size() << "\n";
217  for (const Fp6_3over2_model<n, modulus> &t : v) {
218  out << t << OUTPUT_NEWLINE;
219  }
220 
221  return out;
222 }
223 
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)
227 {
228  v.clear();
229 
230  size_t s;
231  in >> s;
232 
233  char b;
234  in.read(&b, 1);
235 
236  v.reserve(s);
237 
238  for (size_t i = 0; i < s; ++i) {
239  Fp6_3over2_model<n, modulus> el;
240  in >> el;
241  v.emplace_back(el);
242  }
243 
244  return in;
245 }
246 
247 } // namespace libff
248 
249 #endif // FP6_3_OVER_2_TCC_