detail/element/fp6_2over3.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_FP6_2OVER3_HPP
27 #define CRYPTO3_ALGEBRA_FIELDS_ELEMENT_FP6_2OVER3_HPP
28 
31 
32 #include <nil/crypto3/multiprecision/wnaf.hpp>
33 
34 namespace nil {
35  namespace crypto3 {
36  namespace algebra {
37  namespace fields {
38  namespace detail {
39 
40  template<typename FieldParams>
42  typedef FieldParams policy_type;
43 
44  public:
45  typedef typename policy_type::non_residue_type non_residue_type;
46  constexpr static const non_residue_type non_residue = policy_type::non_residue;
47 
48  typedef typename policy_type::underlying_type underlying_type;
49 
50  using data_type = std::array<underlying_type, 2>;
51 
53 
54  constexpr element_fp6_2over3() {
55  data = data_type({underlying_type::zero(), underlying_type::zero()});
56  }
57 
58  constexpr element_fp6_2over3(underlying_type in_data0, underlying_type in_data1) {
59  data = data_type({in_data0, in_data1});
60  }
61 
62  constexpr element_fp6_2over3(const data_type &in_data) {
63  data = data_type({in_data[0], in_data[1]});
64  };
65 
66  constexpr element_fp6_2over3(const element_fp6_2over3 &B) : data {B.data} {};
67 
68  constexpr inline static element_fp6_2over3 zero() {
69  return element_fp6_2over3(underlying_type::zero(), underlying_type::zero());
70  }
71 
72  constexpr inline static element_fp6_2over3 one() {
73  return element_fp6_2over3(underlying_type::one(), underlying_type::zero());
74  }
75 
76  constexpr bool operator==(const element_fp6_2over3 &B) const {
77  return (data[0] == B.data[0]) && (data[1] == B.data[1]);
78  }
79 
80  constexpr bool operator!=(const element_fp6_2over3 &B) const {
81  return (data[0] != B.data[0]) || (data[1] != B.data[1]);
82  }
83 
85  data[0] = B.data[0];
86  data[1] = B.data[1];
87 
88  return *this;
89  }
90 
91  constexpr element_fp6_2over3 operator+(const element_fp6_2over3 &B) const {
92  return element_fp6_2over3(data[0] + B.data[0], data[1] + B.data[1]);
93  }
94 
95  constexpr element_fp6_2over3 doubled() const {
96  return element_fp6_2over3(data[0].doubled(), data[1].doubled());
97  }
98 
99  constexpr element_fp6_2over3 operator-(const element_fp6_2over3 &B) const {
100  return element_fp6_2over3(data[0] - B.data[0], data[1] - B.data[1]);
101  }
102 
104  data[0] -= B.data[0];
105  data[1] -= B.data[1];
106 
107  return *this;
108  }
109 
111  data[0] += B.data[0];
112  data[1] += B.data[1];
113 
114  return *this;
115  }
116 
117  constexpr element_fp6_2over3 operator-() const {
118  return zero() - *this;
119  }
120 
121  constexpr element_fp6_2over3 operator*(const element_fp6_2over3 &B) const {
122  const underlying_type A0B0 = data[0] * B.data[0], A1B1 = data[1] * B.data[1];
123 
124  return element_fp6_2over3(A0B0 + mul_by_non_residue(A1B1),
125  (data[0] + data[1]) * (B.data[0] + B.data[1]) - A0B0 - A1B1);
126  }
127 
129 
130  // compute squared root with Tonelli--Shanks
131  }
132 
133  constexpr element_fp6_2over3 squared() const {
134  // return (*this) * (*this); // maybe can be done more effective
135 
136  /* Devegili OhEig Scott Dahab --- Multiplication and Squaring on Pairing-Friendly
137  * Fields.pdf; Section 3 (Complex) */
138  const underlying_type &B = data[1], &A = data[0];
139  const underlying_type AB = A * B;
140 
141  return element_fp6_2over3(
142  (A + B) * (A + mul_by_non_residue(B)) - AB - mul_by_non_residue(AB), AB + AB);
143  }
144 
145  template<typename PowerType>
146  constexpr element_fp6_2over3 pow(const PowerType &pwr) const {
147  return element_fp6_2over3(power(*this, pwr));
148  }
149 
150  constexpr element_fp6_2over3 inversed() const {
151 
152  /* From "High-Speed Software Implementation of the Optimal Ate Pairing over Barreto-Naehrig
153  * Curves"; Algorithm 8 */
154 
155  const underlying_type &A0 = data[0], &A1 = data[1];
156 
157  const underlying_type t0 = A0.squared();
158  const underlying_type t1 = A1.squared();
159  const underlying_type t2 = t0 - mul_by_non_residue(t1);
160  const underlying_type t3 = t2.inversed();
161  const underlying_type c0 = A0 * t3;
162  const underlying_type c1 = -(A1 * t3);
163 
164  return element_fp6_2over3(c0, c1);
165  }
166 
167  template<typename PowerType>
168  constexpr element_fp6_2over3 Frobenius_map(const PowerType &pwr) const {
169  // return element_fp6_2over3(data[0].Frobenius_map(pwr),
170  // policy_type::Frobenius_coeffs_c1[pwr % 6] *
171  // data[1].Frobenius_map(pwr)});
172  return element_fp6_2over3(
173  data[0].Frobenius_map(pwr),
174  typename policy_type::non_residue_type(policy_type::Frobenius_coeffs_c1[pwr % 6]) *
175  data[1].Frobenius_map(pwr));
176  }
177 
179  return element_fp6_2over3(data[0], -data[1]);
180  }
181 
183  using e_fp = typename underlying_type::underlying_type;
184  using e_fp2 = std::array<e_fp, 2>;
185 
186  auto fp2_squared = [&](const e_fp &A, const e_fp &B) {
187  /* Devegili OhEig Scott Dahab --- Multiplication and Squaring on Pairing-Friendly
188  * Fields.pdf; Section 3 (Complex squaring) */
189  const e_fp AB = A * B;
190 
191  return e_fp2 {(A + B) * (A + non_residue * B) - AB - non_residue * AB, AB + AB};
192  };
193 
194  // e_fp2 a(data[0].data[0], data[1].data[1]);
195  // e_fp2 b(data[1].data[0], data[0].data[2]);
196  // e_fp2 c(data[0].data[1], data[1].data[2]);
197  //
198  // e_fp2 asq = a.squared();
199  // e_fp2 bsq = b.squared();
200  // e_fp2 csq = c.squared();
201  e_fp2 asq = fp2_squared(data[0].data[0], data[1].data[1]);
202  e_fp2 bsq = fp2_squared(data[1].data[0], data[0].data[2]);
203  e_fp2 csq = fp2_squared(data[0].data[1], data[1].data[2]);
204 
205  // A = vector(3*a^2 - 2*Fp2([vector(a)[0],-vector(a)[1]]))
206  // my_Fp A_a = my_Fp(3l) * asq_a - my_Fp(2l) * a_a;
207  e_fp A_a = asq[0] - data[0].data[0];
208  A_a = A_a + A_a + asq[0];
209  // my_Fp A_b = my_Fp(3l) * asq_b + my_Fp(2l) * a_b;
210  e_fp A_b = asq[1] + data[1].data[1];
211  A_b = A_b + A_b + asq[1];
212 
213  // B = vector(3*Fp2([non_residue*c2[1],c2[0]]) + 2*Fp2([vector(b)[0],-vector(b)[1]]))
214  // my_Fp B_a = my_Fp(3l) * underlying_type::non_residue * csq_b + my_Fp(2l) * b_a;
215  e_fp B_tmp = non_residue * csq[1];
216  e_fp B_a = B_tmp + data[1].data[0];
217  B_a = B_a + B_a + B_tmp;
218 
219  // my_Fp B_b = my_Fp(3l) * csq_a - my_Fp(2l) * b_b;
220  e_fp B_b = csq[0] - data[0].data[2];
221  B_b = B_b + B_b + csq[0];
222 
223  // C = vector(3*b^2 - 2*Fp2([vector(c)[0],-vector(c)[1]]))
224  // my_Fp C_a = my_Fp(3l) * bsq_a - my_Fp(2l) * c_a;
225  e_fp C_a = bsq[0] - data[0].data[1];
226  C_a = C_a + C_a + bsq[0];
227  // my_Fp C_b = my_Fp(3l) * bsq_b + my_Fp(2l) * c_b;
228  e_fp C_b = bsq[1] + data[1].data[2];
229  C_b = C_b + C_b + bsq[1];
230 
231  return element_fp6_2over3(underlying_type(A_a, C_a, B_b), underlying_type(B_a, A_b, C_b));
232  }
233 
234  template<typename PowerType>
235  element_fp6_2over3 cyclotomic_exp(const PowerType &exponent) const {
236  // naive implementation
237  // return this->squared();
238 
239  element_fp6_2over3 res = one();
240  element_fp6_2over3 this_inverse = this->unitary_inversed();
241 
242  bool found_nonzero = false;
243  std::vector<long> NAF = nil::crypto3::multiprecision::find_wnaf(1, exponent);
244 
245  for (long i = static_cast<long>(NAF.size() - 1); i >= 0; --i) {
246  if (found_nonzero) {
247  res = res.cyclotomic_squared();
248  }
249 
250  if (NAF[i] != 0) {
251  found_nonzero = true;
252 
253  if (NAF[i] > 0) {
254  res = res * (*this);
255  } else {
256  res = res * this_inverse;
257  }
258  }
259  }
260 
261  return res;
262  }
263 
264  constexpr /*inline static*/ underlying_type mul_by_non_residue(const underlying_type &A) const {
265  return underlying_type(non_residue * A.data[2], A.data[0], A.data[1]);
266  }
267 
269  /* Devegili OhEig Scott Dahab --- Multiplication and Squaring on Pairing-Friendly
270  * Fields.pdf; Section 3 (Karatsuba) */
271 
272  const underlying_type &B = other.data[1], &A = other.data[0], &b = this->data[1],
273  &a = this->data[0];
274  const underlying_type aA = underlying_type(a.data[1] * A.data[2] * non_residue,
275  a.data[2] * A.data[2] * non_residue,
276  a.data[0] * A.data[2]);
277  const underlying_type bB = b * B;
279 
280  return element_fp6_2over3(aA + beta_bB, (a + b) * (A + B) - aA - bB);
281  }
282  };
283 
284  template<typename FieldParams>
285  constexpr element_fp6_2over3<FieldParams>
286  operator*(const typename FieldParams::underlying_type::underlying_type &lhs,
287  const element_fp6_2over3<FieldParams> &rhs) {
288 
289  return element_fp6_2over3<FieldParams>(lhs * rhs.data[0], lhs * rhs.data[1]);
290  }
291 
292  template<typename FieldParams>
293  constexpr element_fp6_2over3<FieldParams>
295  const typename FieldParams::underlying_type::underlying_type &rhs) {
296 
297  return rhs * lhs;
298  }
299 
300  template<typename FieldParams>
303 
304  } // namespace detail
305  } // namespace fields
306  } // namespace algebra
307  } // namespace crypto3
308 } // namespace nil
309 
310 #endif // CRYPTO3_ALGEBRA_FIELDS_ELEMENT_FP6_2OVER3_HPP
Definition: detail/element/fp6_2over3.hpp:41
constexpr static element_fp6_2over3 zero()
Definition: detail/element/fp6_2over3.hpp:68
constexpr element_fp6_2over3(const element_fp6_2over3 &B)
Definition: detail/element/fp6_2over3.hpp:66
constexpr element_fp6_2over3 squared() const
Definition: detail/element/fp6_2over3.hpp:133
constexpr element_fp6_2over3 unitary_inversed() const
Definition: detail/element/fp6_2over3.hpp:178
policy_type::non_residue_type non_residue_type
Definition: detail/element/fp6_2over3.hpp:45
constexpr element_fp6_2over3 operator-(const element_fp6_2over3 &B) const
Definition: detail/element/fp6_2over3.hpp:99
data_type data
Definition: detail/element/fp6_2over3.hpp:52
constexpr element_fp6_2over3 & operator=(const element_fp6_2over3 &B)
Definition: detail/element/fp6_2over3.hpp:84
constexpr bool operator!=(const element_fp6_2over3 &B) const
Definition: detail/element/fp6_2over3.hpp:80
constexpr static element_fp6_2over3 one()
Definition: detail/element/fp6_2over3.hpp:72
constexpr element_fp6_2over3 operator+(const element_fp6_2over3 &B) const
Definition: detail/element/fp6_2over3.hpp:91
constexpr bool operator==(const element_fp6_2over3 &B) const
Definition: detail/element/fp6_2over3.hpp:76
constexpr element_fp6_2over3 operator*(const element_fp6_2over3 &B) const
Definition: detail/element/fp6_2over3.hpp:121
constexpr element_fp6_2over3()
Definition: detail/element/fp6_2over3.hpp:54
policy_type::underlying_type underlying_type
Definition: detail/element/fp6_2over3.hpp:48
element_fp6_2over3 cyclotomic_exp(const PowerType &exponent) const
Definition: detail/element/fp6_2over3.hpp:235
constexpr element_fp6_2over3(const data_type &in_data)
Definition: detail/element/fp6_2over3.hpp:62
constexpr element_fp6_2over3 pow(const PowerType &pwr) const
Definition: detail/element/fp6_2over3.hpp:146
std::array< underlying_type, 2 > data_type
Definition: detail/element/fp6_2over3.hpp:50
constexpr element_fp6_2over3 Frobenius_map(const PowerType &pwr) const
Definition: detail/element/fp6_2over3.hpp:168
constexpr static const non_residue_type non_residue
Definition: detail/element/fp6_2over3.hpp:46
constexpr element_fp6_2over3 & operator-=(const element_fp6_2over3 &B)
Definition: detail/element/fp6_2over3.hpp:103
element_fp6_2over3 mul_by_2345(const element_fp6_2over3 &other) const
Definition: detail/element/fp6_2over3.hpp:268
constexpr element_fp6_2over3 doubled() const
Definition: detail/element/fp6_2over3.hpp:95
element_fp6_2over3 cyclotomic_squared() const
Definition: detail/element/fp6_2over3.hpp:182
constexpr element_fp6_2over3(underlying_type in_data0, underlying_type in_data1)
Definition: detail/element/fp6_2over3.hpp:58
element_fp6_2over3 sqrt() const
Definition: detail/element/fp6_2over3.hpp:128
constexpr element_fp6_2over3 operator-() const
Definition: detail/element/fp6_2over3.hpp:117
constexpr underlying_type mul_by_non_residue(const underlying_type &A) const
Definition: detail/element/fp6_2over3.hpp:264
constexpr element_fp6_2over3 & operator+=(const element_fp6_2over3 &B)
Definition: detail/element/fp6_2over3.hpp:110
constexpr element_fp6_2over3 inversed() const
Definition: detail/element/fp6_2over3.hpp:150
constexpr FieldValueType power(const FieldValueType &base, const NumberType &exponent)
Definition: algebra/include/nil/crypto3/algebra/fields/detail/exponentiation.hpp:41
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