detail/element/fp4.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_FP4_HPP
27 #define CRYPTO3_ALGEBRA_FIELDS_ELEMENT_FP4_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>
41  class element_fp4 {
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_fp4() {
55  data = data_type({underlying_type::zero(), underlying_type::zero()});
56  }
57 
58  constexpr element_fp4(underlying_type in_data0, underlying_type in_data1) {
59  data = data_type({in_data0, in_data1});
60  }
61 
62  constexpr element_fp4(const data_type &in_data) {
63  data = data_type({in_data[0], in_data[1]});
64  };
65 
66  constexpr element_fp4(const element_fp4 &B) : data {B.data} {};
67 
68  constexpr inline static element_fp4 zero() {
69  return element_fp4(underlying_type::zero(), underlying_type::zero());
70  }
71 
72  constexpr inline static element_fp4 one() {
73  return element_fp4(underlying_type::one(), underlying_type::zero());
74  }
75 
76  constexpr bool operator==(const element_fp4 &B) const {
77  return (data[0] == B.data[0]) && (data[1] == B.data[1]);
78  }
79 
80  constexpr bool operator!=(const element_fp4 &B) const {
81  return (data[0] != B.data[0]) || (data[1] != B.data[1]);
82  }
83 
84  constexpr element_fp4 &operator=(const element_fp4 &B) {
85  data[0] = B.data[0];
86  data[1] = B.data[1];
87 
88  return *this;
89  }
90 
91  constexpr element_fp4 operator+(const element_fp4 &B) const {
92  return element_fp4(data[0] + B.data[0], data[1] + B.data[1]);
93  }
94 
95  constexpr element_fp4 doubled() const {
96  return element_fp4(data[0].doubled(), data[1].doubled());
97  }
98 
99  constexpr element_fp4 operator-(const element_fp4 &B) const {
100  return element_fp4(data[0] - B.data[0], data[1] - B.data[1]);
101  }
102 
103  constexpr element_fp4 &operator-=(const element_fp4 &B) {
104  data[0] -= B.data[0];
105  data[1] -= B.data[1];
106 
107  return *this;
108  }
109 
110  constexpr element_fp4 &operator+=(const element_fp4 &B) {
111  data[0] += B.data[0];
112  data[1] += B.data[1];
113 
114  return *this;
115  }
116 
117  constexpr element_fp4 operator-() const {
118  return zero() - *this;
119  }
120 
121  constexpr element_fp4 operator*(const element_fp4 &B) const {
122  const underlying_type A0B0 = data[0] * B.data[0], A1B1 = data[1] * B.data[1];
123 
124  return element_fp4(A0B0 + mul_by_non_residue(A1B1),
125  (data[0] + data[1]) * (B.data[0] + B.data[1]) - A0B0 - A1B1);
126  }
127 
128  element_fp4 sqrt() const {
129 
130  // compute squared root with Tonelli--Shanks
131  }
132 
133  constexpr element_fp4 squared() const {
134  return (*this) * (*this); // maybe can be done more effective
135  }
136 
137  template<typename PowerType>
138  constexpr element_fp4 pow(const PowerType &pwr) const {
139  return element_fp4(power(*this, pwr));
140  }
141 
142  constexpr element_fp4 inversed() const {
143 
144  /* From "High-Speed Software Implementation of the Optimal Ate Pairing over Barreto-Naehrig
145  * Curves"; Algorithm 8 */
146 
147  const underlying_type &A0 = data[0], &A1 = data[1];
148 
149  const underlying_type t0 = A0.squared();
150  const underlying_type t1 = A1.squared();
151  const underlying_type t2 = t0 - mul_by_non_residue(t1);
152  const underlying_type t3 = t2.inversed();
153  const underlying_type c0 = A0 * t3;
154  const underlying_type c1 = -(A1 * t3);
155 
156  return element_fp4(c0, c1);
157  }
158 
159  template<typename PowerType>
160  constexpr element_fp4 Frobenius_map(const PowerType &pwr) const {
161  return element_fp4(
162  data[0].Frobenius_map(pwr),
163  typename policy_type::non_residue_type(policy_type::Frobenius_coeffs_c1[pwr % 4]) *
164  data[1].Frobenius_map(pwr));
165  // return element_fp4(data[0].Frobenius_map(pwr),
166  // policy_type::Frobenius_coeffs_c1[pwr % 4] *
167  // data[1].Frobenius_map(pwr)});
168  }
169 
171  return element_fp4(data[0], -data[1]);
172  }
173 
175  const underlying_type A = data[1].squared();
176  const underlying_type B = data[0] + data[1];
177  const underlying_type C = B.squared() - A;
178  const underlying_type D = mul_by_non_residue(A); // Fp2(A.c1 * non_residue, A.c0)
179  const underlying_type E = C - D;
180  const underlying_type F = D + D + underlying_type::one();
181  const underlying_type G = E - underlying_type::one();
182 
183  return element_fp4(F, G);
184  }
185 
186  template<typename PowerType>
187  element_fp4 cyclotomic_exp(const PowerType &exponent) const {
188  element_fp4 res = this->one();
189  element_fp4 this_inverse = this->unitary_inversed();
190 
191  bool found_nonzero = false;
192  std::vector<long> NAF = nil::crypto3::multiprecision::find_wnaf(1, exponent);
193 
194  for (long i = static_cast<long>(NAF.size() - 1); i >= 0; --i) {
195  if (found_nonzero) {
196  res = res.cyclotomic_squared();
197  }
198 
199  if (NAF[i] != 0) {
200  found_nonzero = true;
201 
202  if (NAF[i] > 0) {
203  res = res * (*this);
204  } else {
205  res = res * this_inverse;
206  }
207  }
208  }
209 
210  return res;
211 
212  // return *this;
213  }
214 
215  constexpr /*inline static*/ underlying_type mul_by_non_residue(const underlying_type &A) const {
216  return underlying_type(non_residue * A.data[1], A.data[0]);
217  }
218 
219  element_fp4 mul_by_023(const element_fp4 &other) const {
220  /* Devegili OhEig Scott Dahab --- Multiplication and Squaring on Pairing-Friendly
221  * Fields.pdf; Section 3 (Karatsuba) */
222  assert(other.data[0].data[1].is_zero());
223 
224  const underlying_type &A = other.data[0], &B = other.data[1], &a = this->data[0],
225  &b = this->data[1];
226  const underlying_type aA = underlying_type(a.data[0] * A.data[0], a.data[1] * A.data[0]);
227  const underlying_type bB = b * B;
228 
230  return element_fp4(aA + beta_bB, (a + b) * (A + B) - aA - bB);
231  }
232  };
233 
234  template<typename FieldParams>
235  constexpr const typename element_fp4<FieldParams>::non_residue_type
237 
238  } // namespace detail
239  } // namespace fields
240  } // namespace algebra
241  } // namespace crypto3
242 } // namespace nil
243 
244 #endif // CRYPTO3_ALGEBRA_FIELDS_ELEMENT_FP4_HPP
Definition: detail/element/fp4.hpp:41
constexpr element_fp4 operator+(const element_fp4 &B) const
Definition: detail/element/fp4.hpp:91
constexpr element_fp4 operator-() const
Definition: detail/element/fp4.hpp:117
constexpr static const non_residue_type non_residue
Definition: detail/element/fp4.hpp:46
constexpr element_fp4 doubled() const
Definition: detail/element/fp4.hpp:95
element_fp4 cyclotomic_exp(const PowerType &exponent) const
Definition: detail/element/fp4.hpp:187
policy_type::underlying_type underlying_type
Definition: detail/element/fp4.hpp:48
constexpr element_fp4()
Definition: detail/element/fp4.hpp:54
constexpr bool operator!=(const element_fp4 &B) const
Definition: detail/element/fp4.hpp:80
element_fp4 cyclotomic_squared() const
Definition: detail/element/fp4.hpp:174
constexpr element_fp4(const element_fp4 &B)
Definition: detail/element/fp4.hpp:66
constexpr element_fp4 operator*(const element_fp4 &B) const
Definition: detail/element/fp4.hpp:121
constexpr element_fp4(underlying_type in_data0, underlying_type in_data1)
Definition: detail/element/fp4.hpp:58
policy_type::non_residue_type non_residue_type
Definition: detail/element/fp4.hpp:45
constexpr static element_fp4 zero()
Definition: detail/element/fp4.hpp:68
constexpr element_fp4 pow(const PowerType &pwr) const
Definition: detail/element/fp4.hpp:138
constexpr element_fp4 inversed() const
Definition: detail/element/fp4.hpp:142
constexpr static element_fp4 one()
Definition: detail/element/fp4.hpp:72
constexpr bool operator==(const element_fp4 &B) const
Definition: detail/element/fp4.hpp:76
constexpr element_fp4 operator-(const element_fp4 &B) const
Definition: detail/element/fp4.hpp:99
element_fp4 sqrt() const
Definition: detail/element/fp4.hpp:128
constexpr element_fp4(const data_type &in_data)
Definition: detail/element/fp4.hpp:62
constexpr element_fp4 squared() const
Definition: detail/element/fp4.hpp:133
std::array< underlying_type, 2 > data_type
Definition: detail/element/fp4.hpp:50
data_type data
Definition: detail/element/fp4.hpp:52
constexpr element_fp4 Frobenius_map(const PowerType &pwr) const
Definition: detail/element/fp4.hpp:160
constexpr underlying_type mul_by_non_residue(const underlying_type &A) const
Definition: detail/element/fp4.hpp:215
constexpr element_fp4 & operator+=(const element_fp4 &B)
Definition: detail/element/fp4.hpp:110
element_fp4 unitary_inversed() const
Definition: detail/element/fp4.hpp:170
constexpr element_fp4 & operator=(const element_fp4 &B)
Definition: detail/element/fp4.hpp:84
element_fp4 mul_by_023(const element_fp4 &other) const
Definition: detail/element/fp4.hpp:219
constexpr element_fp4 & operator-=(const element_fp4 &B)
Definition: detail/element/fp4.hpp:103
constexpr FieldValueType power(const FieldValueType &base, const NumberType &exponent)
Definition: algebra/include/nil/crypto3/algebra/fields/detail/exponentiation.hpp:41
Definition: pair.hpp:31