Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
edwards_g2.cpp
Go to the documentation of this file.
1
9
10namespace libff {
11
12#ifdef PROFILE_OP_COUNTS
13long long edwards_G2::add_cnt = 0;
14long long edwards_G2::dbl_cnt = 0;
15#endif
16
17std::vector<size_t> edwards_G2::wnaf_window_table;
19
20edwards_G2 edwards_G2::G2_zero = {};
21edwards_G2 edwards_G2::G2_one = {};
22bool edwards_G2::initialized = false;
23
25{
26 if (initialized)
27 {
28 this->X = G2_zero.X;
29 this->Y = G2_zero.Y;
30 this->Z = G2_zero.Z;
31 }
32}
33
35{
36 // should be
37 // edwards_Fq3(edwards_twist_mul_by_a_c0 * elt.c2, edwards_twist_mul_by_a_c1 * elt.c0, edwards_twist_mul_by_a_c2 * elt.c1)
38 // but optimizing the fact that edwards_twist_mul_by_a_c1 = edwards_twist_mul_by_a_c2 = 1
39 return edwards_Fq3(edwards_twist_mul_by_a_c0 * elt.c2, elt.c0, elt.c1);
40}
41
46
48{
49 if (this->is_zero())
50 {
51 printf("O\n");
52 }
53 else
54 {
55 edwards_G2 copy(*this);
56 copy.to_affine_coordinates();
57 gmp_printf("(%Nd*z^2 + %Nd*z + %Nd , %Nd*z^2 + %Nd*z + %Nd)\n",
58 copy.X.c2.as_bigint().data, edwards_Fq::num_limbs,
59 copy.X.c1.as_bigint().data, edwards_Fq::num_limbs,
60 copy.X.c0.as_bigint().data, edwards_Fq::num_limbs,
61 copy.Y.c2.as_bigint().data, edwards_Fq::num_limbs,
62 copy.Y.c1.as_bigint().data, edwards_Fq::num_limbs,
63 copy.Y.c0.as_bigint().data, edwards_Fq::num_limbs);
64 }
65}
66
68{
69 if (this->is_zero())
70 {
71 printf("O\n");
72 }
73 else
74 {
75 gmp_printf("(%Nd*z^2 + %Nd*z + %Nd : %Nd*z^2 + %Nd*z + %Nd : %Nd*z^2 + %Nd*z + %Nd)\n",
76 this->X.c2.as_bigint().data, edwards_Fq::num_limbs,
77 this->X.c1.as_bigint().data, edwards_Fq::num_limbs,
78 this->X.c0.as_bigint().data, edwards_Fq::num_limbs,
79 this->Y.c2.as_bigint().data, edwards_Fq::num_limbs,
80 this->Y.c1.as_bigint().data, edwards_Fq::num_limbs,
81 this->Y.c0.as_bigint().data, edwards_Fq::num_limbs,
82 this->Z.c2.as_bigint().data, edwards_Fq::num_limbs,
83 this->Z.c1.as_bigint().data, edwards_Fq::num_limbs,
84 this->Z.c0.as_bigint().data, edwards_Fq::num_limbs);
85 }
86}
87
89{
90 if (this->is_zero())
91 {
92 this->X = edwards_Fq3::zero();
93 this->Y = edwards_Fq3::one();
94 this->Z = edwards_Fq3::one();
95 }
96 else
97 {
98 // go from inverted coordinates to projective coordinates
99 edwards_Fq3 tX = this->Y * this->Z;
100 edwards_Fq3 tY = this->X * this->Z;
101 edwards_Fq3 tZ = this->X * this->Y;
102 // go from projective coordinates to affine coordinates
103 edwards_Fq3 tZ_inv = tZ.inverse();
104 this->X = tX * tZ_inv;
105 this->Y = tY * tZ_inv;
106 this->Z = edwards_Fq3::one();
107 }
108}
109
111{
112 if (this->Z.is_zero())
113 {
114 return;
115 }
116
117#ifdef DEBUG
118 const edwards_G2 copy(*this);
119#endif
120
121 edwards_Fq3 Z_inv = this->Z.inverse();
122 this->X = this->X * Z_inv;
123 this->Y = this->Y * Z_inv;
124 this->Z = edwards_Fq3::one();
125
126#ifdef DEBUG
127 assert((*this) == copy);
128#endif
129}
130
132{
133 return (this->is_zero() || this->Z == edwards_Fq3::one());
134}
135
137{
138 return (this->Y.is_zero() && this->Z.is_zero());
139}
140
141bool edwards_G2::operator==(const edwards_G2 &other) const
142{
143 if (this->is_zero())
144 {
145 return other.is_zero();
146 }
147
148 if (other.is_zero())
149 {
150 return false;
151 }
152
153 /* now neither is O */
154
155 // X1/Z1 = X2/Z2 <=> X1*Z2 = X2*Z1
156 if ((this->X * other.Z) != (other.X * this->Z))
157 {
158 return false;
159 }
160
161 // Y1/Z1 = Y2/Z2 <=> Y1*Z2 = Y2*Z1
162 if ((this->Y * other.Z) != (other.Y * this->Z))
163 {
164 return false;
165 }
166
167 return true;
168}
169
170bool edwards_G2::operator!=(const edwards_G2& other) const
171{
172 return !(operator==(other));
173}
174
176{
177 // handle special cases having to do with O
178 if (this->is_zero())
179 {
180 return other;
181 }
182
183 if (other.is_zero())
184 {
185 return (*this);
186 }
187
188 return this->add(other);
189}
190
192{
193 return edwards_G2(-(this->X), this->Y, this->Z);
194}
195
196
198{
199 return (*this) + (-other);
200}
201
203{
204#ifdef PROFILE_OP_COUNTS
205 this->add_cnt++;
206#endif
207 // NOTE: does not handle O and pts of order 2,4
208 // http://www.hyperelliptic.org/EFD/g1p/auto-twisted-inverted.html#addition-add-2008-bbjlp
209
210 const edwards_Fq3 A = (this->Z) * (other.Z); // A = Z1*Z2
211 const edwards_Fq3 B = edwards_G2::mul_by_d(A.squared()); // B = d*A^2
212 const edwards_Fq3 C = (this->X) * (other.X); // C = X1*X2
213 const edwards_Fq3 D = (this->Y) * (other.Y); // D = Y1*Y2
214 const edwards_Fq3 E = C*D; // E = C*D
215 const edwards_Fq3 H = C - edwards_G2::mul_by_a(D); // H = C-a*D
216 const edwards_Fq3 I = (this->X+this->Y)*(other.X+other.Y)-C-D; // I = (X1+Y1)*(X2+Y2)-C-D
217 const edwards_Fq3 X3 = (E+B)*H; // X3 = (E+B)*H
218 const edwards_Fq3 Y3 = (E-B)*I; // Y3 = (E-B)*I
219 const edwards_Fq3 Z3 = A*H*I; // Z3 = A*H*I
220
221 return edwards_G2(X3, Y3, Z3);
222}
223
225{
226#ifdef PROFILE_OP_COUNTS
227 this->add_cnt++;
228#endif
229 // handle special cases having to do with O
230 if (this->is_zero())
231 {
232 return other;
233 }
234
235 if (other.is_zero())
236 {
237 return *this;
238 }
239
240#ifdef DEBUG
241 assert(other.is_special());
242#endif
243
244 // NOTE: does not handle O and pts of order 2,4
245 // http://www.hyperelliptic.org/EFD/g1p/auto-edwards-inverted.html#addition-madd-2007-lb
246
247 const edwards_Fq3 A = this->Z; // A = Z1*Z2
248 const edwards_Fq3 B = edwards_G2::mul_by_d(A.squared()); // B = d*A^2
249 const edwards_Fq3 C = (this->X) * (other.X); // C = X1*X2
250 const edwards_Fq3 D = (this->Y) * (other.Y); // D = Y1*Y2
251 const edwards_Fq3 E = C*D; // E = C*D
252 const edwards_Fq3 H = C - edwards_G2::mul_by_a(D); // H = C-a*D
253 const edwards_Fq3 I = (this->X+this->Y)*(other.X+other.Y)-C-D; // I = (X1+Y1)*(X2+Y2)-C-D
254 const edwards_Fq3 X3 = (E+B)*H; // X3 = (E+B)*H
255 const edwards_Fq3 Y3 = (E-B)*I; // Y3 = (E-B)*I
256 const edwards_Fq3 Z3 = A*H*I; // Z3 = A*H*I
257
258 return edwards_G2(X3, Y3, Z3);
259}
260
262{
263#ifdef PROFILE_OP_COUNTS
264 this->dbl_cnt++;
265#endif
266 if (this->is_zero())
267 {
268 return (*this);
269 }
270 else
271 {
272 // NOTE: does not handle O and pts of order 2,4
273 // http://www.hyperelliptic.org/EFD/g1p/auto-twisted-inverted.html#doubling-dbl-2008-bbjlp
274
275 const edwards_Fq3 A = (this->X).squared(); // A = X1^2
276 const edwards_Fq3 B = (this->Y).squared(); // B = Y1^2
277 const edwards_Fq3 U = edwards_G2::mul_by_a(B); // U = a*B
278 const edwards_Fq3 C = A+U; // C = A+U
279 const edwards_Fq3 D = A-U; // D = A-U
280 const edwards_Fq3 E = (this->X+this->Y).squared()-A-B; // E = (X1+Y1)^2-A-B
281 const edwards_Fq3 X3 = C*D; // X3 = C*D
282 const edwards_Fq3 dZZ = edwards_G2::mul_by_d(this->Z.squared());
283 const edwards_Fq3 Y3 = E*(C-dZZ-dZZ); // Y3 = E*(C-2*d*Z1^2)
284 const edwards_Fq3 Z3 = D*E; // Z3 = D*E
285
286 return edwards_G2(X3, Y3, Z3);
287 }
288}
289
291{
292 return edwards_G2((this->X).Frobenius_map(1),
293 edwards_twist_mul_by_q_Y * (this->Y).Frobenius_map(1),
294 edwards_twist_mul_by_q_Z * (this->Z).Frobenius_map(1));
295}
296
298{
299 /* Note that point at infinity is the only special case we must check as
300 inverted representation does no cover points (0, +-c) and (+-c, 0). */
301 if (this->is_zero())
302 {
303 return true;
304 }
305 else
306 {
307 /*
308 a x^2 + y^2 = 1 + d x^2 y^2
309
310 We are using inverted, so equation we need to check is actually
311
312 a (z/x)^2 + (z/y)^2 = 1 + d z^4 / (x^2 * y^2)
313 z^2 (a y^2 + x^2 - dz^2) = x^2 y^2
314 */
315 edwards_Fq3 X2 = this->X.squared();
316 edwards_Fq3 Y2 = this->Y.squared();
317 edwards_Fq3 Z2 = this->Z.squared();
320 return (Z2 * (aY2 + X2 - dZ2) == X2 * Y2);
321 }
322}
323
325{
326 return G2_zero;
327}
328
330{
331 return G2_one;
332}
333
338
339std::ostream& operator<<(std::ostream &out, const edwards_G2 &g)
340{
341 edwards_G2 copy(g);
342 copy.to_affine_coordinates();
343#ifdef NO_PT_COMPRESSION
344 out << copy.X << OUTPUT_SEPARATOR << copy.Y;
345#else
346 /* storing LSB of Y */
347 out << copy.X << OUTPUT_SEPARATOR << (copy.Y.c0.as_bigint().data[0] & 1);
348#endif
349 return out;
350}
351
352std::istream& operator>>(std::istream &in, edwards_G2 &g)
353{
354 edwards_Fq3 tX, tY;
355
356#ifdef NO_PT_COMPRESSION
357 in >> tX;
359 in >> tY;
360#else
361 /*
362 a x^2 + y^2 = 1 + d x^2 y^2
363 y = sqrt((1-ax^2)/(1-dx^2))
364 */
365 unsigned char Y_lsb;
366 in >> tX;
368
369 in.read((char*)&Y_lsb, 1);
370 Y_lsb -= '0';
371
372 edwards_Fq3 tX2 = tX.squared();
373 const edwards_Fq3 tY2 =
376 tY = tY2.sqrt();
377
378 if ((tY.c0.as_bigint().data[0] & 1) != Y_lsb)
379 {
380 tY = -tY;
381 }
382#endif
383
384 // using inverted coordinates
385 g.X = tY;
386 g.Y = tX;
387 g.Z = tX * tY;
388
389#ifdef USE_MIXED_ADDITION
390 g.to_special();
391#endif
392
393 return in;
394}
395
396void edwards_G2::batch_to_special_all_non_zeros(std::vector<edwards_G2> &vec)
397{
398 std::vector<edwards_Fq3> Z_vec;
399 Z_vec.reserve(vec.size());
400
401 for (auto &el: vec)
402 {
403 Z_vec.emplace_back(el.Z);
404 }
406
408
409 for (size_t i = 0; i < vec.size(); ++i)
410 {
411 vec[i].X = vec[i].X * Z_vec[i];
412 vec[i].Y = vec[i].Y * Z_vec[i];
413 vec[i].Z = one;
414 }
415}
416
417} // libff
Fp3_model inverse() const
Fp3_model squared() const
Fp3_model sqrt() const
bool is_zero() const
Definition fp3.hpp:61
bigint< n > as_bigint() const
static Fp_model< n, modulus > random_element()
edwards_G2 dbl() const
static edwards_G2 random_element()
bool is_well_formed() const
static edwards_G2 zero()
bool operator!=(const edwards_G2 &other) const
bool operator==(const edwards_G2 &other) const
static void batch_to_special_all_non_zeros(std::vector< edwards_G2 > &vec)
edwards_G2 add(const edwards_G2 &other) const
edwards_G2 operator-() const
void print() const
static std::vector< size_t > fixed_base_exp_window_table
static bool initialized
edwards_G2 mixed_add(const edwards_G2 &other) const
static edwards_G2 one()
static edwards_Fq3 mul_by_a(const edwards_Fq3 &elt)
void to_affine_coordinates()
void print_coordinates() const
static edwards_Fq3 mul_by_d(const edwards_Fq3 &elt)
edwards_G2 operator+(const edwards_G2 &other) const
static edwards_G2 G2_one
static std::vector< size_t > wnaf_window_table
static edwards_G2 G2_zero
edwards_G2 mul_by_q() const
bool is_zero() const
bool is_special() const
#define D(var, file, col, who, lev,...)
Definition debug.h:44
#define OUTPUT_SEPARATOR
Fp3_model< edwards_q_limbs, edwards_modulus_q > edwards_Fq3
std::istream & operator>>(std::istream &in, alt_bn128_G1 &g)
edwards_Fq edwards_twist_mul_by_q_Y
void consume_OUTPUT_SEPARATOR(std::istream &in)
edwards_Fq edwards_twist_mul_by_d_c1
edwards_Fq edwards_twist_mul_by_q_Z
std::ostream & operator<<(std::ostream &out, const alt_bn128_G1 &g)
edwards_Fq edwards_twist_mul_by_a_c0
edwards_Fq edwards_twist_mul_by_d_c2
void batch_invert(std::vector< FieldT > &vec)
edwards_Fq edwards_twist_mul_by_d_c0
Definition lib.h:43
Definition dtoa.c:306