14 #ifdef PROFILE_OP_COUNTS
15 long long bn128_G2::add_cnt = 0;
16 long long bn128_G2::dbl_cnt = 0;
25 bn::Fp2 bn128_G2::sqrt(
const bn::Fp2 &el)
36 for (
size_t i = 0; i < v - 1; ++i) {
37 bn::Fp2::square(check, check);
40 assert(check == bn::Fp2(bn::Fp(1), bn::Fp(0)));
46 while (b != bn::Fp2(1)) {
49 while (b2m != bn::Fp2(bn::Fp(1), bn::Fp(0))) {
51 bn::Fp2::square(b2m, b2m);
59 bn::Fp2::square(w, w);
86 std::cout <<
"(" << copy.
X.toString(10) <<
" : " << copy.
Y.toString(10)
87 <<
" : " << copy.
Z.toString(10) <<
")\n";
96 std::cout <<
"(" <<
X.toString(10) <<
" : " <<
Y.toString(10) <<
" : "
97 <<
Z.toString(10) <<
")\n";
111 bn::Fp2::square(
Z, r);
137 bn::Fp2 Z1sq, Z2sq, lhs, rhs;
138 bn::Fp2::square(Z1sq, this->
Z);
139 bn::Fp2::square(Z2sq, other.
Z);
140 bn::Fp2::mul(lhs, Z2sq, this->
X);
141 bn::Fp2::mul(rhs, Z1sq, other.
X);
147 bn::Fp2 Z1cubed, Z2cubed;
148 bn::Fp2::mul(Z1cubed, Z1sq, this->
Z);
149 bn::Fp2::mul(Z2cubed, Z2sq, other.
Z);
150 bn::Fp2::mul(lhs, Z2cubed, this->
Y);
151 bn::Fp2::mul(rhs, Z1cubed, other.
Y);
176 if (this->
operator==(other)) {
179 return this->
add(other);
186 bn::Fp2::neg(result.
Y, result.
Y);
192 return (*
this) + (-other);
197 #ifdef PROFILE_OP_COUNTS
201 bn::Fp2 this_coord[3], other_coord[3], result_coord[3];
204 bn::ecop::ECAdd(result_coord, this_coord, other_coord);
239 bn::Fp2::square(Z1Z1, this->
Z);
240 const bn::Fp2 &U1 = this->
X;
242 bn::Fp2::mul(U2, other.
X, Z1Z1);
244 bn::Fp2::mul(Z1_cubed, this->
Z, Z1Z1);
246 const bn::Fp2 &S1 = this->
Y;
249 bn::Fp2::mul(S2, other.
Y, Z1_cubed);
251 if (U1 == U2 && S1 == S2) {
256 #ifdef PROFILE_OP_COUNTS
261 bn::Fp2 H, HH, I, J, r, V, tmp;
263 bn::Fp2::sub(H, U2, this->
X);
265 bn::Fp2::square(HH, H);
267 bn::Fp2::add(tmp, HH, HH);
268 bn::Fp2::add(I, tmp, tmp);
270 bn::Fp2::mul(J, H, I);
272 bn::Fp2::sub(tmp, S2, this->
Y);
273 bn::Fp2::add(r, tmp, tmp);
275 bn::Fp2::mul(V, this->
X, I);
277 bn::Fp2::square(result.
X, r);
278 bn::Fp2::sub(result.
X, result.
X, J);
279 bn::Fp2::sub(result.
X, result.
X, V);
280 bn::Fp2::sub(result.
X, result.
X, V);
282 bn::Fp2::sub(tmp, V, result.
X);
283 bn::Fp2::mul(result.
Y, r, tmp);
284 bn::Fp2::mul(tmp, this->
Y, J);
285 bn::Fp2::sub(result.
Y, result.
Y, tmp);
286 bn::Fp2::sub(result.
Y, result.
Y, tmp);
288 bn::Fp2::add(tmp, this->
Z, H);
289 bn::Fp2::square(result.
Z, tmp);
290 bn::Fp2::sub(result.
Z, result.
Z, Z1Z1);
291 bn::Fp2::sub(result.
Z, result.
Z, HH);
297 #ifdef PROFILE_OP_COUNTS
301 bn::Fp2 this_coord[3], result_coord[3];
303 bn::ecop::ECDouble(result_coord, this_coord);
325 bn::Fp2::square(X2, this->
X);
326 bn::Fp2::square(Y2, this->
Y);
327 bn::Fp2::square(Z2, this->
Z);
330 bn::Fp2::mul(X3, X2, this->
X);
331 bn::Fp2::mul(Z3, Z2, this->
Z);
332 bn::Fp2::square(Z6, Z3);
360 #ifndef BINARY_OUTPUT
364 out.write((
char *)&gcopy.
X.a_,
sizeof(gcopy.
X.a_));
365 out.write((
char *)&gcopy.
X.b_,
sizeof(gcopy.
X.b_));
366 out.write((
char *)&gcopy.
Y.a_,
sizeof(gcopy.
Y.a_));
367 out.write((
char *)&gcopy.
Y.b_,
sizeof(gcopy.
Y.b_));
378 #ifndef BINARY_OUTPUT
381 out.write((
char *)&gcopy.
X.a_,
sizeof(gcopy.
X.a_));
382 out.write((
char *)&gcopy.
X.b_,
sizeof(gcopy.
X.b_));
385 << (((
unsigned char *)&gcopy.
Y.a_)[0] & 1 ?
'1' :
'0');
396 #ifndef BINARY_OUTPUT
405 in.read((
char *)&g.
X.a_,
sizeof(g.
X.a_));
406 in.read((
char *)&g.
X.b_,
sizeof(g.
X.b_));
407 in.read((
char *)&g.
Y.a_,
sizeof(g.
Y.a_));
408 in.read((
char *)&g.
Y.b_,
sizeof(g.
Y.b_));
413 g.
Z = bn::Fp2(bn::Fp(1), bn::Fp(0));
428 #ifndef BINARY_OUTPUT
433 in.read((
char *)&tX.a_,
sizeof(tX.a_));
434 in.read((
char *)&tX.b_,
sizeof(tX.b_));
438 in.read((
char *)&Y_lsb, 1);
445 bn::Fp2::square(tX2, tX);
446 bn::Fp2::mul(tY2, tX2, tX);
449 g.
Y = bn128_G2::sqrt(tY2);
450 if ((((
unsigned char *)&g.
Y.a_)[0] & 1) != Y_lsb) {
451 bn::Fp2::neg(g.
Y, g.
Y);
457 g.
Z = bn::Fp2(bn::Fp(1), bn::Fp(0));
465 #ifdef NO_PT_COMPRESSION
475 #ifdef NO_PT_COMPRESSION
485 std::vector<bn::Fp2> Z_vec;
486 Z_vec.reserve(vec.size());
488 for (
auto &el : vec) {
489 Z_vec.emplace_back(el.Z);
491 bn_batch_invert<bn::Fp2>(Z_vec);
493 const bn::Fp2
one = 1;
495 for (
size_t i = 0; i < vec.size(); ++i) {
497 bn::Fp2::square(Z2, Z_vec[i]);
498 bn::Fp2::mul(Z3, Z2, Z_vec[i]);
500 bn::Fp2::mul(vec[i].
X, vec[i].
X, Z2);
501 bn::Fp2::mul(vec[i].
Y, vec[i].
Y, Z3);