detail/element/fp2.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2020-2021 Mikhail Komarov <nemo@nil.foundation>
3 // Copyright (c) 2020-2021 Nikita Kaskov <nbering@nil.foundation>
4 //
5 // MIT License
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy
8 // of this software and associated documentation files (the "Software"), to deal
9 // in the Software without restriction, including without limitation the rights
10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 // copies of the Software, and to permit persons to whom the Software is
12 // furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in all
15 // copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 // SOFTWARE.
24 //---------------------------------------------------------------------------//
25 
26 #ifndef CRYPTO3_ALGEBRA_FIELDS_ELEMENT_FP2_HPP
27 #define CRYPTO3_ALGEBRA_FIELDS_ELEMENT_FP2_HPP
28 
31 
32 namespace nil {
33  namespace crypto3 {
34  namespace algebra {
35  namespace fields {
36  namespace detail {
37 
38  template<typename FieldParams>
39  class element_fp2 {
40  typedef FieldParams policy_type;
41 
42  typedef typename policy_type::integral_type integral_type;
43 
44  constexpr static const integral_type modulus = policy_type::modulus;
45 
46  public:
47  typedef typename policy_type::field_type field_type;
48 
49  typedef typename policy_type::non_residue_type non_residue_type;
50  constexpr static const non_residue_type non_residue = policy_type::non_residue;
51 
52  typedef typename policy_type::underlying_type underlying_type;
53 
54  using data_type = std::array<underlying_type, 2>;
55 
57 
58  constexpr element_fp2() {
59  data = data_type({underlying_type::zero(), underlying_type::zero()});
60  }
61 
62  template<typename Number1, typename Number2>
63  constexpr element_fp2(const Number1 &in_data0, const Number2 &in_data1) {
64  data = data_type({underlying_type(in_data0), underlying_type(in_data1)});
65  }
66 
67  constexpr element_fp2(const data_type &in_data) {
68  data = data_type({in_data[0], in_data[1]});
69  };
70 
71  constexpr element_fp2(const underlying_type &in_data0, const underlying_type &in_data1) {
72  data = data_type({in_data0, in_data1});
73  }
74 
75  constexpr element_fp2(const element_fp2 &B) : data {B.data} {};
76 
77  constexpr inline static element_fp2 zero() {
78  return element_fp2(underlying_type::zero(), underlying_type::zero());
79  }
80 
81  constexpr inline static element_fp2 one() {
82  return element_fp2(underlying_type::one(), underlying_type::zero());
83  }
84 
85  constexpr bool is_zero() const {
86  return (data[0] == underlying_type::zero()) && (data[1] == underlying_type::zero());
87  }
88 
89  constexpr bool is_one() const {
90  return (data[0] == underlying_type::one()) && (data[1] == underlying_type::zero());
91  }
92 
93  constexpr bool operator==(const element_fp2 &B) const {
94  return (data[0] == B.data[0]) && (data[1] == B.data[1]);
95  }
96 
97  constexpr bool operator!=(const element_fp2 &B) const {
98  return (data[0] != B.data[0]) || (data[1] != B.data[1]);
99  }
100 
101  constexpr element_fp2 &operator=(const element_fp2 &B) {
102  data[0] = B.data[0];
103  data[1] = B.data[1];
104 
105  return *this;
106  }
107 
108  constexpr element_fp2 operator+(const element_fp2 &B) const {
109  return element_fp2(data[0] + B.data[0], data[1] + B.data[1]);
110  }
111 
112  constexpr element_fp2 operator-(const element_fp2 &B) const {
113  return element_fp2(data[0] - B.data[0], data[1] - B.data[1]);
114  }
115 
116  constexpr element_fp2 &operator-=(const element_fp2 &B) {
117  data[0] -= B.data[0];
118  data[1] -= B.data[1];
119 
120  return *this;
121  }
122 
123  constexpr element_fp2 &operator+=(const element_fp2 &B) {
124  data[0] += B.data[0];
125  data[1] += B.data[1];
126 
127  return *this;
128  }
129 
130  constexpr element_fp2 operator-() const {
131  return zero() - *this;
132  }
133 
134  constexpr element_fp2 operator*(const element_fp2 &B) const {
135  // TODO: the use of data and B.data directly in return statement addition cause constexpr
136  // error for gcc
137  const underlying_type A0 = data[0], A1 = data[1], B0 = B.data[0], B1 = B.data[1];
138  const underlying_type A0B0 = data[0] * B.data[0], A1B1 = data[1] * B.data[1];
139 
140  return element_fp2(A0B0 + non_residue * A1B1, (A0 + A1) * (B0 + B1) - A0B0 - A1B1);
141  }
142 
143  constexpr element_fp2 &operator*=(const element_fp2 &B) {
144  *this = *this * B;
145 
146  return *this;
147  }
148 
149  constexpr element_fp2 operator/(const element_fp2 &B) const {
150  return *this * B.inversed();
151  }
152 
153  /*
154  For pairing bn128
155  XITAG
156  u^2 = -1
157  xi = 9 + u
158  (a + bu)(9 + u) = (9a - b) + (a + 9b)u
159  */
161  return element_fp2(data[0].doubled().doubled().doubled() + data[0] - data[1],
162  data[1].doubled().doubled().doubled() + data[1] + data[0]);
163  }
164 
165  /*
166  u^2 = -1
167  (a + b)u = -b + au
168 
169  1 * Fp neg
170  */
171  constexpr element_fp2 mul_x() {
172  return element_fp2(-data[1], data[0]);
173  }
174 
175  // z = x * b
176  constexpr element_fp2 mul_Fp_0(const underlying_type &b) {
177  return element_fp2(data[0] * b, data[1] * b);
178  }
179 
180  /*
181  (a + bu)cu = -bc + acu,
182  where u is u^2 = -1.
183 
184  2 * Fp mul
185  1 * Fp neg
186  */
187  constexpr element_fp2 mul_Fp_1(const underlying_type &y_b) {
188  return element_fp2(-(data[1] * y_b), data[0] * y_b);
189  }
190 
191  constexpr element_fp2 _2z_add_3x() {
192  return element_fp2(data[0]._2z_add_3x(), data[1]._2z_add_3x());
193  }
194 
195  constexpr element_fp2 divBy2() const {
196  return element_fp2(divBy2(data[0]), divBy2(data[1]));
197  }
198 
199  constexpr element_fp2 divBy4() const {
200  return element_fp2(divBy4(data[0]), divBy4(data[1]));
201  }
202 
203  constexpr element_fp2 doubled() const {
204  return element_fp2(data[0].doubled(), data[1].doubled());
205  }
206 
207  constexpr element_fp2 sqrt() const {
208 
209  element_fp2 one = this->one();
210 
211  std::size_t v = policy_type::s;
212  element_fp2 z(policy_type::nqr_to_t[0], policy_type::nqr_to_t[1]);
213  element_fp2 w = this->pow(policy_type::t_minus_1_over_2);
214  element_fp2 x((*this) * w);
215  element_fp2 b = x * w; // b = (*this)^t
216 
217  // compute square root with Tonelli--Shanks
218  // (does not terminate if not a square!)
219 
220  while (b != one) {
221  std::size_t m = 0;
222  element_fp2 b2m = b;
223  while (b2m != one) {
224  /* invariant: b2m = b^(2^m) after entering this loop */
225  b2m = b2m.squared();
226  m += 1;
227  }
228 
229  int j = v - m - 1;
230  w = z;
231  while (j > 0) {
232  w = w.squared();
233  --j;
234  } // w = z^2^(v-m-1)
235 
236  z = w.squared();
237  b = b * z;
238  x = x * w;
239  v = m;
240  }
241 
242  return x;
243  }
244 
245  constexpr element_fp2 squared() const {
246  // return (*this) * (*this); // maybe can be done more effective
247 
248  /* Devegili OhEig Scott Dahab --- Multiplication and Squaring on Pairing-Friendly
249  * Fields.pdf; Section 3 (Complex squaring) */
250  // TODO: reference here could cause error in constexpr for gcc
251  const underlying_type A = data[0], B = data[1];
252  const underlying_type AB = A * B;
253 
254  return element_fp2((A + B) * (A + non_residue * B) - AB - non_residue * AB, AB + AB);
255  }
256 
257  constexpr bool is_square() const {
258  element_fp2 tmp = this->pow(policy_type::group_order);
259  return (tmp.is_one() || tmp.is_zero()); // maybe can be done more effective
260  }
261 
262  template<typename PowerType>
263  constexpr element_fp2 pow(const PowerType &pwr) const {
264  return element_fp2(power(*this, pwr));
265  }
266 
267  constexpr element_fp2 inversed() const {
268 
269  /* From "High-Speed Software Implementation of the Optimal Ate Pairing over Barreto-Naehrig
270  * Curves"; Algorithm 8 */
271 
272  const underlying_type &A0 = data[0], &A1 = data[1];
273 
274  const underlying_type t0 = A0.squared();
275  const underlying_type t1 = A1.squared();
276  const underlying_type t2 = t0 - non_residue * t1;
277  const underlying_type t3 = t2.inversed();
278  const underlying_type c0 = A0 * t3;
279  const underlying_type c1 = -(A1 * t3);
280 
281  return element_fp2(c0, c1);
282  }
283 
284  template<typename PowerType>
285  constexpr element_fp2 Frobenius_map(const PowerType &pwr) const {
286  return element_fp2(
287  data[0],
288  typename policy_type::non_residue_type(policy_type::Frobenius_coeffs_c1[pwr % 2]) *
289  data[1]);
290  // return element_fp2(data[0], policy_type::Frobenius_coeffs_c1[pwr % 2] * data[1]});
291  }
292  };
293 
294  template<typename FieldParams>
295  constexpr element_fp2<FieldParams> operator*(const typename FieldParams::underlying_type &lhs,
296  const element_fp2<FieldParams> &rhs) {
297  return element_fp2<FieldParams>(lhs * rhs.data[0], lhs * rhs.data[1]);
298  }
299 
300  template<typename FieldParams>
302  const typename FieldParams::underlying_type &rhs) {
303  return rhs * lhs;
304  }
305 
306  template<typename FieldParams>
308  const element_fp2<FieldParams> &B) {
309  }
310 
311  template<typename FieldParams>
313  const element_fp2<FieldParams> &B) {
314  }
315 
316  template<typename FieldParams>
317  constexpr const typename element_fp2<FieldParams>::non_residue_type
319 
320  } // namespace detail
321  } // namespace fields
322  } // namespace algebra
323  } // namespace crypto3
324 } // namespace nil
325 
326 #endif // CRYPTO3_ALGEBRA_FIELDS_ELEMENT_FP2_HPP
Definition: detail/element/fp2.hpp:39
std::array< underlying_type, 2 > data_type
Definition: detail/element/fp2.hpp:54
element_fp2 mul_xi()
Definition: detail/element/fp2.hpp:160
constexpr element_fp2 pow(const PowerType &pwr) const
Definition: detail/element/fp2.hpp:263
policy_type::underlying_type underlying_type
Definition: detail/element/fp2.hpp:52
constexpr element_fp2 doubled() const
Definition: detail/element/fp2.hpp:203
constexpr element_fp2(const data_type &in_data)
Definition: detail/element/fp2.hpp:67
constexpr element_fp2 operator*(const element_fp2 &B) const
Definition: detail/element/fp2.hpp:134
constexpr element_fp2 operator-() const
Definition: detail/element/fp2.hpp:130
constexpr bool is_one() const
Definition: detail/element/fp2.hpp:89
constexpr static element_fp2 zero()
Definition: detail/element/fp2.hpp:77
constexpr element_fp2 sqrt() const
Definition: detail/element/fp2.hpp:207
constexpr element_fp2 & operator-=(const element_fp2 &B)
Definition: detail/element/fp2.hpp:116
policy_type::non_residue_type non_residue_type
Definition: detail/element/fp2.hpp:49
data_type data
Definition: detail/element/fp2.hpp:56
constexpr static element_fp2 one()
Definition: detail/element/fp2.hpp:81
constexpr element_fp2(const underlying_type &in_data0, const underlying_type &in_data1)
Definition: detail/element/fp2.hpp:71
constexpr bool is_square() const
Definition: detail/element/fp2.hpp:257
constexpr element_fp2()
Definition: detail/element/fp2.hpp:58
constexpr element_fp2 & operator*=(const element_fp2 &B)
Definition: detail/element/fp2.hpp:143
constexpr element_fp2 divBy4() const
Definition: detail/element/fp2.hpp:199
constexpr bool operator!=(const element_fp2 &B) const
Definition: detail/element/fp2.hpp:97
constexpr element_fp2 operator+(const element_fp2 &B) const
Definition: detail/element/fp2.hpp:108
constexpr element_fp2 divBy2() const
Definition: detail/element/fp2.hpp:195
constexpr element_fp2 squared() const
Definition: detail/element/fp2.hpp:245
constexpr element_fp2 operator-(const element_fp2 &B) const
Definition: detail/element/fp2.hpp:112
constexpr element_fp2 mul_Fp_0(const underlying_type &b)
Definition: detail/element/fp2.hpp:176
constexpr bool is_zero() const
Definition: detail/element/fp2.hpp:85
constexpr element_fp2(const element_fp2 &B)
Definition: detail/element/fp2.hpp:75
constexpr element_fp2 Frobenius_map(const PowerType &pwr) const
Definition: detail/element/fp2.hpp:285
constexpr element_fp2 & operator+=(const element_fp2 &B)
Definition: detail/element/fp2.hpp:123
constexpr bool operator==(const element_fp2 &B) const
Definition: detail/element/fp2.hpp:93
constexpr element_fp2(const Number1 &in_data0, const Number2 &in_data1)
Definition: detail/element/fp2.hpp:63
constexpr element_fp2 operator/(const element_fp2 &B) const
Definition: detail/element/fp2.hpp:149
constexpr element_fp2 _2z_add_3x()
Definition: detail/element/fp2.hpp:191
constexpr element_fp2 mul_Fp_1(const underlying_type &y_b)
Definition: detail/element/fp2.hpp:187
constexpr element_fp2 & operator=(const element_fp2 &B)
Definition: detail/element/fp2.hpp:101
policy_type::field_type field_type
Definition: detail/element/fp2.hpp:47
constexpr static const non_residue_type non_residue
Definition: detail/element/fp2.hpp:50
constexpr element_fp2 inversed() const
Definition: detail/element/fp2.hpp:267
constexpr element_fp2 mul_x()
Definition: detail/element/fp2.hpp:171
constexpr element_fp2< FieldParams > addNC(const element_fp2< FieldParams > &A, const element_fp2< FieldParams > &B)
Definition: detail/element/fp2.hpp:307
constexpr FieldValueType power(const FieldValueType &base, const NumberType &exponent)
Definition: algebra/include/nil/crypto3/algebra/fields/detail/exponentiation.hpp:41
constexpr element_fp2< FieldParams > subNC(const element_fp2< FieldParams > &A, const element_fp2< FieldParams > &B)
Definition: detail/element/fp2.hpp:312
element_fp12_2over3over2< FieldParams > operator*(const typename FieldParams::underlying_type::underlying_type::underlying_type &lhs, const element_fp12_2over3over2< FieldParams > &rhs)
Definition: detail/element/fp12_2over3over2.hpp:364
Definition: pair.hpp:31