40 static constexpr const size_t kBits = kN;
46 const Elt k2, k3, k8, k3b, k9b, k24b;
54 ECPoint(
const Elt& x,
const Elt& y,
const Elt& z) : x(x), y(y), z(z) {}
57 EllipticCurve(
const Elt& a,
const Elt& b,
const Elt& gX,
const Elt& gY,
69 k9b(F.mulf(F.of_scalar(9), b_)),
70 k24b(F.mulf(F.of_scalar(24), b_)) {
71 is_minus_3_a_ = (a_ == F.negf(k3));
72 is_zero_a_ = (a_ == F.zero());
79 bool equal(
const ECPoint& p,
const ECPoint& q)
const {
81 if (q.x == f_.zero() && q.z == f_.zero() && q.y != f_.zero() &&
82 p.x == f_.zero() && p.z == f_.zero() && p.y != f_.zero()) {
85 if (q.x == p.x && q.z == p.z && q.y == p.y) {
89 return (f_.mulf(p.x, q.z) == f_.mulf(q.x, p.z) &&
90 f_.mulf(p.y, q.z) == f_.mulf(q.y, p.z));
96 bool is_on_curve(
const ECPoint& p)
const {
97 if (equal(p, zero())) {
101 if (p.z != f_.one()) {
104 return is_on_curve(p.x, p.y);
109 ECPoint point(
const Elt& x,
const Elt& y)
const {
111 check(is_on_curve(p),
"Invalid curve point");
115 void normalize(
ECPoint& p)
const {
116 if (p.z == f_.zero())
return;
124 addE(p3.x, p3.y, p3.z, p3.x, p3.y, p3.z, p2.x, p2.y, p2.z);
127 void doubleE(
ECPoint& p3)
const {
128 doubleE(p3.x, p3.y, p3.z, p3.x, p3.y, p3.z);
148 for (
size_t d = 0; d < N::kLimbs; ++d) {
149 auto nd = scalar.limb_[d];
150 for (
size_t i = 0; i < N::kBitsPerLimb; ++i) {
169 return scalar_multf(p[0], scalar[0]);
171 return bos_coster(n, p, scalar);
175 ECPoint zero()
const {
return ECPoint(f_.zero(), f_.one(), f_.zero()); }
179 bool is_on_curve(
const Elt& X,
const Elt& Y)
const {
180 Elt left = f_.mulf(Y, Y);
181 Elt X3 = f_.mulf(X, f_.mulf(X, X));
182 Elt right = f_.addf(f_.addf(X3, f_.mulf(a_, X)), b_);
183 return left == right;
186 void addE(Elt& X3o, Elt& Y3o, Elt& Z3o,
const Elt& X1,
const Elt& Y1,
187 const Elt& Z1,
const Elt& X2,
const Elt& Y2,
const Elt& Z2)
const {
189 if (is_zero_a_)
return addEZeroA(X3o, Y3o, Z3o, X1, Y1, Z1, X2, Y2, Z2);
191 return addEMinus3A(X3o, Y3o, Z3o, X1, Y1, Z1, X2, Y2, Z2);
201 if (X1 == f_.zero() && Z1 == f_.zero()) {
208 if (X2 == f_.zero() && Z2 == f_.zero()) {
215 Elt Y1Z2 = f_.mulf(Y1, Z2);
216 Elt X1Z2 = f_.mulf(X1, Z2);
217 Elt u = f_.subf(f_.mulf(Y2, Z1), Y1Z2);
218 Elt v = f_.subf(f_.mulf(X2, Z1), X1Z2);
219 if (u == f_.zero()) {
220 doubleE(X3o, Y3o, Z3o, X1, Y1, Z1);
227 if (v == f_.zero()) {
234 Elt Z1Z2 = f_.mulf(Z1, Z2);
235 Elt uu = f_.mulf(u, u);
236 Elt vv = f_.mulf(v, v);
237 Elt vvv = f_.mulf(v, vv);
238 Elt R = f_.mulf(vv, X1Z2);
239 Elt A = f_.subf(f_.subf(f_.mulf(uu, Z1Z2), vvv), f_.mulf(k2, R));
240 Elt X3 = f_.mulf(v, A);
241 Elt Y3 = f_.subf(f_.mulf(u, f_.subf(R, A)), f_.mulf(vvv, Y1Z2));
242 Elt Z3 = f_.mulf(vvv, Z1Z2);
249 void doubleE(Elt& X3o, Elt& Y3o, Elt& Z3o,
const Elt& X,
const Elt& Y,
250 const Elt& Z)
const {
252 if (is_zero_a_)
return doubleEZeroA(X3o, Y3o, Z3o, X, Y, Z);
253 if (is_minus_3_a_)
return doubleEMinus3A(X3o, Y3o, Z3o, X, Y, Z);
261 if (X == f_.zero() && Z == f_.zero()) {
268 Elt Z2 = f_.mulf(Z, Z);
269 Elt X2 = f_.mulf(X, X);
270 Elt X2_3 = f_.addf(f_.addf(X2, X2), X2);
271 Elt s = f_.mulf(Y, Z);
272 Elt ss = f_.mulf(s, s);
273 Elt sss = f_.mulf(s, ss);
274 Elt sss_2 = f_.addf(sss, sss);
275 Elt w = f_.addf(f_.mulf(a_, Z2), X2_3);
276 Elt R = f_.mulf(Y, s);
277 Elt sss_4 = f_.addf(sss_2, sss_2);
278 Elt B = f_.mulf(X, R);
279 Elt sss_8 = f_.addf(sss_4, sss_4);
280 Elt B_2 = f_.addf(B, B);
281 Elt R2 = f_.mulf(R, R);
282 Elt B_4 = f_.addf(B_2, B_2);
283 Elt B_8 = f_.addf(B_4, B_4);
284 Elt w2 = f_.mulf(w, w);
285 Elt h = f_.subf(w2, B_8);
286 Elt s_2 = f_.addf(s, s);
287 Elt X3 = f_.mulf(h, s_2);
288 Elt R2_2 = f_.addf(R2, R2);
289 Elt R2_4 = f_.addf(R2_2, R2_2);
290 Elt R2_8 = f_.addf(R2_4, R2_4);
291 Elt Y3 = f_.subf(f_.mulf(w, f_.subf(B_4, h)), R2_8);
307 void addEZeroA(Elt& X3o, Elt& Y3o, Elt& Z3o,
const Elt& X1,
const Elt& Y1,
308 const Elt& Z1,
const Elt& X2,
const Elt& Y2,
309 const Elt& Z2)
const {
310 Elt t0 = f_.mulf(X2, Y1);
311 Elt t1 = f_.mulf(X1, Y2);
312 Elt t2 = f_.addf(t1, t0);
313 Elt t3 = f_.mulf(Y1, Y2);
314 Elt t4 = f_.mulf(Z1, Z2);
315 Elt t5 = f_.mulf(Y1, Z2);
316 Elt t6 = f_.mulf(Y2, Z1);
317 Elt t7 = f_.addf(t5, t6);
318 Elt t8 = f_.mulf(X1, Z2);
319 Elt t9 = f_.mulf(X2, Z1);
320 Elt t10 = f_.addf(t8, t9);
321 Elt t11 = f_.mulf(X1, X2);
322 Elt t12 = f_.mulf(k3b, t4);
323 Elt t13 = f_.addf(t3, t12);
324 Elt t14 = f_.subf(t3, t12);
326 X3o = f_.subf(f_.mulf(t2, t14), f_.mulf(k3b, f_.mulf(t7, t10)));
327 Y3o = f_.addf(f_.mulf(t13, t14), f_.mulf(k9b, f_.mulf(t11, t10)));
328 Z3o = f_.addf(f_.mulf(t7, t13), f_.mulf(k3, f_.mulf(t11, t2)));
334 void addEMinus3A(Elt& X3o, Elt& Y3o, Elt& Z3o,
const Elt& X1,
const Elt& Y1,
335 const Elt& Z1,
const Elt& X2,
const Elt& Y2,
336 const Elt& Z2)
const {
337 Elt t0 = f_.mulf(X1, X2);
338 Elt t1 = f_.mulf(Y1, Y2);
339 Elt t2 = f_.mulf(Z1, Z2);
340 Elt t3 = f_.addf(X1, Y1);
341 Elt t4 = f_.addf(X2, Y2);
342 t3 = f_.mulf(t3, t4);
343 t4 = f_.addf(t0, t1);
344 t3 = f_.subf(t3, t4);
345 t4 = f_.addf(Y1, Z1);
346 Elt X3 = f_.addf(Y2, Z2);
347 t4 = f_.mulf(t4, X3);
348 X3 = f_.addf(t1, t2);
349 t4 = f_.subf(t4, X3);
350 X3 = f_.addf(X1, Z1);
351 Elt Y3 = f_.addf(X2, Z2);
352 X3 = f_.mulf(X3, Y3);
353 Y3 = f_.addf(t0, t2);
354 Y3 = f_.subf(X3, Y3);
355 Elt Z3 = f_.mulf(b_, t2);
356 X3 = f_.subf(Y3, Z3);
357 Z3 = f_.addf(X3, X3);
358 X3 = f_.addf(X3, Z3);
359 Z3 = f_.subf(t1, X3);
360 X3 = f_.addf(t1, X3);
361 Y3 = f_.mulf(b_, Y3);
362 t1 = f_.addf(t2, t2);
363 t2 = f_.addf(t1, t2);
364 Y3 = f_.subf(Y3, t2);
365 Y3 = f_.subf(Y3, t0);
366 t1 = f_.addf(Y3, Y3);
367 Y3 = f_.addf(t1, Y3);
368 t1 = f_.addf(t0, t0);
369 t0 = f_.addf(t1, t0);
370 t0 = f_.subf(t0, t2);
371 t1 = f_.mulf(t4, Y3);
372 t2 = f_.mulf(t0, Y3);
373 Y3 = f_.mulf(X3, Z3);
374 Y3 = f_.addf(Y3, t2);
375 X3 = f_.mulf(t3, X3);
376 X3 = f_.subf(X3, t1);
377 Z3 = f_.mulf(t4, Z3);
378 t1 = f_.mulf(t3, t0);
379 Z3 = f_.addf(Z3, t1);
389 void doubleEMinus3A(Elt& X3o, Elt& Y3o, Elt& Z3o,
const Elt& X,
const Elt& Y,
390 const Elt& Z)
const {
391 Elt t0 = f_.mulf(X, X);
392 Elt t1 = f_.mulf(Y, Y);
393 Elt t2 = f_.mulf(Z, Z);
394 Elt t3 = f_.mulf(X, Y);
395 t3 = f_.addf(t3, t3);
396 Elt Z3 = f_.mulf(X, Z);
397 Z3 = f_.addf(Z3, Z3);
398 Elt Y3 = f_.mulf(b_, t2);
399 Y3 = f_.subf(Y3, Z3);
400 Elt X3 = f_.addf(Y3, Y3);
401 Y3 = f_.addf(X3, Y3);
402 X3 = f_.subf(t1, Y3);
403 Y3 = f_.addf(t1, Y3);
404 Y3 = f_.mulf(X3, Y3);
405 X3 = f_.mulf(X3, t3);
406 t3 = f_.addf(t2, t2);
407 t2 = f_.addf(t2, t3);
408 Z3 = f_.mulf(b_, Z3);
409 Z3 = f_.subf(Z3, t2);
410 Z3 = f_.subf(Z3, t0);
411 t3 = f_.addf(Z3, Z3);
412 Z3 = f_.addf(Z3, t3);
413 t3 = f_.addf(t0, t0);
414 t0 = f_.addf(t3, t0);
415 t0 = f_.subf(t0, t2);
416 t0 = f_.mulf(t0, Z3);
417 Y3 = f_.addf(Y3, t0);
419 t0 = f_.addf(t0, t0);
420 Z3 = f_.mulf(t0, Z3);
421 X3 = f_.subf(X3, Z3);
422 Z3 = f_.mulf(t0, t1);
423 Z3 = f_.addf(Z3, Z3);
424 Z3 = f_.addf(Z3, Z3);
438 void doubleEZeroA(Elt& X3o, Elt& Y3o, Elt& Z3o,
const Elt& X,
const Elt& Y,
439 const Elt& Z)
const {
440 Elt t0 = f_.mulf(X, Y);
441 Elt t1 = f_.mulf(Y, Y);
442 Elt t2 = f_.mulf(Z, Z);
443 Elt t4 = f_.mulf(Y, Z);
444 Elt t5 = f_.mulf(k9b, t2);
445 Elt t6 = f_.subf(t1, t5);
446 Elt t7 = f_.mulf(k3b, t2);
447 Elt t8 = f_.addf(t1, t7);
448 X3o = f_.mulf(k2, f_.mulf(t0, t6));
449 Y3o = f_.addf(f_.mulf(t6, t8), f_.mulf(k24b, f_.mulf(t1, t2)));
450 Z3o = f_.mulf(k8, f_.mulf(t1, t4));
513 void bury(
size_t i,
size_t n,
ECPoint p[], N s[],
const ECPoint& tp,
518 if (2 * i + 1 < n && s[cld] < s[2 * i + 1]) {
540 void bury0(
size_t n,
ECPoint p[], N s[])
const {
548 bury(1, n, p, s, tp, ts);
554 check(n >= 2,
"n >= 2");
558 for (
size_t i = (n / 2); i >= 1; --i) {
561 bury(i, n, p, s,
ECPoint(p[i]), N(s[i]));
566 while (s[0] != N{}) {
576 uint64_t lsb = s[0].shiftr(1);