detail/element/fp3.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_FP3_HPP
27 #define CRYPTO3_ALGEBRA_FIELDS_ELEMENT_FP3_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_fp3 {
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 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, 3>;
55 
57 
58  constexpr element_fp3() {
59  data =
60  data_type({underlying_type::zero(), underlying_type::zero(), underlying_type::zero()});
61  }
62 
63  template<typename Number1, typename Number2, typename Number3>
64  constexpr element_fp3(const Number1 &in_data0,
65  const Number2 &in_data1,
66  const Number3 &in_data2) {
67  data = data_type(
68  {underlying_type(in_data0), underlying_type(in_data1), underlying_type(in_data2)});
69  }
70 
71  constexpr element_fp3(const data_type &in_data) {
72  data = data_type({in_data[0], in_data[1], in_data[2]});
73  };
74 
75  constexpr element_fp3(const underlying_type &in_data0,
76  const underlying_type &in_data1,
77  const underlying_type &in_data2) {
78  data = data_type({in_data0, in_data1, in_data2});
79  }
80 
81  constexpr element_fp3(const element_fp3 &B) : data {B.data} {};
82 
83  constexpr inline static element_fp3 zero() {
84  return element_fp3(
85  underlying_type::zero(), underlying_type::zero(), underlying_type::zero());
86  }
87 
88  constexpr inline static element_fp3 one() {
89  return element_fp3(
90  underlying_type::one(), underlying_type::zero(), underlying_type::zero());
91  }
92 
93  constexpr bool is_zero() const {
94  return (data[0] == underlying_type::zero()) && (data[1] == underlying_type::zero()) &&
95  (data[2] == underlying_type::zero());
96  }
97 
98  constexpr bool is_one() const {
99  return (data[0] == underlying_type::one()) && (data[1] == underlying_type::zero()) &&
100  (data[2] == underlying_type::zero());
101  }
102 
103  constexpr bool operator==(const element_fp3 &B) const {
104  return (data[0] == B.data[0]) && (data[1] == B.data[1]) && (data[2] == B.data[2]);
105  }
106 
107  constexpr bool operator!=(const element_fp3 &B) const {
108  return (data[0] != B.data[0]) || (data[1] != B.data[1]) || (data[2] != B.data[2]);
109  }
110 
111  constexpr element_fp3 &operator=(const element_fp3 &B) {
112  data[0] = B.data[0];
113  data[1] = B.data[1];
114  data[2] = B.data[2];
115 
116  return *this;
117  }
118 
119  constexpr element_fp3 operator+(const element_fp3 &B) const {
120  return element_fp3(data[0] + B.data[0], data[1] + B.data[1], data[2] + B.data[2]);
121  }
122 
123  constexpr element_fp3 doubled() const {
124  return element_fp3(data[0].doubled(), data[1].doubled(), data[2].doubled());
125  }
126 
127  constexpr element_fp3 operator-(const element_fp3 &B) const {
128  return element_fp3(data[0] - B.data[0], data[1] - B.data[1], data[2] - B.data[2]);
129  }
130 
131  constexpr element_fp3 &operator-=(const element_fp3 &B) {
132  data[0] -= B.data[0];
133  data[1] -= B.data[1];
134 
135  return *this;
136  }
137 
138  constexpr element_fp3 &operator+=(const element_fp3 &B) {
139  data[0] += B.data[0];
140  data[1] += B.data[1];
141 
142  return *this;
143  }
144 
145  constexpr element_fp3 operator-() const {
146  return zero() - *this;
147  }
148 
149  constexpr element_fp3 operator*(const element_fp3 &B) const {
150  const underlying_type A0B0 = data[0] * B.data[0], A1B1 = data[1] * B.data[1],
151  A2B2 = data[2] * B.data[2];
152 
153  return element_fp3(
154  A0B0 + non_residue * ((data[1] + data[2]) * (B.data[1] + B.data[2]) - A1B1 - A2B2),
155  (data[0] + data[1]) * (B.data[0] + B.data[1]) - A0B0 - A1B1 + non_residue * A2B2,
156  (data[0] + data[2]) * (B.data[0] + B.data[2]) - A0B0 + A1B1 - A2B2);
157  }
158 
159  constexpr element_fp3 sqrt() const {
160 
161  element_fp3 one = this->one();
162 
163  std::size_t v = policy_type::s;
164  element_fp3 z(policy_type::nqr_to_t[0], policy_type::nqr_to_t[1], policy_type::nqr_to_t[2]);
165  element_fp3 w = this->pow(policy_type::t_minus_1_over_2);
166  element_fp3 x((*this) * w);
167  element_fp3 b = x * w; // b = (*this)^t
168 
169  // compute square root with Tonelli--Shanks
170  // (does not terminate if not a square!)
171 
172  while (b != one) {
173  std::size_t m = 0;
174  element_fp3 b2m = b;
175  while (b2m != one) {
176  /* invariant: b2m = b^(2^m) after entering this loop */
177  b2m = b2m.squared();
178  m += 1;
179  }
180 
181  int j = v - m - 1;
182  w = z;
183  while (j > 0) {
184  w = w.squared();
185  --j;
186  } // w = z^2^(v-m-1)
187 
188  z = w.squared();
189  b = b * z;
190  x = x * w;
191  v = m;
192  }
193 
194  return x;
195  }
196 
197  constexpr element_fp3 squared() const {
198  return (*this) * (*this); // maybe can be done more effective
199  }
200 
201  constexpr bool is_square() const {
202  element_fp3 tmp = this->pow((policy_type::group_order - 1) / 2);
203  return (tmp.is_one() || tmp.is_zero()); // maybe can be done more effective
204  }
205 
206  template<typename PowerType>
207  constexpr element_fp3 pow(const PowerType &pwr) const {
208  return element_fp3(power(*this, pwr));
209  }
210 
211  constexpr element_fp3 inversed() const {
212 
213  /* From "High-Speed Software Implementation of the Optimal Ate Pairing over Barreto-Naehrig
214  * Curves"; Algorithm 17 */
215 
216  const underlying_type &A0 = data[0], &A1 = data[1], &A2 = data[2];
217 
218  const underlying_type t0 = A0.squared();
219  const underlying_type t1 = A1.squared();
220  const underlying_type t2 = A2.squared();
221  const underlying_type t3 = A0 * A1;
222  const underlying_type t4 = A0 * A2;
223  const underlying_type t5 = A1 * A2;
224  const underlying_type c0 = t0 - non_residue * t5;
225  const underlying_type c1 = non_residue * t2 - t3;
226  const underlying_type c2 =
227  t1 - t4; // typo in paper referenced above. should be "-" as per Scott, but is "*"
228  const underlying_type t6 = (A0 * c0 + non_residue * (A2 * c1 + A1 * c2)).inversed();
229  return element_fp3(t6 * c0, t6 * c1, t6 * c2);
230  }
231 
232  template<typename PowerType>
233  constexpr element_fp3 Frobenius_map(const PowerType &pwr) const {
234  return element_fp3(
235  data[0],
236  typename policy_type::non_residue_type(policy_type::Frobenius_coeffs_c1[pwr % 3]) *
237  data[1],
238  typename policy_type::non_residue_type(policy_type::Frobenius_coeffs_c2[pwr % 3]) *
239  data[2]);
240  // return element_fp3(data[0],
241  // policy_type::Frobenius_coeffs_c1[pwr % 3] * data[1],
242  // policy_type::Frobenius_coeffs_c2[pwr % 3] * data[2]});
243  }
244  };
245 
246  template<typename FieldParams>
247  constexpr element_fp3<FieldParams> operator*(const typename FieldParams::underlying_type &lhs,
248  const element_fp3<FieldParams> &rhs) {
249  return element_fp3<FieldParams>(lhs * rhs.data[0], lhs * rhs.data[1], lhs * rhs.data[2]);
250  }
251 
252  template<typename FieldParams>
254  const typename FieldParams::underlying_type &rhs) {
255  return rhs * lhs;
256  }
257 
258  template<typename FieldParams>
259  constexpr const typename element_fp3<FieldParams>::non_residue_type
261 
262  } // namespace detail
263  } // namespace fields
264  } // namespace algebra
265  } // namespace crypto3
266 } // namespace nil
267 
268 #endif // CRYPTO3_ALGEBRA_FIELDS_ELEMENT_FP3_HPP
Definition: detail/element/fp3.hpp:39
constexpr element_fp3 sqrt() const
Definition: detail/element/fp3.hpp:159
constexpr element_fp3 & operator=(const element_fp3 &B)
Definition: detail/element/fp3.hpp:111
constexpr element_fp3 squared() const
Definition: detail/element/fp3.hpp:197
constexpr element_fp3 operator-(const element_fp3 &B) const
Definition: detail/element/fp3.hpp:127
policy_type::field_type field_type
Definition: detail/element/fp3.hpp:47
std::array< underlying_type, 3 > data_type
Definition: detail/element/fp3.hpp:54
constexpr element_fp3 operator+(const element_fp3 &B) const
Definition: detail/element/fp3.hpp:119
constexpr element_fp3(const data_type &in_data)
Definition: detail/element/fp3.hpp:71
constexpr element_fp3()
Definition: detail/element/fp3.hpp:58
constexpr element_fp3 operator-() const
Definition: detail/element/fp3.hpp:145
data_type data
Definition: detail/element/fp3.hpp:56
constexpr static element_fp3 one()
Definition: detail/element/fp3.hpp:88
constexpr static non_residue_type non_residue
Definition: detail/element/fp3.hpp:50
constexpr element_fp3 Frobenius_map(const PowerType &pwr) const
Definition: detail/element/fp3.hpp:233
policy_type::underlying_type underlying_type
Definition: detail/element/fp3.hpp:52
policy_type::non_residue_type non_residue_type
Definition: detail/element/fp3.hpp:49
constexpr static element_fp3 zero()
Definition: detail/element/fp3.hpp:83
constexpr element_fp3 & operator-=(const element_fp3 &B)
Definition: detail/element/fp3.hpp:131
constexpr element_fp3(const Number1 &in_data0, const Number2 &in_data1, const Number3 &in_data2)
Definition: detail/element/fp3.hpp:64
constexpr element_fp3(const underlying_type &in_data0, const underlying_type &in_data1, const underlying_type &in_data2)
Definition: detail/element/fp3.hpp:75
constexpr element_fp3 operator*(const element_fp3 &B) const
Definition: detail/element/fp3.hpp:149
constexpr element_fp3 pow(const PowerType &pwr) const
Definition: detail/element/fp3.hpp:207
constexpr bool is_square() const
Definition: detail/element/fp3.hpp:201
constexpr element_fp3(const element_fp3 &B)
Definition: detail/element/fp3.hpp:81
constexpr bool is_one() const
Definition: detail/element/fp3.hpp:98
constexpr element_fp3 doubled() const
Definition: detail/element/fp3.hpp:123
constexpr element_fp3 & operator+=(const element_fp3 &B)
Definition: detail/element/fp3.hpp:138
constexpr bool operator!=(const element_fp3 &B) const
Definition: detail/element/fp3.hpp:107
constexpr element_fp3 inversed() const
Definition: detail/element/fp3.hpp:211
constexpr bool is_zero() const
Definition: detail/element/fp3.hpp:93
constexpr bool operator==(const element_fp3 &B) const
Definition: detail/element/fp3.hpp:103
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