Clearmatics Libff  0.1
C++ library for Finite Fields and Elliptic Curves
fp4.tcc
Go to the documentation of this file.
1 /** @file
2  *****************************************************************************
3 
4  Implementation of interfaces for the (extension) field Fp4.
5 
6  See fp4.hpp .
7 
8  *****************************************************************************
9  * @author This file is part of libff, developed by SCIPR Lab
10  * and contributors (see AUTHORS).
11  * @copyright MIT license (see LICENSE file)
12  *****************************************************************************/
13 
14 #ifndef FP4_TCC_
15 #define FP4_TCC_
16 
17 #include <libff/algebra/fields/field_utils.hpp>
18 #include <libff/algebra/scalar_multiplication/wnaf.hpp>
19 
20 namespace libff
21 {
22 
23 template<mp_size_t n, const bigint<n> &modulus>
24 Fp2_model<n, modulus> Fp4_model<n, modulus>::mul_by_non_residue(
25  const Fp2_model<n, modulus> &elt)
26 {
27  return Fp2_model<n, modulus>(non_residue * elt.coeffs[1], elt.coeffs[0]);
28 }
29 
30 template<mp_size_t n, const bigint<n> &modulus>
31 Fp4_model<n, modulus> Fp4_model<n, modulus>::zero()
32 {
33  return Fp4_model<n, modulus>(my_Fp2::zero(), my_Fp2::zero());
34 }
35 
36 template<mp_size_t n, const bigint<n> &modulus>
37 Fp4_model<n, modulus> Fp4_model<n, modulus>::one()
38 {
39  return Fp4_model<n, modulus>(my_Fp2::one(), my_Fp2::zero());
40 }
41 
42 template<mp_size_t n, const bigint<n> &modulus>
43 Fp4_model<n, modulus> Fp4_model<n, modulus>::random_element()
44 {
45  Fp4_model<n, modulus> r;
46  r.coeffs[0] = my_Fp2::random_element();
47  r.coeffs[1] = my_Fp2::random_element();
48 
49  return r;
50 }
51 
52 template<mp_size_t n, const bigint<n> &modulus>
53 bool Fp4_model<n, modulus>::operator==(const Fp4_model<n, modulus> &other) const
54 {
55  return (
56  this->coeffs[0] == other.coeffs[0] &&
57  this->coeffs[1] == other.coeffs[1]);
58 }
59 
60 template<mp_size_t n, const bigint<n> &modulus>
61 bool Fp4_model<n, modulus>::operator!=(const Fp4_model<n, modulus> &other) const
62 {
63  return !(operator==(other));
64 }
65 
66 template<mp_size_t n, const bigint<n> &modulus>
67 Fp4_model<n, modulus> Fp4_model<n, modulus>::operator+(
68  const Fp4_model<n, modulus> &other) const
69 {
70  return Fp4_model<n, modulus>(
71  this->coeffs[0] + other.coeffs[0], this->coeffs[1] + other.coeffs[1]);
72 }
73 
74 template<mp_size_t n, const bigint<n> &modulus>
75 Fp4_model<n, modulus> Fp4_model<n, modulus>::operator-(
76  const Fp4_model<n, modulus> &other) const
77 {
78  return Fp4_model<n, modulus>(
79  this->coeffs[0] - other.coeffs[0], this->coeffs[1] - other.coeffs[1]);
80 }
81 
82 template<mp_size_t n, const bigint<n> &modulus>
83 Fp4_model<n, modulus> operator*(
84  const Fp_model<n, modulus> &lhs, const Fp4_model<n, modulus> &rhs)
85 {
86  return Fp4_model<n, modulus>(lhs * rhs.coeffs[0], lhs * rhs.coeffs[1]);
87 }
88 
89 template<mp_size_t n, const bigint<n> &modulus>
90 Fp4_model<n, modulus> operator*(
91  const Fp2_model<n, modulus> &lhs, const Fp4_model<n, modulus> &rhs)
92 {
93  return Fp4_model<n, modulus>(lhs * rhs.coeffs[0], lhs * rhs.coeffs[1]);
94 }
95 
96 template<mp_size_t n, const bigint<n> &modulus>
97 Fp4_model<n, modulus> Fp4_model<n, modulus>::operator*(
98  const Fp4_model<n, modulus> &other) const
99 {
100  // Devegili OhEig Scott Dahab --- Multiplication and Squaring on
101  // Pairing-Friendly Fields.pdf; Section 3 (Karatsuba)
102 
103  const my_Fp2 &B = other.coeffs[1], &A = other.coeffs[0],
104  &b = this->coeffs[1], &a = this->coeffs[0];
105  const my_Fp2 aA = a * A;
106  const my_Fp2 bB = b * B;
107 
108  const my_Fp2 beta_bB = Fp4_model<n, modulus>::mul_by_non_residue(bB);
109  return Fp4_model<n, modulus>(aA + beta_bB, (a + b) * (A + B) - aA - bB);
110 }
111 
112 template<mp_size_t n, const bigint<n> &modulus>
113 Fp4_model<n, modulus> Fp4_model<n, modulus>::mul_by_023(
114  const Fp4_model<n, modulus> &other) const
115 {
116  // Devegili OhEig Scott Dahab --- Multiplication and Squaring on
117  // Pairing-Friendly Fields.pdf; Section 3 (Karatsuba)
118  assert(other.coeffs[0].coeffs[1].is_zero());
119 
120  const my_Fp2 &B = other.coeffs[1], &A = other.coeffs[0],
121  &b = this->coeffs[1], &a = this->coeffs[0];
122  const my_Fp2 aA =
123  my_Fp2(a.coeffs[0] * A.coeffs[0], a.coeffs[1] * A.coeffs[0]);
124  const my_Fp2 bB = b * B;
125 
126  const my_Fp2 beta_bB = Fp4_model<n, modulus>::mul_by_non_residue(bB);
127  return Fp4_model<n, modulus>(aA + beta_bB, (a + b) * (A + B) - aA - bB);
128 }
129 
130 template<mp_size_t n, const bigint<n> &modulus>
131 Fp4_model<n, modulus> Fp4_model<n, modulus>::operator-() const
132 {
133  return Fp4_model<n, modulus>(-this->coeffs[0], -this->coeffs[1]);
134 }
135 
136 template<mp_size_t n, const bigint<n> &modulus>
137 Fp4_model<n, modulus> Fp4_model<n, modulus>::squared() const
138 {
139  // Devegili OhEig Scott Dahab --- Multiplication and Squaring on
140  // Pairing-Friendly Fields.pdf; Section 3 (Complex)
141 
142  const my_Fp2 &b = this->coeffs[1], &a = this->coeffs[0];
143  const my_Fp2 ab = a * b;
144 
145  return Fp4_model<n, modulus>(
146  (a + b) * (a + Fp4_model<n, modulus>::mul_by_non_residue(b)) - ab -
147  Fp4_model<n, modulus>::mul_by_non_residue(ab),
148  ab + ab);
149 }
150 
151 template<mp_size_t n, const bigint<n> &modulus>
152 Fp4_model<n, modulus> Fp4_model<n, modulus>::inverse() const
153 {
154  // From "High-Speed Software Implementation of the Optimal Ate Pairing over
155  // Barreto-Naehrig Curves"; Algorithm 8
156  const my_Fp2 &b = this->coeffs[1], &a = this->coeffs[0];
157  const my_Fp2 t1 = b.squared();
158  const my_Fp2 t0 =
159  a.squared() - Fp4_model<n, modulus>::mul_by_non_residue(t1);
160  const my_Fp2 new_t1 = t0.inverse();
161 
162  return Fp4_model<n, modulus>(a * new_t1, -(b * new_t1));
163 }
164 
165 template<mp_size_t n, const bigint<n> &modulus>
166 Fp4_model<n, modulus> Fp4_model<n, modulus>::Frobenius_map(
167  unsigned long power) const
168 {
169  return Fp4_model<n, modulus>(
170  coeffs[0].Frobenius_map(power),
171  Frobenius_coeffs_c1[power % 4] * coeffs[1].Frobenius_map(power));
172 }
173 
174 template<mp_size_t n, const bigint<n> &modulus>
175 Fp4_model<n, modulus> Fp4_model<n, modulus>::unitary_inverse() const
176 {
177  return Fp4_model<n, modulus>(this->coeffs[0], -this->coeffs[1]);
178 }
179 
180 template<mp_size_t n, const bigint<n> &modulus>
181 Fp4_model<n, modulus> Fp4_model<n, modulus>::cyclotomic_squared() const
182 {
183  const my_Fp2 A = this->coeffs[1].squared();
184  const my_Fp2 B = this->coeffs[1] + this->coeffs[0];
185  const my_Fp2 C = B.squared() - A;
186  // Fp2(A.coeffs[1] * non_residue, A.coeffs[0])
187  const my_Fp2 D = Fp4_model<n, modulus>::mul_by_non_residue(A);
188  const my_Fp2 E = C - D;
189  const my_Fp2 F = D + D + my_Fp2::one();
190  const my_Fp2 G = E - my_Fp2::one();
191 
192  return Fp4_model<n, modulus>(F, G);
193 }
194 
195 template<mp_size_t n, const bigint<n> &modulus>
196 template<mp_size_t m>
197 Fp4_model<n, modulus> Fp4_model<n, modulus>::cyclotomic_exp(
198  const bigint<m> &exponent) const
199 {
200  Fp4_model<n, modulus> res = Fp4_model<n, modulus>::one();
201  Fp4_model<n, modulus> this_inverse = this->unitary_inverse();
202 
203  bool found_nonzero = false;
204  std::vector<long> NAF = find_wnaf(1, exponent);
205 
206  for (long i = static_cast<long>(NAF.size() - 1); i >= 0; --i) {
207  if (found_nonzero) {
208  res = res.cyclotomic_squared();
209  }
210 
211  if (NAF[i] != 0) {
212  found_nonzero = true;
213 
214  if (NAF[i] > 0) {
215  res = res * (*this);
216  } else {
217  res = res * this_inverse;
218  }
219  }
220  }
221 
222  return res;
223 }
224 
225 template<mp_size_t n, const bigint<n> &modulus, mp_size_t m>
226 Fp4_model<n, modulus> operator^(
227  const Fp4_model<n, modulus> &self, const bigint<m> &exponent)
228 {
229  return power<Fp4_model<n, modulus>>(self, exponent);
230 }
231 
232 template<
233  mp_size_t n,
234  const bigint<n> &modulus,
235  mp_size_t m,
236  const bigint<m> &modulus_p>
237 Fp4_model<n, modulus> operator^(
238  const Fp4_model<n, modulus> &self, const Fp_model<m, modulus_p> &exponent)
239 {
240  return self ^ (exponent.as_bigint());
241 }
242 
243 template<mp_size_t n, const bigint<n> &modulus>
244 std::ostream &operator<<(std::ostream &out, const Fp4_model<n, modulus> &el)
245 {
246  out << el.coeffs[0] << OUTPUT_SEPARATOR << el.coeffs[1];
247  return out;
248 }
249 
250 template<mp_size_t n, const bigint<n> &modulus>
251 std::istream &operator>>(std::istream &in, Fp4_model<n, modulus> &el)
252 {
253  in >> el.coeffs[0] >> el.coeffs[1];
254  return in;
255 }
256 
257 } // namespace libff
258 
259 #endif // FP4_TCC_