Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
mnt6_g2.cpp
Go to the documentation of this file.
1
15
16namespace libff {
17
18#ifdef PROFILE_OP_COUNTS
19long long mnt6_G2::add_cnt = 0;
20long long mnt6_G2::dbl_cnt = 0;
21#endif
22
23std::vector<size_t> mnt6_G2::wnaf_window_table;
24std::vector<size_t> mnt6_G2::fixed_base_exp_window_table;
28mnt6_G2 mnt6_G2::G2_zero = {};
29mnt6_G2 mnt6_G2::G2_one = {};
30bool mnt6_G2::initialized = false;
31
33{
35 {
36 this->X = G2_zero.X;
37 this->Y = G2_zero.Y;
38 this->Z = G2_zero.Z;
39 }
40}
41
46
51
52void mnt6_G2::print() const
53{
54 if (this->is_zero())
55 {
56 printf("O\n");
57 }
58 else
59 {
60 mnt6_G2 copy(*this);
61 copy.to_affine_coordinates();
62 gmp_printf("(%Nd*z^2 + %Nd*z + %Nd , %Nd*z^2 + %Nd*z + %Nd)\n",
63 copy.X.c2.as_bigint().data, mnt6_Fq::num_limbs,
64 copy.X.c1.as_bigint().data, mnt6_Fq::num_limbs,
65 copy.X.c0.as_bigint().data, mnt6_Fq::num_limbs,
66 copy.Y.c2.as_bigint().data, mnt6_Fq::num_limbs,
67 copy.Y.c1.as_bigint().data, mnt6_Fq::num_limbs,
68 copy.Y.c0.as_bigint().data, mnt6_Fq::num_limbs);
69 }
70}
71
73{
74 if (this->is_zero())
75 {
76 printf("O\n");
77 }
78 else
79 {
80 gmp_printf("(%Nd*z^2 + %Nd*z + %Nd : %Nd*z^2 + %Nd*z + %Nd : %Nd*z^2 + %Nd*z + %Nd)\n",
81 this->X.c2.as_bigint().data, mnt6_Fq::num_limbs,
82 this->X.c1.as_bigint().data, mnt6_Fq::num_limbs,
83 this->X.c0.as_bigint().data, mnt6_Fq::num_limbs,
84 this->Y.c2.as_bigint().data, mnt6_Fq::num_limbs,
85 this->Y.c1.as_bigint().data, mnt6_Fq::num_limbs,
86 this->Y.c0.as_bigint().data, mnt6_Fq::num_limbs,
87 this->Z.c2.as_bigint().data, mnt6_Fq::num_limbs,
88 this->Z.c1.as_bigint().data, mnt6_Fq::num_limbs,
89 this->Z.c0.as_bigint().data, mnt6_Fq::num_limbs);
90 }
91}
92
94{
95 if (this->is_zero())
96 {
97 this->X = mnt6_Fq3::zero();
98 this->Y = mnt6_Fq3::one();
99 this->Z = mnt6_Fq3::zero();
100 }
101 else
102 {
103 const mnt6_Fq3 Z_inv = Z.inverse();
104 this->X = this->X * Z_inv;
105 this->Y = this->Y * Z_inv;
106 this->Z = mnt6_Fq3::one();
107 }
108}
109
111{
112 this->to_affine_coordinates();
113}
114
116{
117 return (this->is_zero() || this->Z == mnt6_Fq3::one());
118}
119
121{
122 // TODO: use zero for here
123 return (this->X.is_zero() && this->Z.is_zero());
124}
125
126bool mnt6_G2::operator==(const mnt6_G2 &other) const
127{
128 if (this->is_zero())
129 {
130 return other.is_zero();
131 }
132
133 if (other.is_zero())
134 {
135 return false;
136 }
137
138 /* now neither is O */
139
140 // X1/Z1 = X2/Z2 <=> X1*Z2 = X2*Z1
141 if ((this->X * other.Z) != (other.X * this->Z))
142 {
143 return false;
144 }
145
146 // Y1/Z1 = Y2/Z2 <=> Y1*Z2 = Y2*Z1
147 if ((this->Y * other.Z) != (other.Y * this->Z))
148 {
149 return false;
150 }
151
152 return true;
153}
154
155bool mnt6_G2::operator!=(const mnt6_G2& other) const
156{
157 return !(operator==(other));
158}
159
161{
162 // handle special cases having to do with O
163 if (this->is_zero())
164 {
165 return other;
166 }
167
168 if (other.is_zero())
169 {
170 return *this;
171 }
172
173 // no need to handle points of order 2,4
174 // (they cannot exist in a prime-order subgroup)
175
176 // handle double case, and then all the rest
177 /*
178 The code below is equivalent to (but faster than) the snippet below:
179
180 if (this->operator==(other))
181 {
182 return this->dbl();
183 }
184 else
185 {
186 return this->add(other);
187 }
188 */
189
190 const mnt6_Fq3 X1Z2 = (this->X) * (other.Z); // X1Z2 = X1*Z2
191 const mnt6_Fq3 X2Z1 = (this->Z) * (other.X); // X2Z1 = X2*Z1
192
193 // (used both in add and double checks)
194
195 const mnt6_Fq3 Y1Z2 = (this->Y) * (other.Z); // Y1Z2 = Y1*Z2
196 const mnt6_Fq3 Y2Z1 = (this->Z) * (other.Y); // Y2Z1 = Y2*Z1
197
198 if (X1Z2 == X2Z1 && Y1Z2 == Y2Z1)
199 {
200 // perform dbl case
201 const mnt6_Fq3 XX = (this->X).squared(); // XX = X1^2
202 const mnt6_Fq3 ZZ = (this->Z).squared(); // ZZ = Z1^2
203 const mnt6_Fq3 w = mnt6_G2::mul_by_a(ZZ) + (XX + XX + XX); // w = a*ZZ + 3*XX
204 const mnt6_Fq3 Y1Z1 = (this->Y) * (this->Z);
205 const mnt6_Fq3 s = Y1Z1 + Y1Z1; // s = 2*Y1*Z1
206 const mnt6_Fq3 ss = s.squared(); // ss = s^2
207 const mnt6_Fq3 sss = s * ss; // sss = s*ss
208 const mnt6_Fq3 R = (this->Y) * s; // R = Y1*s
209 const mnt6_Fq3 RR = R.squared(); // RR = R^2
210 const mnt6_Fq3 B = ((this->X)+R).squared()-XX-RR; // B = (X1+R)^2 - XX - RR
211 const mnt6_Fq3 h = w.squared() - (B+B); // h = w^2 - 2*B
212 const mnt6_Fq3 X3 = h * s; // X3 = h*s
213 const mnt6_Fq3 Y3 = w * (B-h)-(RR+RR); // Y3 = w*(B-h) - 2*RR
214 const mnt6_Fq3 Z3 = sss; // Z3 = sss
215
216 return mnt6_G2(X3, Y3, Z3);
217 }
218
219 // if we have arrived here we are in the add case
220 const mnt6_Fq3 Z1Z2 = (this->Z) * (other.Z); // Z1Z2 = Z1*Z2
221 const mnt6_Fq3 u = Y2Z1 - Y1Z2; // u = Y2*Z1-Y1Z2
222 const mnt6_Fq3 uu = u.squared(); // uu = u^2
223 const mnt6_Fq3 v = X2Z1 - X1Z2; // v = X2*Z1-X1Z2
224 const mnt6_Fq3 vv = v.squared(); // vv = v^2
225 const mnt6_Fq3 vvv = v * vv; // vvv = v*vv
226 const mnt6_Fq3 R = vv * X1Z2; // R = vv*X1Z2
227 const mnt6_Fq3 A = uu * Z1Z2 - (vvv + R + R); // A = uu*Z1Z2 - vvv - 2*R
228 const mnt6_Fq3 X3 = v * A; // X3 = v*A
229 const mnt6_Fq3 Y3 = u * (R-A) - vvv * Y1Z2; // Y3 = u*(R-A) - vvv*Y1Z2
230 const mnt6_Fq3 Z3 = vvv * Z1Z2; // Z3 = vvv*Z1Z2
231
232 return mnt6_G2(X3, Y3, Z3);
233}
234
236{
237 return mnt6_G2(this->X, -(this->Y), this->Z);
238}
239
240
242{
243 return (*this) + (-other);
244}
245
246mnt6_G2 mnt6_G2::add(const mnt6_G2 &other) const
247{
248 // handle special cases having to do with O
249 if (this->is_zero())
250 {
251 return other;
252 }
253
254 if (other.is_zero())
255 {
256 return (*this);
257 }
258
259 // no need to handle points of order 2,4
260 // (they cannot exist in a prime-order subgroup)
261
262 // handle double case
263 if (this->operator==(other))
264 {
265 return this->dbl();
266 }
267
268#ifdef PROFILE_OP_COUNTS
269 this->add_cnt++;
270#endif
271 // NOTE: does not handle O and pts of order 2,4
272 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-projective.html#addition-add-1998-cmo-2
273
274 const mnt6_Fq3 Y1Z2 = (this->Y) * (other.Z); // Y1Z2 = Y1*Z2
275 const mnt6_Fq3 X1Z2 = (this->X) * (other.Z); // X1Z2 = X1*Z2
276 const mnt6_Fq3 Z1Z2 = (this->Z) * (other.Z); // Z1Z2 = Z1*Z2
277 const mnt6_Fq3 u = (other.Y) * (this->Z) - Y1Z2; // u = Y2*Z1-Y1Z2
278 const mnt6_Fq3 uu = u.squared(); // uu = u^2
279 const mnt6_Fq3 v = (other.X) * (this->Z) - X1Z2; // v = X2*Z1-X1Z2
280 const mnt6_Fq3 vv = v.squared(); // vv = v^2
281 const mnt6_Fq3 vvv = v * vv; // vvv = v*vv
282 const mnt6_Fq3 R = vv * X1Z2; // R = vv*X1Z2
283 const mnt6_Fq3 A = uu * Z1Z2 - (vvv + R + R); // A = uu*Z1Z2 - vvv - 2*R
284 const mnt6_Fq3 X3 = v * A; // X3 = v*A
285 const mnt6_Fq3 Y3 = u * (R-A) - vvv * Y1Z2; // Y3 = u*(R-A) - vvv*Y1Z2
286 const mnt6_Fq3 Z3 = vvv * Z1Z2; // Z3 = vvv*Z1Z2
287
288 return mnt6_G2(X3, Y3, Z3);
289}
290
292{
293#ifdef PROFILE_OP_COUNTS
294 this->add_cnt++;
295#endif
296 // NOTE: does not handle O and pts of order 2,4
297 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-projective.html#addition-add-1998-cmo-2
298 //assert(other.Z == mnt6_Fq3::one());
299
300 if (this->is_zero())
301 {
302 return other;
303 }
304
305 if (other.is_zero())
306 {
307 return (*this);
308 }
309
310#ifdef DEBUG
311 assert(other.is_special());
312#endif
313
314 const mnt6_Fq3 &X1Z2 = (this->X); // X1Z2 = X1*Z2 (but other is special and not zero)
315 const mnt6_Fq3 X2Z1 = (this->Z) * (other.X); // X2Z1 = X2*Z1
316
317 // (used both in add and double checks)
318
319 const mnt6_Fq3 &Y1Z2 = (this->Y); // Y1Z2 = Y1*Z2 (but other is special and not zero)
320 const mnt6_Fq3 Y2Z1 = (this->Z) * (other.Y); // Y2Z1 = Y2*Z1
321
322 if (X1Z2 == X2Z1 && Y1Z2 == Y2Z1)
323 {
324 return this->dbl();
325 }
326
327 const mnt6_Fq3 u = Y2Z1 - this->Y; // u = Y2*Z1-Y1
328 const mnt6_Fq3 uu = u.squared(); // uu = u2
329 const mnt6_Fq3 v = X2Z1 - this->X; // v = X2*Z1-X1
330 const mnt6_Fq3 vv = v.squared(); // vv = v2
331 const mnt6_Fq3 vvv = v*vv; // vvv = v*vv
332 const mnt6_Fq3 R = vv * this->X; // R = vv*X1
333 const mnt6_Fq3 A = uu * this->Z - vvv - R - R; // A = uu*Z1-vvv-2*R
334 const mnt6_Fq3 X3 = v * A; // X3 = v*A
335 const mnt6_Fq3 Y3 = u*(R-A) - vvv * this->Y; // Y3 = u*(R-A)-vvv*Y1
336 const mnt6_Fq3 Z3 = vvv * this->Z; // Z3 = vvv*Z1
337
338 return mnt6_G2(X3, Y3, Z3);
339}
340
342{
343#ifdef PROFILE_OP_COUNTS
344 this->dbl_cnt++;
345#endif
346 if (this->is_zero())
347 {
348 return (*this);
349 }
350 else
351 {
352 // NOTE: does not handle O and pts of order 2,4
353 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-projective.html#doubling-dbl-2007-bl
354
355 const mnt6_Fq3 XX = (this->X).squared(); // XX = X1^2
356 const mnt6_Fq3 ZZ = (this->Z).squared(); // ZZ = Z1^2
357 const mnt6_Fq3 w = mnt6_G2::mul_by_a(ZZ) + (XX + XX + XX); // w = a*ZZ + 3*XX
358 const mnt6_Fq3 Y1Z1 = (this->Y) * (this->Z);
359 const mnt6_Fq3 s = Y1Z1 + Y1Z1; // s = 2*Y1*Z1
360 const mnt6_Fq3 ss = s.squared(); // ss = s^2
361 const mnt6_Fq3 sss = s * ss; // sss = s*ss
362 const mnt6_Fq3 R = (this->Y) * s; // R = Y1*s
363 const mnt6_Fq3 RR = R.squared(); // RR = R^2
364 const mnt6_Fq3 B = ((this->X)+R).squared()-XX-RR; // B = (X1+R)^2 - XX - RR
365 const mnt6_Fq3 h = w.squared() - (B+B); // h = w^2-2*B
366 const mnt6_Fq3 X3 = h * s; // X3 = h*s
367 const mnt6_Fq3 Y3 = w * (B-h)-(RR+RR); // Y3 = w*(B-h) - 2*RR
368 const mnt6_Fq3 Z3 = sss; // Z3 = sss
369
370 return mnt6_G2(X3, Y3, Z3);
371 }
372}
373
375{
376 return mnt6_G2(mnt6_twist_mul_by_q_X * (this->X).Frobenius_map(1),
377 mnt6_twist_mul_by_q_Y * (this->Y).Frobenius_map(1),
378 (this->Z).Frobenius_map(1));
379}
380
382{
383 if (this->is_zero())
384 {
385 return true;
386 }
387 else
388 {
389
390 /*
391 y^2 = x^3 + ax + b
392
393 We are using projective, so equation we need to check is actually
394
395 (y/z)^2 = (x/z)^3 + a (x/z) + b
396 z y^2 = x^3 + a z^2 x + b z^3
397
398 z (y^2 - b z^2) = x ( x^2 + a z^2)
399 */
400 const mnt6_Fq3 X2 = this->X.squared();
401 const mnt6_Fq3 Y2 = this->Y.squared();
402 const mnt6_Fq3 Z2 = this->Z.squared();
403 const mnt6_Fq3 aZ2 = mnt6_twist_coeff_a * Z2;
404
405 return (this->Z * (Y2 - mnt6_twist_coeff_b * Z2) == this->X * (X2 + aZ2));
406 }
407}
408
410{
411 return G2_zero;
412}
413
415{
416 return G2_one;
417}
418
420{
421 return (mnt6_Fr::random_element().as_bigint()) * G2_one;
422}
423
424std::ostream& operator<<(std::ostream &out, const mnt6_G2 &g)
425{
426 mnt6_G2 copy(g);
427 copy.to_affine_coordinates();
428
429 out << (copy.is_zero() ? 1 : 0) << OUTPUT_SEPARATOR;
430#ifdef NO_PT_COMPRESSION
431 out << copy.X << OUTPUT_SEPARATOR << copy.Y;
432#else
433 /* storing LSB of Y */
434 out << copy.X << OUTPUT_SEPARATOR << (copy.Y.c0.as_bigint().data[0] & 1);
435#endif
436
437 return out;
438}
439
440std::istream& operator>>(std::istream &in, mnt6_G2 &g)
441{
442 char is_zero;
443 mnt6_Fq3 tX, tY;
444
445#ifdef NO_PT_COMPRESSION
446 in >> is_zero >> tX >> tY;
447 is_zero -= '0';
448#else
449 in.read((char*)&is_zero, 1); // this reads is_zero;
450 is_zero -= '0';
452
453 unsigned char Y_lsb;
454 in >> tX;
456 in.read((char*)&Y_lsb, 1);
457 Y_lsb -= '0';
458
459 // y = +/- sqrt(x^3 + a*x + b)
460 if (!is_zero)
461 {
462 const mnt6_Fq3 tX2 = tX.squared();
463 const mnt6_Fq3 tY2 = (tX2 + mnt6_twist_coeff_a) * tX + mnt6_twist_coeff_b;
464 tY = tY2.sqrt();
465
466 if ((tY.c0.as_bigint().data[0] & 1) != Y_lsb)
467 {
468 tY = -tY;
469 }
470 }
471#endif
472 // using projective coordinates
473 if (!is_zero)
474 {
475 g.X = tX;
476 g.Y = tY;
477 g.Z = mnt6_Fq3::one();
478 }
479 else
480 {
481 g = mnt6_G2::zero();
482 }
483
484 return in;
485}
486
487void mnt6_G2::batch_to_special_all_non_zeros(std::vector<mnt6_G2> &vec)
488{
489 std::vector<mnt6_Fq3> Z_vec;
490 Z_vec.reserve(vec.size());
491
492 for (auto &el: vec)
493 {
494 Z_vec.emplace_back(el.Z);
495 }
497
498 const mnt6_Fq3 one = mnt6_Fq3::one();
499
500 for (size_t i = 0; i < vec.size(); ++i)
501 {
502 vec[i] = mnt6_G2(vec[i].X * Z_vec[i], vec[i].Y * Z_vec[i], one);
503 }
504}
505
506} // libff
Fp3_model inverse() const
Fp3_model squared() const
static Fp3_model< n, modulus > one()
Fp3_model sqrt() const
static Fp3_model< n, modulus > zero()
bigint< n > as_bigint() const
static Fp_model< n, modulus > random_element()
void to_special()
Definition mnt6_g2.cpp:110
static std::vector< size_t > wnaf_window_table
Definition mnt6_g2.hpp:32
mnt6_Fq3 Z
Definition mnt6_g2.hpp:45
mnt6_G2 operator+(const mnt6_G2 &other) const
Definition mnt6_g2.cpp:160
static void batch_to_special_all_non_zeros(std::vector< mnt6_G2 > &vec)
Definition mnt6_g2.cpp:487
static bool initialized
Definition mnt6_g2.hpp:36
mnt6_G2 operator-() const
Definition mnt6_g2.cpp:235
mnt6_G2 add(const mnt6_G2 &other) const
Definition mnt6_g2.cpp:246
bool is_zero() const
Definition mnt6_g2.cpp:120
bool is_well_formed() const
Definition mnt6_g2.cpp:381
static mnt6_Fq3 mul_by_b(const mnt6_Fq3 &elt)
Definition mnt6_g2.cpp:47
mnt6_Fq3 X
Definition mnt6_g2.hpp:45
static mnt6_G2 random_element()
Definition mnt6_g2.cpp:419
bool is_special() const
Definition mnt6_g2.cpp:115
static mnt6_G2 G2_one
Definition mnt6_g2.hpp:35
mnt6_G2 dbl() const
Definition mnt6_g2.cpp:341
static mnt6_Fq3 twist
Definition mnt6_g2.hpp:37
static mnt6_G2 G2_zero
Definition mnt6_g2.hpp:34
bool operator==(const mnt6_G2 &other) const
Definition mnt6_g2.cpp:126
mnt6_G2 mixed_add(const mnt6_G2 &other) const
Definition mnt6_g2.cpp:291
static mnt6_Fq3 mul_by_a(const mnt6_Fq3 &elt)
Definition mnt6_g2.cpp:42
void print() const
Definition mnt6_g2.cpp:52
static mnt6_G2 one()
Definition mnt6_g2.cpp:414
mnt6_G2 mul_by_q() const
Definition mnt6_g2.cpp:374
mnt6_Fq3 Y
Definition mnt6_g2.hpp:45
static mnt6_G2 zero()
Definition mnt6_g2.cpp:409
static mnt6_Fq3 coeff_a
Definition mnt6_g2.hpp:38
static mnt6_Fq3 coeff_b
Definition mnt6_g2.hpp:39
bool operator!=(const mnt6_G2 &other) const
Definition mnt6_g2.cpp:155
void to_affine_coordinates()
Definition mnt6_g2.cpp:93
void print_coordinates() const
Definition mnt6_g2.cpp:72
static std::vector< size_t > fixed_base_exp_window_table
Definition mnt6_g2.hpp:33
#define OUTPUT_SEPARATOR
std::istream & operator>>(std::istream &in, alt_bn128_G1 &g)
void consume_OUTPUT_SEPARATOR(std::istream &in)
std::ostream & operator<<(std::ostream &out, const alt_bn128_G1 &g)
mnt6_Fq mnt6_twist_mul_by_a_c0
Definition mnt6_init.cpp:26
mnt6_Fq mnt6_twist_mul_by_a_c2
Definition mnt6_init.cpp:28
mnt6_Fq mnt6_twist_mul_by_b_c2
Definition mnt6_init.cpp:31
mnt6_Fq mnt6_twist_mul_by_b_c1
Definition mnt6_init.cpp:30
mnt6_Fq3 mnt6_twist_coeff_a
Definition mnt6_init.cpp:24
mnt6_Fq mnt6_twist_mul_by_q_Y
Definition mnt6_init.cpp:33
mnt6_Fq mnt6_twist_mul_by_b_c0
Definition mnt6_init.cpp:29
mnt6_Fq mnt6_twist_mul_by_q_X
Definition mnt6_init.cpp:32
Fp3_model< mnt6_q_limbs, mnt6_modulus_q > mnt6_Fq3
Definition mnt6_init.hpp:37
mnt6_Fq3 mnt6_twist_coeff_b
Definition mnt6_init.cpp:25
void batch_invert(std::vector< FieldT > &vec)
mnt6_Fq mnt6_twist_mul_by_a_c1
Definition mnt6_init.cpp:27
Definition lib.h:43
#define R
#define A
char * s