Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
bn.cpp
Go to the documentation of this file.
1#include <stdio.h>
2#include <memory.h>
3#ifndef XBYAK_NO_OP_NAMES
4 #define XBYAK_NO_OP_NAMES
5#endif
6#include "xbyak/xbyak_util.h"
8#include "bn.h"
9#include <iostream>
10#include "util.h"
11#include <cybozu/benchmark.hpp>
12#include "test_point.hpp"
13
14#define NUM_OF_ARRAY(x) (sizeof(x) / sizeof(*x))
15
16using namespace bn;
17using namespace ecop;
18
19static int s_errNum = 0;
20static int s_testNum = 0;
21
22#define TEST_EQUAL(x, y) { s_testNum++; if (x != y) { s_errNum++; printf("%s(%d): err %s != %s\n", __FILE__, __LINE__, #x, #y); std::cout << "lhs=" << (x) << "\nrhs=" << (y) << std::endl; } }
23#define TEST_ASSERT(x) { s_testNum++; if (!(x)) { s_errNum++; printf("%s(%d): err assert %s\n", __FILE__, __LINE__, #x); } }
24
25#define FATAL_EXIT(msg) { printf("%s(%d): err %s\n", __FILE__, __LINE__, msg); exit(1); }
26
29
30void benchFp()
31{
32 Fp x("1234566239428049280498203948209482039482");
33 Fp y("999999999999999999999999999999999999999");
34 Fp::Dbl d;
35 CYBOZU_BENCH("Fp::add ", Fp::add, x, x, y);
36 CYBOZU_BENCH("Fp::sub ", Fp::sub, x, x, y);
37 CYBOZU_BENCH("Fp::neg ", Fp::neg, x, x);
38 CYBOZU_BENCH("Fp::mul ", Fp::mul, x, x, y);
39 CYBOZU_BENCH("Fp::inv ", Fp::inv, x, x);
40 CYBOZU_BENCH("mul256 ", Fp::Dbl::mul, d, x, y);
41 CYBOZU_BENCH("mod512 ", Fp::Dbl::mod, x, d);
42 CYBOZU_BENCH("Fp::divBy2", Fp::divBy2, x, x);
43 CYBOZU_BENCH("Fp::divBy4", Fp::divBy4, x, x);
44}
46{
47 Fp2 x, y;
48 x.a_.set("4");
49 x.b_.set("464652165165");
50 y = x * x;
51 CYBOZU_BENCH("Fp2::add ", Fp2::add, x, x, y);
52 CYBOZU_BENCH("Fp2::addNC ", Fp2::addNC, x, x, y);
53 CYBOZU_BENCH("Fp2::sub ", Fp2::sub, x, x, y);
54 CYBOZU_BENCH("Fp2::neg ", Fp2::neg, x, x);
55 CYBOZU_BENCH("Fp2::mul ", Fp2::mul, x, x, y);
56 CYBOZU_BENCH("Fp2::inverse ", x.inverse);
57 CYBOZU_BENCH("Fp2::square ", Fp2::square, x, x);
58 CYBOZU_BENCH("Fp2::mul_xi ", Fp2::mul_xi, x, x);
59 CYBOZU_BENCH("Fp2::mul_Fp_0", Fp2::mul_Fp_0, x, x, Param::half);
60 CYBOZU_BENCH("Fp2::mul_Fp_1", Fp2::mul_Fp_1, x, Param::half);
61 CYBOZU_BENCH("Fp2::divBy2 ", Fp2::divBy2, x, x);
62 CYBOZU_BENCH("Fp2::divBy4 ", Fp2::divBy4, x, x);
63}
64
66{
67 puts(__FUNCTION__);
68 const Point& pt = selectPoint(cp);
69 const Fp2 g2[3] = {
70 Fp2(Fp(pt.g2.aa), Fp(pt.g2.ab)),
71 Fp2(Fp(pt.g2.ba), Fp(pt.g2.bb)),
72 Fp2(1, 0),
73 };
74 const Fp g1[3] = { pt.g1.a, pt.g1.b, 1 };
75 Fp12 e;
76 benchFp();
77 benchFp2();
78 CYBOZU_BENCH("finalexp", e.final_exp);
79 CYBOZU_BENCH("pairing", opt_atePairingJac<Fp>, e, g2, g1);
80
81 Fp12 e2;
82 std::vector<Fp6> Qcoeff;
83 Fp2 precQ[3];
84 bn::components::precomputeG2(Qcoeff, precQ, g2);
85 Fp precP[3];
86 bn::ecop::NormalizeJac(precP, g1);
87 bn::components::millerLoop(e2, Qcoeff, precP);
88 e2.final_exp();
89 TEST_EQUAL(e, e2);
90 CYBOZU_BENCH("precomp ", bn::components::precomputeG2, Qcoeff, precQ, g2);
91 CYBOZU_BENCH("millerLoop", bn::components::millerLoop, e2, Qcoeff, precP);
92}
93
94#ifdef BN_SUPPORT_SNARK
95
96int main(int argc, char *argv[])
97{
98 int b = 3;
99 if (argc >= 2) {
100 b = atoi(argv[1]);
101 if (b != 3 && b != 82) {
102 printf("not support b=%d\n", b);
103 return 1;
104 }
105 }
106 printf("SNARK b = %d\n", b);
107 bn::CurveParam cp = bn::CurveSNARK1;
108 cp.b = b;
109 bn::Param::init(cp);
110 test_multi(cp);
111 if (sclk.getCount()) printf("sclk:%.2fclk(%dtimes)\n", sclk.getClock() / double(sclk.getCount()), sclk.getCount());
112 printf("err=%d(test=%d)\n", s_errNum, s_testNum);
113}
114#else
115/*
116 generate a value of the X-coordinate of P
117*/
118const Fp genPx()
119{
120 const Fp Px = Fp(2);
121 return Px;
122}
123/*
124 generate a value of the Y-coordinate of P
125*/
126const Fp genPy()
127{
128 const Fp Py = Fp("16740896641879863340107777353588575149660814923656713498672603551465628253431");
129 return Py;
130}
131
132/*
133 generate a value of the X-coordinate of [2]P
134*/
135const Fp genP2x()
136{
137 const Fp P2x = Fp("13438486984812665827952643313785387127911349697151255879146972340858203091778");
138 return P2x;
139}
140/*
141 generate a value of the Y-coordinate of [2]P
142*/
143const Fp genP2y()
144{
145 const Fp P2y = Fp("12741389316352206200828479361093127917015298445269456291074734498988157668221");
146 return P2y;
147}
148
149template<class F>
150void SetJacobi(F out[3], const F* in)
151{
152 copy(out, in);
153 const int z = 123;
154 out[0] *= z * z;
155 out[1] *= z * z * z;
156 out[2] *= z;
157}
158
160{
161 puts(__FUNCTION__);
162 const Fp P[] = { genPx(), genPy(), Fp(1) };
163 const Fp P2[] = { genP2x(), genP2y(), Fp(1) };
164 const Fp Zero[] = { 1, 1, 0 };
165 const struct {
166 const Fp* ok; // ok = 2x
167 const Fp* x;
168 } tbl[] = {
169 { P2, P },
170 { Zero, Zero },
171 };
172
173 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
174 Fp x[3];
175 SetJacobi(x, tbl[i].x);
176 const Fp* ok = tbl[i].ok;
177
178 for (int m = 0; m < 2; m++) {
179 Fp out[3];
180
181 if (m == 0) {
182 // dst != src
183 ECDouble(out, x);
184 } else {
185 out[0] = x[0];
186 out[1] = x[1];
187 out[2] = x[2];
188 // dst != src
189 ECDouble(out, out);
190 }
191
193 NormalizeJac(out, out);
195
196 if (ok[2] != 0) {
197 TEST_EQUAL(out[0], ok[0]);
198 TEST_EQUAL(out[1], ok[1]);
199 }
200
201 TEST_EQUAL(out[2], ok[2]);
202 }
203 }
204}
205
207{
208 puts(__FUNCTION__);
209 const Fp P[] = { genPx(), genPy(), Fp(1) };
210 const Fp negP[] = { genPx(), -genPy(), Fp(1) };
211 const Fp P2[] = { genP2x(), genP2y(), Fp(1) };
212 const Fp P3[] = {
213 Fp("933228262834212904718933563457318550549399284524392769385206412559597436928"),
214 Fp("13081617668227268048378253503661144166646030151223471427486357073175298320248"),
215 Fp(1),
216 };
217 const Fp Zero[] = { 1, 1, 0 };
218 {
219 const struct {
220 const Fp* ok; // ok = x + y
221 const Fp* x;
222 const Fp* y;
223 } tbl[] = {
224 { P3, P, P2 },
225 { P3, P2, P },
226 { P2, P, P },
227 { Zero, P, negP },
228 { Zero, negP, P },
229
230 { P, P, Zero },
231 { P, Zero, P },
232 { Zero, Zero, Zero },
233 };
234
235 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
236 Fp x[3]; SetJacobi(x, tbl[i].x);
237 Fp y[3]; SetJacobi(y, tbl[i].y);
238 const Fp* ok = tbl[i].ok;
239
240 for (int m = 0; m < 3; m++) {
241 Fp out[3];
242
243 if (m == 0) { // z <- (x, y)
244 ECAdd(out, x, y);
245 } else if (m == 1) { // x <- (x, y)
246 copy(out, x);
247 ECAdd(out, out, y);
248 } else { // y <- (x, y)
249 copy(out, y);
250 ECAdd(out, x, out);
251 }
252
254 NormalizeJac(out, out);
256
257 if (ok[2] != 0) {
258 TEST_EQUAL(out[0], ok[0]);
259 TEST_EQUAL(out[1], ok[1]);
260 }
261
262 TEST_EQUAL(out[2], ok[2]);
263 }
264 }
265 }
266 {
267 const struct {
268 const Fp* ok; // ok = 2x
269 const Fp* x;
270 } tbl[] = {
271 { P2, P },
272 { Zero, Zero },
273 };
274
275 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
276 Fp x[3]; SetJacobi(x, tbl[i].x);
277 const Fp* ok = tbl[i].ok;
278
279 for (int m = 0; m < 2; m++) {
280 Fp out[3];
281
282 if (m == 0) { // z <- (x, x)
283 ECAdd(out, x, x);
284 } else {
285 copy(out, x);
286 ECAdd(out, out, out); // x <- (x, x)
287 }
288
290 NormalizeJac(out, out);
292
293 if (ok[2] != 0) {
294 TEST_EQUAL(out[0], ok[0]);
295 TEST_EQUAL(out[1], ok[1]);
296 }
297
298 TEST_EQUAL(out[2], ok[2]);
299 }
300 }
301 }
302}
303
304void testECOperationsG1(bool allBench)
305{
306 puts(__FUNCTION__);
307 const Fp P[] = { genPx(), genPy(), Fp(1) };
309 const Fp R[] = {
310 Fp("13444485882265322272857095018562747159513775856924555608551532122942502696033"),
311 Fp("11811997307285544251176681325629039017467625014708607213193666012921830535998"),
312 Fp(1),
313 };
315 const Fp P2_ok[] = { genP2x(), genP2y(), Fp(1) };
316 TEST_ASSERT(isOnECJac3(P2_ok));
317 const Fp P3_ok[] = {
318 Fp("933228262834212904718933563457318550549399284524392769385206412559597436928"),
319 Fp("13081617668227268048378253503661144166646030151223471427486357073175298320248"),
320 Fp(1),
321 };
322 TEST_ASSERT(isOnECJac3(P3_ok));
323 const Fp PR_ok[] = {
324 Fp("5029559281027098065112074313654538061170641740632027092904459697655977527307"),
325 Fp("8600928869174184710378059261155172010154737801304483073001259795547035852644"),
326 Fp(1),
327 };
328 TEST_ASSERT(isOnECJac3(PR_ok));
329 const std::string m_str("9347746330740818252600716999005395295745642941583534686803606077666502");
330 const Fp Pm_ok[] = {
331 Fp("8336933749104329731435220896541057907796368507118046070748143351359530106012"),
332 Fp("4188048486869311245492662268177668835013141885357103548787568172806640854865"),
333 Fp(1),
334 };
335 TEST_ASSERT(isOnECJac3(Pm_ok));
336 {
337 Fp P2[3];
338 ECDouble(P2, P);
340 NormalizeJac(P2, P2);
342 TEST_EQUAL(P2[0], P2_ok[0]);
343 TEST_EQUAL(P2[1], P2_ok[1]);
344 TEST_EQUAL(P2[2], P2_ok[2]);
345 if (allBench) CYBOZU_BENCH("ECDouble", ECDouble<Fp>, P2, P);
346 }
347 {
348 Fp P3[] = { P[0], P[1], P[2], };
349 Fp PR[] = { P[0], P[1], P[2], };
350 ECAdd(P3, P3, P2_ok);
351 ECAdd(PR, PR, R);
354 NormalizeJac(P3, P3);
355 NormalizeJac(PR, PR);
358 TEST_EQUAL(P3[0], P3_ok[0]);
359 TEST_EQUAL(P3[1], P3_ok[1]);
360 TEST_EQUAL(P3[2], P3_ok[2]);
361 TEST_EQUAL(PR[0], PR_ok[0]);
362 TEST_EQUAL(PR[1], PR_ok[1]);
363 TEST_EQUAL(PR[2], PR_ok[2]);
364 if (allBench) CYBOZU_BENCH("ECAdd", ECAdd<Fp>, PR, P, R);
365 }
366 {
367 mie::Vuint m;
368 Fp Pm[3], Pm_norm[3];
369 m = 0;
370 ScalarMult(Pm, P, m);
372 TEST_EQUAL(Pm[2], 0);
373 NormalizeJac(Pm_norm, Pm);
374 TEST_ASSERT(isOnECJac3(Pm_norm));
375 TEST_EQUAL(Pm_norm[2], 0);
376
377 m = 1;
378 ScalarMult(Pm, P, m);
380 NormalizeJac(Pm_norm, Pm);
381 TEST_ASSERT(isOnECJac3(Pm_norm));
382 TEST_EQUAL(Pm_norm[0], P[0]);
383 TEST_EQUAL(Pm_norm[1], P[1]);
384 TEST_EQUAL(Pm_norm[2], P[2]);
385
386 m = 2;
387 ScalarMult(Pm, P, m);
389 NormalizeJac(Pm_norm, Pm);
390 TEST_ASSERT(isOnECJac3(Pm_norm));
391 TEST_EQUAL(Pm_norm[0], P2_ok[0]);
392 TEST_EQUAL(Pm_norm[1], P2_ok[1]);
393 TEST_EQUAL(Pm_norm[2], P2_ok[2]);
394
395 m = 3;
396 ScalarMult(Pm, P, m);
398 NormalizeJac(Pm_norm, Pm);
399 TEST_ASSERT(isOnECJac3(Pm_norm));
400 TEST_EQUAL(Pm_norm[0], P3_ok[0]);
401 TEST_EQUAL(Pm_norm[1], P3_ok[1]);
402 TEST_EQUAL(Pm_norm[2], P3_ok[2]);
403
404 m.set(m_str);
405 ScalarMult(Pm, P, m);
407 NormalizeJac(Pm, Pm);
409 TEST_EQUAL(Pm[0], Pm_ok[0]);
410 TEST_EQUAL(Pm[1], Pm_ok[1]);
411 TEST_EQUAL(Pm[2], Pm_ok[2]);
412
413 if (allBench) CYBOZU_BENCH("ScalarMult", (ScalarMult<Fp, mie::Vuint>), Pm, P, m);
414 }
415 {
416 const mie::Vuint& r = Param::r;
417 Fp Pz[3], Rz[3];
418 ScalarMult(Pz, P, r);
419 ScalarMult(Rz, R, r);
420 TEST_ASSERT(Pz[2].isZero());
421 TEST_ASSERT(Rz[2].isZero());
422 }
423}
424
426{
427 puts(__FUNCTION__);
428 Fp2 x, y, z;
429 x.a_ = 1;
430 x.b_ = 2;
431 y.a_ = 3;
432 y.b_ = 4;
433 Fp2::mul(z, x, y);
434 x.a_.set("1");
435 x.b_.set("0");
436 z = x * x;
437 PUT(x);
438 Fp2::square(y, x);
439 TEST_EQUAL(z, y);
440 x.a_.set("4");
441 x.b_.set("464652165165");
442 z.a_.set("16798108731015832284940804142231733909889187121439069633032080833550314387514");
443 z.b_.set("3717217321320");
444 y = x * x;
445 Fp2::square(x, x);
446 TEST_EQUAL(x, z);
447 TEST_EQUAL(y, z);
448 {
449 std::ostringstream oss;
450 oss << x;
451 std::istringstream iss(oss.str());
452 Fp2 w;
453 iss >> w;
454 TEST_EQUAL(x, w);
455 }
456 y = mie::power(x, p * p);
457 TEST_EQUAL(y, x);
458 y = x;
459 y.inverse();
460 x *= y;
461 TEST_EQUAL(x, Fp2(1));
462 {
463 Fp c1 = x.a_ / Fp(2);
464 Fp c2 = x.a_;
465 Fp::divBy2(c2, c2);
466 TEST_EQUAL(c2, c1);
467 }
468 {
469 Fp c1 = x.b_ / Fp(2);
470 Fp c2 = x.b_;
471 Fp::divBy2(c2, c2);
472 TEST_EQUAL(c2, c1);
473 }
474 {
475 Fp c1 = y.a_ / Fp(2);
476 Fp c2 = y.a_;
477 Fp::divBy2(c2, c2);
478 TEST_EQUAL(c2, c1);
479 }
480 {
481 Fp c1 = y.b_ / Fp(2);
482 Fp c2 = y.b_;
483 Fp::divBy2(c2, c2);
484 TEST_EQUAL(c2, c1);
485 }
486 {
487 Fp c1 = z.a_ / Fp(2);
488 Fp c2 = z.a_;
489 Fp::divBy2(c2, c2);
490 TEST_EQUAL(c2, c1);
491 }
492 {
493 Fp c1 = z.b_ / Fp(2);
494 Fp c2 = z.b_;
495 Fp::divBy2(c2, c2);
496 TEST_EQUAL(c2, c1);
497 }
498 {
499 Fp c1 = x.a_ / Fp(4);
500 Fp c2 = x.a_;
501 Fp::divBy4(c2, c2);
502 TEST_EQUAL(c2, c1);
503 }
504 {
505 Fp c1 = x.b_ / Fp(4);
506 Fp c2 = x.b_;
507 Fp::divBy4(c2, c2);
508 TEST_EQUAL(c2, c1);
509 }
510 {
511 Fp c1 = y.a_ / Fp(4);
512 Fp c2 = y.a_;
513 Fp::divBy4(c2, c2);
514 TEST_EQUAL(c2, c1);
515 }
516 {
517 Fp c1 = y.b_ / Fp(4);
518 Fp c2 = y.b_;
519 Fp::divBy4(c2, c2);
520 TEST_EQUAL(c2, c1);
521 }
522 {
523 Fp c1 = z.a_ / Fp(4);
524 Fp c2 = z.a_;
525 Fp::divBy4(c2, c2);
526 TEST_EQUAL(c2, c1);
527 }
528 {
529 Fp c1 = z.b_ / Fp(4);
530 Fp c2 = z.b_;
531 Fp::divBy4(c2, c2);
532 TEST_EQUAL(c2, c1);
533 }
534 Fp2 r2(Fp(2), Fp(0));
535 r2.inverse();
536 {
537 Fp2 c1 = x * r2;// Fp2(Fp(2), Fp(0));
538 Fp2 c2 = x;
539 Fp2::divBy2(c2, c2);
540 TEST_EQUAL(c2, c1);
541 }
542 {
543 Fp2 c1 = y * r2;
544 Fp2 c2 = y;
545 Fp2::divBy2(c2, c2);
546 TEST_EQUAL(c2, c1);
547 }
548 {
549 Fp2 c1 = z * r2;
550 Fp2 c2 = z;
551 Fp2::divBy2(c2, c2);
552 TEST_EQUAL(c2, c1);
553 }
554}
555
556/*
557 generate a value of the X-coordinate of Q
558*/
559const Fp2& genQx()
560{
561 static const Fp2 Qx = Fp2(
562 Fp("13234664681033688271405396239524358974366484883419628236101274746557464997054"),
563 Fp("11347691494386824311357230151706543132011346014309658325337514955760433353199")
564 );
565 return Qx;
566}
567/*
568 generate a value of the Y-coordinate of Q
569*/
570const Fp2& genQy()
571{
572 static const Fp2 Qy = Fp2(
573 Fp("9427224573130940705767837740977388851395498800066112237265227139877389298881"),
574 Fp("8452141316509224651353689669356928563000175149166480473836682926961687453514")
575 );
576 return Qy;
577}
578
579/*
580 generate a value of the X-coordinate of [2]Q
581*/
582const Fp2& genQ2x()
583{
584 static const Fp2 Q2x = Fp2(
585 Fp("5299180442706306781938040029147283818308705141288620744338313273731299805815"),
586 Fp("15797930548095856607649462137302524883761892212429298307727251696384886639045")
587 );
588 return Q2x;
589}
590/*
591 generate a value of the Y-coordinate of [2]Q
592*/
593const Fp2& genQ2y()
594{
595 static const Fp2 Q2y = Fp2(
596 Fp("14682155566465612687855553028405011181016442868657350988232774125667855691350"),
597 Fp("16774596877583816470230777985570065066758171976339091353731418650582998086894")
598 );
599 return Q2y;
600}
601
603{
604 puts(__FUNCTION__);
605 const Fp2 P[] = { genQx(), genQy(), Fp2(Fp(1), Fp(0)) };
607 /*
608 R = [m]P,
609 m = 5966028534901141772758784140942452307515635636755408154850488537894844702903
610 */
611 const Fp2 R[] = {
612 Fp2(Fp("11704862095684563340633177014105692338896570212191553344841646079297773588350"),
613 Fp("8109660419091099176077386016058664786484443690836266670000859598224113683590")),
614 Fp2(Fp("13675004707765291840926741134330657174325775842323897203730447415462283202661"),
615 Fp("6686821593302402098300348923000142044418144174058402521315042066378362212321")),
616 Fp2(Fp(1), Fp(0)),
617 };
619 /*
620 P2 = P + P
621 */
622 const Fp2 P2_ok[] = { genQ2x(), genQ2y(), Fp2(Fp(1), Fp(0)) };
624 /*
625 P3 = P + P + P
626 */
627 const Fp2 P3_ok[] = {
628 Fp2(Fp("5041208034834306969246893597801606913952969715168759592126996067188338654460"),
629 Fp("4745545055096211316438209286296610929317392331700796959265362461502810670741")),
630 Fp2(Fp("4448845430036386900904134218385919238634516280940850750340057793276116990520"),
631 Fp("5381197710638591824110650873873102215710463161465576982098481156644922737066")),
632 Fp2(Fp(1), Fp(0)),
633 };
635 /*
636 PR = P + R
637 */
638 const Fp2 PR_ok[] = {
639 Fp2(Fp("4101018695001932981939478048097100312454053747763620019092459247845054185862"),
640 Fp("11837424651832479256515762856497142957022424405035735958314961199911873048158")),
641 Fp2(Fp("4188277960223912253520496835244041970690458283101292677577969922331161931355"),
642 Fp("6626563699999679639856135562000857142994474772523438562835858347560344528530")),
643 Fp2(Fp(1), Fp(0)),
644 };
646 const std::string m_str("9347746330740818252600716999005395295745642941583534686803606077666502");
647 const Fp2 Pm_ok[] = {
648 Fp2(Fp("10441210346477881509066116513368913513335705597787319222238764774307447511387"),
649 Fp("14433824588814776544086946350203752791948488948859728417684455048057787177915")),
650 Fp2(Fp("5562925282053339482485224304075873800061135879275456976861613117140339306723"),
651 Fp("4780189879307383623106336041945958171623286554407266664048019152689513531681")),
652 Fp2(Fp(1), Fp(0)),
653 };
655 {
656 Fp2 P2[3];
657 ECDouble(P2, P);
659 Fp2 P2_norm[3];
660 NormalizeJac(P2_norm, P2);
662 TEST_EQUAL(P2_norm[0], P2_ok[0]);
663 TEST_EQUAL(P2_norm[1], P2_ok[1]);
664 TEST_EQUAL(P2_norm[2], P2_ok[2]);
665 }
666 {
667 Fp2 P3[3], PR[3];
668 ECAdd(P3, P, P2_ok);
669 ECAdd(PR, P, R);
672 Fp2 P3_norm[3], PR_norm[3];
673 NormalizeJac(P3_norm, P3);
674 NormalizeJac(PR_norm, PR);
677 TEST_EQUAL(P3_norm[0], P3_ok[0]);
678 TEST_EQUAL(P3_norm[1], P3_ok[1]);
679 TEST_EQUAL(P3_norm[2], P3_ok[2]);
680 TEST_EQUAL(PR_norm[0], PR_ok[0]);
681 TEST_EQUAL(PR_norm[1], PR_ok[1]);
682 TEST_EQUAL(PR_norm[2], PR_ok[2]);
683 }
684 {
685 mie::Vuint m;
686 Fp2 Pm[3], Pm_norm[3];
687 {
688 m = 0;
689 ScalarMult(Pm, P, m);
691 TEST_EQUAL(Pm[2], 0);
692 NormalizeJac(Pm_norm, Pm);
694 TEST_EQUAL(Pm_norm[2], 0);
695 }
696 {
697 m = 1;
698 ScalarMult(Pm, P, m);
700 NormalizeJac(Pm_norm, Pm);
702 TEST_EQUAL(Pm_norm[0], P[0]);
703 TEST_EQUAL(Pm_norm[1], P[1]);
704 TEST_EQUAL(Pm_norm[2], P[2]);
705 }
706 {
707 m = 2;
708 ScalarMult(Pm, P, m);
710 NormalizeJac(Pm_norm, Pm);
712 TEST_EQUAL(Pm_norm[0], P2_ok[0]);
713 TEST_EQUAL(Pm_norm[1], P2_ok[1]);
714 TEST_EQUAL(Pm_norm[2], P2_ok[2]);
715 }
716 {
717 m = 3;
718 ScalarMult(Pm, P, m);
720 NormalizeJac(Pm_norm, Pm);
722 TEST_EQUAL(Pm_norm[0], P3_ok[0]);
723 TEST_EQUAL(Pm_norm[1], P3_ok[1]);
724 TEST_EQUAL(Pm_norm[2], P3_ok[2]);
725 }
726 m.set(m_str);
727 ScalarMult(Pm, P, m);
729 NormalizeJac(Pm_norm, Pm);
731 TEST_EQUAL(Pm_norm[0], Pm_ok[0]);
732 TEST_EQUAL(Pm_norm[1], Pm_ok[1]);
733 TEST_EQUAL(Pm_norm[2], Pm_ok[2]);
734 }
735 {
736 const mie::Vuint& r = Param::r;
737 Fp2 Pz[3], Rz[3];
738 ScalarMult(Pz, P, r);
739 ScalarMult(Rz, R, r);
740 TEST_ASSERT(Pz[2].isZero());
741 TEST_ASSERT(Rz[2].isZero());
742 }
743}
744
746{
747 puts(__FUNCTION__);
748 Fp6 x, y, z;
749
750 for (int i = 0; i < 6; i++) {
751 x.get()[i] = i * i + 3;
752 }
753
754 y = x * Fp6(2);
755 x = x + x;
756 TEST_EQUAL(x, y);
757 x *= x;
758 Fp6::square(z, y);
759 TEST_EQUAL(x, z);
760#ifdef MIE_ATE_USE_GMP
761 mpz_class p6(p.toStr());
762 p6 *= p6;
763 p6 = p6 * p6 * p6;
764 y = mie::power(x, p6);
765 TEST_EQUAL(y, x);
766#endif
767 y = x; y.inverse();
768 x *= y;
769 TEST_EQUAL(x, Fp6(1));
770 {
771 std::ostringstream oss;
772 oss << y;
773 std::istringstream iss(oss.str());
774 iss >> x;
775 TEST_EQUAL(x, y);
776 }
777 {
778 Fp2 t(Fp("50"), Fp("25"));
779 Fp6 x(t, t, t);
780 Fp6 inv_x = x; inv_x.inverse();
781 x *= inv_x;
782 TEST_EQUAL(x, 1);
783 }
784}
785
787{
788 puts(__FUNCTION__);
789 const Fp6 a(
790 Fp2(Fp("12962627302162075398060982177087436574303347298537835668202414221253817262982"),
791 Fp("138260844306952217670025767932179019912073169546101859135312230638880521223")),
792 Fp2(Fp("15137160497776903814679214726809029070339754602997091488396727793679994724725"),
793 Fp("14585393257630973637130780517598702183004769121002667593088137712456098389147")),
794 Fp2(Fp("11656022636984400462137420855351583248422833051633377387451406154513829093114"),
795 Fp("14215712895255419029580702653008196543286207503420913686381671784091829605544")));
796 const Fp6Dbl ad(
797 "1593170926598915345387635677083748286590764833236455841205970156921632690659321696124459206976218892050264244158092130253877279907839544343324979280024170",
798 "1179973114230341892737360925692630156593789184269536881494768733457774943578761248088761269289336962320683158703377660715101868763181549734994595794867496",
799 "730145342724752832742804498354752537572280628992449438960103160339237082085998618512864763426475086477471191730731012602806937310004548457512536010563048",
800 "678118683224664762511490289199702755525092922001331540945747396044828904358828485331396580462479434002293484047506951365087686946333164073941237815303466",
801 "1696690105116639227371389908462484956149748096108668929604390112965542312011722226936838080163446882161586173219949938265621015171049147844994233756309066",
802 "67733454177668654989670636173597892971566229940879910979133487599488650994140729503900163935167021366038874739997773956034575689900205013416256257888322");
803 const Fp6 b(
804 Fp2(Fp("13266032064412835795130953448702250621050762510696965292045893361178860841079"),
805 Fp("2457069570102593370680131966272186058752442119075136300728910430721054975883")),
806 Fp2(Fp("2761323283613335519656714595170176518640718973086035562998271277678441691369"),
807 Fp("9282239544249417776161170354699989681427448957391036300962080470210029743316")),
808 Fp2(Fp("4725335130491002940371667092034595414883167034697622603206446595963780685950"),
809 Fp("2979604114551910299899042707207603351108418195709860388438523763202896562826")));
810 const Fp6Dbl bd(
811 "1475839844663843322570757741744775997036014731165662766646651170904291281982509370757030826186551260691254724613316384521255185802946693994015137182068602",
812 "1095370597739171250835471130891927869346414000670922062465412467538839645554804526075383358963227758462571697459677545719232104735169846503013457660892884",
813 "536047623091184724949149589675730696115091482580183754959193574690322789326610874996202176921473611369946983196347243075470791570525589963488361345383304",
814 "567095369910236561517167429427649270237483207499847850016456655352630986857858611181208043791533419484288551607360907558060915416405739300095090914524646",
815 "1628045414693061051387160519487414991569044842223778536119706327028677432835046952047761290724596114203937423373736927070986873116393928193270995863382370",
816 "113601886886856063908255915522830311745119439542360068010955258226612862901220453756679629604364967513217403777663391468064348420745734171787344796709574");
817 {
818 Fp6 t;
819 Fp6Dbl::mod(t, ad);
820 TEST_EQUAL(t, a);
821 Fp6Dbl::mod(t, bd);
822 TEST_EQUAL(t, b);
823 }
824 {
825 const Fp6 c = a + b;
826 const Fp6Dbl cd = ad + bd;
827 Fp6 t;
828 Fp6Dbl::mod(t, cd);
829 TEST_EQUAL(t, c);
830 }
831 {
832 const Fp6 c = -a;
833 const Fp6Dbl cd = -ad;
834 Fp6 t;
835 Fp6Dbl::mod(t, cd);
836 TEST_EQUAL(t, c);
837 }
838 {
839 const Fp6 c = a - b;
840 const Fp6Dbl cd = ad - bd;
841 Fp6 t;
842 Fp6Dbl::mod(t, cd);
843 TEST_EQUAL(t, c);
844 }
845 {
846 const Fp6 c = a * b;
847 Fp6Dbl cd;
848 Fp6Dbl::mul(cd, a, b);
849 Fp6 t;
850 Fp6Dbl::mod(t, cd);
851 TEST_EQUAL(t, c);
852 }
853}
854
856{
857 puts(__FUNCTION__);
858 TEST_EQUAL(sizeof(Fp12), sizeof(Fp) * 12);
859 Fp12 x, y;
860
861 for (int i = 0; i < 12; i++) {
862 x.get()[i] = i + 3;
863 }
864
865 y = x * Fp12(2);
866 x = x + x;
867 TEST_EQUAL(x, y);
868 x *= x;
869 Fp12::square(y);
870 TEST_EQUAL(x, y);
871
872 for (int i = 0; i < 12; i++) {
873 TEST_EQUAL(x.get()[i], y.get()[i]);
874 }
875
876#ifdef MIE_ATE_USE_GMP
877 mpz_class p12(p.toStr());
878 p12 *= p12;
879 p12 *= p12;
880 p12 = p12 * p12 * p12;
881 y = mie::power(x, p12);
882 TEST_EQUAL(y, x);
883#endif
884 y = x; y.inverse();
885 x *= y;
886 TEST_EQUAL(x, Fp12(1));
887 {
888 std::ostringstream oss;
889 oss << y;
890 std::istringstream iss(oss.str());
891 iss >> x;
892 TEST_EQUAL(x, y);
893 }
894}
895
897{
898 puts(__FUNCTION__);
899 /*
900 @note: Large exponent can not be used. Fix mie::Vuint.
901 */
902 std::string x_ok[] = {
903 "11740569797851521013113382206139723952380476000114006726254700017011388077491",
904 "11620869091920297152310912851876223249241005004927120638208161874259694264776",
905 "14319816424335732586640646744712820835577263950059423761702049659454143614010",
906 "8979195516353115834499099104570340580610233612320353839807503737299124538894",
907 "3889724809319970439398470559040488185853720726993744629936064081043226370937",
908 "8413606802647893249443694454915434425270568587052196647221488597304121045130",
909 "14595160807872212739731328980223779718645553907712177545489677083052892894971",
910 "14502774460357020920607411114414652729864247679483682272558415181562578814999",
911 "10561873726035110127922260604858986830025105803068865817827274807245635306750",
912 "7550390871387103641373102946170924993232803081589755675446081315707092125599",
913 "6140564006391685719531664678338338121143689549850528456971885232802932902162",
914 "15817781432103820015704945553128688539437475919918982282164580563407301207430",
915 };
916 Fp12 z;
917
918 for (int i = 0; i < 12; i++) {
919 z.get()[i] = Fp(x_ok[i]);
920 }
921
922 Fp12 x;
923
924 for (int i = 0; i < 12; i++) {
925 x.get()[i] = i + 3;
926 }
927
928 {
929 x.final_exp();
930 const mie::Vsint& zi = bn::Param::z;
931 mie::Vsint d_prime = (2 * zi) * (6 * zi * zi + 3 * zi + 1);
932 mie::Vuint d_abs;
933 mie::Vsint::absolute(d_abs, d_prime);
934 z = mie::power(z, d_abs);
935
936 if (d_prime.isNegative()) {
937 z.inverse();
938 }
939
940#if 0// QQQ old_exp
941 for (size_t i = 0; i < 12; i++) {
942 TEST_EQUAL(x.get()[i], z.get()[i]);
943 }
944#endif
945 }
946
947 {
948 Fp12 xt = mie::power(x, Param::r);
949 TEST_EQUAL(xt, Fp12(1));
950 Fp12 zt = mie::power(z, Param::r);
951 TEST_EQUAL(zt, Fp12(1));
952 }
953 CYBOZU_BENCH("final_exp", x.final_exp);
954}
955
956void test_pointDblLineEval(bool allBench)
957{
958 puts(__FUNCTION__);
959 Fp2 Q[] = { genQx(), genQy(), Fp2(Fp(1), Fp(0)) };
961 Fp P[3] = { genPx(), genPy(), Fp(1) };
963 Fp::neg(P[2], P[1]); // @note: For the assumption of pointDblLineEval
964 const Fp2 Q2_ok[] = { genQ2x(), genQ2y(), Fp2(Fp(1), Fp(0)) };
966 const Fp2 l00_ok(
967 Fp("1218653166067285584538203738497237160646510048316462546675922230477971988366"),
968 Fp("13444680966039708564821554178786623445404802733727517756140842427775282241991"));
969 const Fp2 l02_ok(
970 Fp("14669021325553969631665050171167465779242435633491920423094037145439504174348"),
971 Fp("771665946433473991711581179554051515057882422398978711857886722975787742693"));
972 const Fp2 l11_ok(
973 Fp("5083654211557558794221004641727153878275981283694826539168100383303202382274"),
974 Fp("6366225659089551329035322836142125548492356702076290974152251785589487583351"));
975 Fp2 Q2[] = { Q[0], Q[1], Q[2], };
976 Fp6 l;
977 Fp2& l00 = l.a_;
978 Fp2& l02 = l.c_;
979 Fp2& l11 = l.b_;
982 NormalizeHom(Q2, Q2);
984 TEST_EQUAL(Q2[0], Q2_ok[0]);
985 TEST_EQUAL(Q2[1], Q2_ok[1]);
986 TEST_EQUAL(Q2[2], Q2_ok[2]);
987 TEST_EQUAL(l00, l00_ok);
988 TEST_EQUAL(l02, l02_ok);
989 TEST_EQUAL(l11, l11_ok);
990 if (allBench) CYBOZU_BENCH("pointDblLineEval", Fp6::pointDblLineEval, l, Q2, P);
991}
992
993void test_pointAddLineEval(bool allBench)
994{
995 puts(__FUNCTION__);
996 Fp2 Q[] = { genQx(), genQy(), Fp2(Fp(1), Fp(0)) };
998 const Fp P[] = { genPx(), genPy(), Fp(1) };
1000 /*
1001 R = [m]Q
1002 where m = 8983814277390549953271767160356356855324831094607072139965475719941358715055
1003 */
1004 const Fp2 R[] = {
1005 Fp2(Fp("538403429049656139897565072692893539987872088302878297862474357627057534036"),
1006 Fp("9360831036830943010552886973925002873262696706980698595440552561606683082311")),
1007 Fp2(Fp("4602226271967538444445722209125398887820203020623789000433097490686198967692"),
1008 Fp("10027082368454222153717339435200994429592852929609246856551738735310444995281")),
1009 Fp2(Fp(1), Fp(0)),
1010 };
1012 /*
1013 RQ = R + Q
1014 */
1015 const Fp2 RQ_ok[] = {
1016 Fp2(Fp("14462635707798746157040779719592332683099281599171708385749388482446745043127"),
1017 Fp("5086071869627888235657453291665320777682769673183769388625923076659929904768")),
1018 Fp2(Fp("16071875127812105172451027231039463141848166104557696531987123967356838839389"),
1019 Fp("15279844061281116178616101791776992126994407482416317579299271742300496066177")),
1020 Fp2(Fp(1), Fp(0)),
1021 };
1023 const Fp2 l00_ok(Fp("10013952835140506910916067999531081753178250370402232448154990388205483309972"),
1024 Fp("4926609310552091279051699015655777273195016616696233579052261219295065454280"));
1025 const Fp2 l02_ok(Fp("9649996602326804522644231063703979927150591558884646473664259298382380662378"),
1026 Fp("13648226627125837280213504610543602176703831560553537083503603809375238781189"));
1027 const Fp2 l11_ok(Fp("10422676207793898611344309297861346302460414709615008088696917811505787281979"),
1028 Fp("7036010756497237943264447921878652888644981129674790435334341908753079422899"));
1029 Fp2 RQ[] = { R[0], R[1], R[2], };
1030 Fp6 l;
1031 Fp2& l00 = l.a_;
1032 Fp2& l02 = l.c_;
1033 Fp2& l11 = l.b_;
1034 Fp6::pointAddLineEval(l, RQ, Q, P);
1036 NormalizeHom(RQ, RQ);
1038 TEST_EQUAL(RQ[0], RQ_ok[0]);
1039 TEST_EQUAL(RQ[1], RQ_ok[1]);
1040 TEST_EQUAL(RQ[2], RQ_ok[2]);
1041 TEST_EQUAL(l00, l00_ok);
1042 TEST_EQUAL(l02, l02_ok);
1043 TEST_EQUAL(l11, l11_ok);
1044 if (allBench) CYBOZU_BENCH("pointAddLineEval", Fp6::pointAddLineEval, l, RQ, Q, P);
1045}
1046
1047void test_compression(bool allBench)
1048{
1049 puts(__FUNCTION__);
1050 Fp12 a;
1051
1052 for (int i = 0; i < 12; ++i) {
1053 a.get()[i] = i;
1054 }
1055
1056 Fp12 aa;
1057 a.mapToCyclo(aa);
1058 a = aa;
1059 Fp12 c;
1060 Compress b(c, a);
1061 TEST_EQUAL(intptr_t(&b.z_), intptr_t(&c));
1062 TEST_EQUAL(b.z_, c);
1063 TEST_EQUAL(b.g1_, c.getFp2()[4]);
1064 TEST_EQUAL(b.g2_, c.getFp2()[3]);
1065 TEST_EQUAL(b.g3_, c.getFp2()[2]);
1066 TEST_EQUAL(b.g4_, c.getFp2()[1]);
1067 TEST_EQUAL(b.g5_, c.getFp2()[5]);
1068 if (allBench) {
1069 CYBOZU_BENCH_C("decompress", 10000, b.decompress);
1070 TEST_EQUAL(a, c);
1071 }
1072}
1073
1074void test_compressed_square(bool allBench)
1075{
1076 puts(__FUNCTION__);
1077 Fp12 a;
1078
1079 for (int i = 0; i < 12; ++i) {
1080 a.get()[i] = i;
1081 }
1082
1083 Fp12 aa;
1084 a.mapToCyclo(aa);
1085 a = aa;
1086 Fp12 d;
1087 Compress b(d, a);
1088 a *= a;
1089 Fp12 d2;
1090 Compress c(d2, b);
1091 Compress::square_n(c, 1);
1092 c.decompress();
1093 TEST_EQUAL(a, d2);
1094 Compress::square_n(b, 1);
1095 b.decompress();
1096 TEST_EQUAL(a, d);
1097 if (allBench) CYBOZU_BENCH("Compress::square", Fp12::square, a);
1098}
1099
1101{
1102 puts(__FUNCTION__);
1103 Fp12 a;
1104
1105 for (int i = 0; i < 12; ++i) {
1106 a.get()[i] = i;
1107 }
1108
1109 Fp12 aa;
1110 a.mapToCyclo(aa);
1111 a = aa;
1112 Fp12 b;
1114 Fp12 c = mie::power(a, Param::z.get());
1115 TEST_EQUAL(b, c);
1116 if (allBench) CYBOZU_BENCH("Compress::fixed_power", Compress::fixed_power, b, a);
1117}
1118
1119void test_sqru(bool allBench)
1120{
1121 puts(__FUNCTION__);
1122 {
1123 Fp12 a;
1124
1125 for (int i = 0; i < 12; ++i) {
1126 a.get()[i] = i;
1127 }
1128 Fp12 aa;
1129 a.mapToCyclo(aa);
1130 a = aa;
1131 Fp12 b, c = a;
1132 b = a;
1133 b.sqru();
1134 Fp12::square(c);
1135 TEST_EQUAL(b, c);
1136 if (allBench) {
1137 CYBOZU_BENCH("Fp12::sqru ", a.sqru);
1138 CYBOZU_BENCH("Fp12::square", Fp12::square, a);
1139 CYBOZU_BENCH("Fp12::mul ", Fp12::mul, a, a, b);
1140 }
1141 }
1142}
1143
1144void test_FrobEndOnTwist_1(bool allBench)
1145{
1146 puts(__FUNCTION__);
1147 Fp2 Q[] = { genQx(), genQy() };
1149 const Fp2 Qp[] = {
1150 Fp2(Fp("2056759109515975861665426147192151608007308721500683629663464772885511939168"),
1151 Fp("10296094419291805247741898368672988774667071764149880389566192920518825046253")),
1152 Fp2(Fp("15318789889948026269195465641311637076887470214980886516517795245676250468201"),
1153 Fp("16086843419903922136591069704206201345656058171834106763866049911942744484945")),
1154 };
1156 FrobEndOnTwist_1(Q, Q);
1157 TEST_EQUAL(Q[0], Qp[0]);
1158 TEST_EQUAL(Q[1], Qp[1]);
1159
1160 for (size_t i = 1; i < 12; ++i) {
1161 FrobEndOnTwist_1(Q, Q);
1162 }
1163
1164 {
1165 Fp2 Q1[] = { genQx(), genQy() };
1166 TEST_EQUAL(Q[0], Q1[0]);
1167 TEST_EQUAL(Q[1], Q1[1]);
1168 }
1169
1170 if (allBench) CYBOZU_BENCH("FrobEndTwist_1", FrobEndOnTwist_1<Fp>, Q, Q);
1171}
1172
1173void test_FrobEndOnTwist_2(bool allBench)
1174{
1175 puts(__FUNCTION__);
1176 Fp2 Q[] = { genQx(), genQy() };
1178 const Fp2 Qp2_ok[] = {
1179 Fp2(Fp("10065458361706171050734313676266120070744817595308631072199963185069217686139"),
1180 Fp("3393658127113032111918147843333039169870532385628727893932735697426808572356")),
1181 Fp2(Fp("7370884157884891579172966401254345058493688321372957611668488286195364565842"),
1182 Fp("8345967414506607633587114472874805346889011972272589375097032499111066411209")),
1183 };
1185 FrobEndOnTwist_2(Q, Q);
1186 TEST_EQUAL(Q[0], Qp2_ok[0]);
1187 TEST_EQUAL(Q[1], Qp2_ok[1]);
1188
1189 for (size_t i = 1; i < 6; ++i) {
1190 FrobEndOnTwist_2(Q, Q);
1191 }
1192
1193 {
1194 Fp2 Q1[] = { genQx(), genQy() };
1195 TEST_EQUAL(Q[0], Q1[0]);
1196 TEST_EQUAL(Q[1], Q1[1]);
1197 }
1198 if (allBench) CYBOZU_BENCH("FrobEndTwist_2", FrobEndOnTwist_2<Fp>, Q, Q);
1199}
1200
1202{
1203 puts(__FUNCTION__);
1204 const Fp P[] = { genPx(), genPy() };
1206 const Fp P2[] = { genP2x(), genP2y() };
1208 const Fp2 Q[] = { genQx(), genQy() };
1210 const Fp2 Q2[] = { genQ2x(), genQ2y() };
1212 Fp12 e, e21, e22;
1213 opt_atePairing<Fp>(e, Q, P);
1214 opt_atePairing<Fp>(e21, Q, P2);
1215 opt_atePairing<Fp>(e22, Q2, P);
1216 TEST_EQUAL(e * e, e21);
1217 TEST_EQUAL(e * e, e22);
1218 for (int j = 0; j < 4; j++) {
1219 double begin = GetCurrTime();
1221 const int N = 10000;
1222 clk.begin();
1223
1224 for (int i = 0; i < N; i++) {
1225 opt_atePairing<Fp>(e, Q, P);
1226 }
1227
1228 clk.end();
1229 double end = GetCurrTime();
1230 printf("opt_ate:%.2fclk(N=%d) ", clk.getClock() / double(N), N);
1231 printf("%.3fmsec\n", (end - begin) * 1e3 / N);
1232 }
1233}
1234
1236{
1237 puts(__FUNCTION__);
1238 Fp x, y;
1239 TEST_EQUAL(sizeof(Fp), Fp::N * sizeof(mie::Unit));
1240 TEST_EQUAL((void*)&x, (void*)&x[0]);
1241 x = 123;
1242 y = 456;
1243 x += y;
1244 TEST_EQUAL(x, Fp("579"));
1245 x = 0x123;
1246 y = 0x456;
1247 x *= y;
1248 TEST_EQUAL(x, Fp("0x4EDC2"));
1249 x.set("123");
1250 y.set("456");
1251 x += y;
1252 TEST_EQUAL(x, Fp("579"));
1253 x -= Fp("580");
1254 TEST_EQUAL(x, Fp(Fp::getModulo() - 1));
1255 x.set("13235535167791909954945079826683319167288269422503395778717464766711290103089");
1256 y.set("12009422934659625156361067360716584218353200927749721008493193292779219981220");
1257 x *= x;
1258 TEST_EQUAL(x, y);
1259 {
1260 Fp x, y;
1262 x.set("3");
1263 z.set("3");
1264
1265 for (int i = 0; i < 100000; i++) {
1266 y = x;
1267 w = z;
1268 x *= x;
1269 z *= z;
1270 x -= y;
1271 z -= w;
1272
1273 if (x.toString() != z.toString()) {
1274 printf("err %d\n", i);
1275 std::cout << "x=" << y << std::endl;
1276 std::cout << "1=" << x << std::endl;
1277 std::cout << "2=" << z << std::endl;
1278 exit(1);
1279 }
1280 }
1281 }
1282 x = 3;
1283 y = power(x, Fp::getModulo() - 1);
1284 TEST_EQUAL(y, 1);
1285 y = x;
1286 y.inverse();
1287 x *= y;
1288 TEST_EQUAL(x, 1);
1289}
1290
1292{
1293 puts(__FUNCTION__);
1294 Fp x, y, z;
1295 const struct {
1296 const char* x;
1297 const char* y;
1298 const char* z;
1299 } tbl[] = {
1300 { "0", "0", "0" },
1301 { "12345", "6789", "19134" },
1302 { "0x2523648240000001ba344d80000000086121000000000013a700000000000012", "1", "0" },
1303 { "0x2523648240000001ba344d80000000086121000000000013a700000000000012", "2", "1" },
1304 { "0x2523648240000001ba344d80000000086121000000000013a700000000000012", "0x2000000000000000000000000000000000000000000000000000000000000000", "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" },
1305 { "0x2523648240000001ba344d80000000086121000000000013a700000000000012", "0x2523648240000001ba344d80000000086121000000000013a700000000000012", "0x2523648240000001ba344d80000000086121000000000013a700000000000011" },
1306 };
1307
1308 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1309 x.set(tbl[i].x);
1310 y.set(tbl[i].y);
1311 z.set(tbl[i].z);
1312 TEST_EQUAL(x + y, z);
1313 TEST_EQUAL(z - x, y);
1314 TEST_EQUAL(z - y, x);
1315 }
1316}
1317
1318struct MontgomeryTest {};
1319
1320void montgomery(mie::Vuint& z, const mie::Vuint& x, const mie::Vuint& y)
1321{
1322 mie::Vuint c = 0;
1323 const mie::Vuint p = Fp::getModulo();
1324 const size_t UnitLen = sizeof(mie::Unit) * 8;
1325 static mie::Unit pp;
1326 static bool isFirst = true;
1327
1328 if (isFirst) {
1330 ZN::setModulo(mie::Vuint(1) << UnitLen);
1331 ZN t(p);
1332 t = -t;
1333 t.inverse();
1334 pp = t[0];
1335 isFirst = false;
1336 }
1337
1338#if 1
1339 c = x * y;
1340 const size_t n = 256 / UnitLen;
1341
1342 for (size_t i = 0; i < n; i++) {
1343 mie::Unit u = c[0];
1344 mie::Unit q = u * pp;
1345 c += q * p;
1346 c >>= UnitLen;
1347 }
1348
1349#else
1350 const size_t n = 256 / UnitLen;
1351
1352 for (size_t i = 0; i < n; i++) {
1353 Unit t = y.size() > i ? y[i] : 0;
1354 c += x * t;
1355 Unit u = c[0];
1356 Unit q = u * pp;
1357 c += q * p;
1358 c >>= UnitLen;
1359 }
1360
1361#endif
1362
1363 if (c >= p) {
1364 c -= p;
1365 }
1366
1367 z = c;
1368}
1369
1371{
1372 puts(__FUNCTION__);
1373 FpDbl dummy;
1374 TEST_EQUAL(sizeof(dummy), FpDbl::SIZE);
1375 TEST_EQUAL(uintptr_t(&dummy), uintptr_t(&dummy[0]));
1376 {
1377 Fp x, y;
1378 mie::Vuint t;
1379 t = p - 1;
1380 Fp::setDirect(x, t);
1381 t = p - 2;
1382 Fp::setDirect(y, t);
1383 FpDbl zd;
1384 FpDbl::mul(zd, x, y);
1385 t = (p - 1) * (p - 2);
1386 mie::Vuint tzd = zd.getDirect();
1387 TEST_EQUAL(t, tzd);
1388 Fp z, zmod;
1389 z = x * y;
1390 FpDbl::mod(zmod, zd);
1391 TEST_EQUAL(z, zmod);
1392 }
1393 {
1394 const struct {
1395 const char* a;
1396 const char* b;
1397 } tbl[] = {
1398 {
1399 "0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
1400 "0x000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
1401 },
1402 {
1403 "0x2370fb049d410fbe4e761a9886e502417d023f40180000017e805370fb049d410fbe4e761a9886e50241370fb049d410fbe4e761a9886e502410000000003334",
1404 "0x2370fb049d410fbe4e761a9886e502417d01a9886e502417d023f40180000017e805370fb049d410fbe4e761a9886e50241370fb049d410fbe4e761a9886e502",
1405 },
1406 {
1407 "0x70fb049d410fbe4e761a9886e502417d023f40180000017e805370fb049d410fbe4e761a9886e50241370fb049d410fbe4e761a9886e502410000000003334",
1408 "0x70fb049d410fbe4e761a9886e502417d01a9886e502417d023f40180000017e805370fb049d410fbe4e761a9886e50241370fb049d410fbe4e761a9886e502",
1409 },
1410 };
1411 mie::Vuint pm = Fp::getModulo() * (mie::Vuint(1) << 256);
1412
1413 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1414 mie::Vuint x(tbl[i].a), y(tbl[i].b);
1415 FpDbl s, t;
1416 s.setDirect(x);
1417 t.setDirect(y);
1418 x = (x + y) % pm;
1419 s += t;
1420 y.set(s.const_ptr(), Fp::N * 2);
1421 TEST_EQUAL(x, y);
1422 }
1423 }
1424}
1425
1427{
1428 puts(__FUNCTION__);
1429 const char* as = "0x826db9eced02a46cccc83dd73d7ee9a1ac44da788daff6d90f91e0a49dfcd5e";
1430 const char* ads = "0x10e6616f9d658d62913a152516a1930d3b95eb1c4f69dd334c286bf2e322e34fab44d283e8ef4e6491c7fef40ca63362182fb3be3aad38785109f6b1a568c24";
1431 const char* bs = "0xbb4674a8b1fc189e5402353d6d991585e9a93a1fccb6bb48991033aa064661f";
1432 const char* bds = "0x18440289e040f84f0f8bb27b1f5607ad646bfeccbd737684bfdfeae964fd3bb4c5bb9f032044cb265788331de43a90e842b3b1e88eb9817676c8fe4934a8632";
1433 const Fp one(1);
1434 mie::Vuint ai(as), bi(bs);
1435 Fp a, b;
1436 Fp::setDirect(a, ai);
1437 Fp::setDirect(b, bi);
1438 const FpDbl ad(ads);
1439 const FpDbl bd(bds);
1440 {
1441 Fp t;
1442 FpDbl::mod(t, ad);
1443 TEST_EQUAL(t, a);
1444 FpDbl::mod(t, bd);
1445 TEST_EQUAL(t, b);
1446 }
1447 {
1448 const char* cs = "0x13db42e959efebd0b20ca7314ab17ff2795ee14985a66b221a8a2144ea44337d";
1449 const char* cds = "0x292a63f97da685b1a0c5c7a035f79abaa001e9e90cdd53b80c0856dc48201f04710071870934198ae9503211f0e0c44a5ae365a6c966b9eec7d2f4fada11256";
1450 FpDbl ad(ads);
1451 const FpDbl bd(bds);
1452 const FpDbl cd(cds);
1453 mie::Vuint ci(cs);
1454 Fp c, ct;
1455 Fp::setDirect(c, ci);
1456 FpDbl::mod(ct, cd);
1457 TEST_EQUAL(c, ct);
1458 FpDbl::add(ad, ad, bd);
1459 TEST_EQUAL(ad, cd);
1460 }
1461 {
1462 const char* a2s = "0x104db73d9da0548d999907bae7afdd3435889b4f11b5fedb21f23c1493bf9abc";
1463 const char* a2ds = "0x21ccc2df3acb1ac522742a4a2d43261a772bd6389ed3ba669850d7e5c645c69f5689a507d1de9cc9238ffde8194c66c4305f677c755a70f0a213ed634ad1848";
1464 FpDbl ad(ads);
1465 const FpDbl a2d(a2ds);
1466 mie::Vuint a2i(a2s);
1467 Fp a2, a2t;
1468 Fp::setDirect(a2, a2i);
1469 FpDbl::mod(a2t, a2d);
1470 TEST_EQUAL(a2, a2t);
1471 FpDbl::add(ad, ad, ad);
1472 TEST_EQUAL(ad, a2d);
1473 }
1474 {
1475 FpDbl ad, bd;
1476 const Fp c = a + b;
1477 Fp ct;
1478 FpDbl::mul(ad, a, one);
1479 FpDbl::mul(bd, b, one);
1480 FpDbl::add(ad, ad, bd);
1481 FpDbl::mod(ct, ad);
1482 TEST_EQUAL(ct, c);
1483 }
1484 {
1485 FpDbl ad;
1486 const Fp c = a + a;
1487 Fp ct;
1488 FpDbl::mul(ad, a, one);
1489 FpDbl::add(ad, ad, ad);
1490 FpDbl::mod(ct, ad);
1491 TEST_EQUAL(ct, c);
1492 }
1493 {
1494 const char* cds = "0x2414fe6b4629a72b9120ac2dae95e6d78d67a14e3b096240723d7940d1cdd1de054bb2d7c1710b19b6e38010bf359cc9de7d04c41c552c787aef6094e5a973dc";
1495 FpDbl ad(ads);
1496 const FpDbl cd(cds);
1497 FpDbl::neg(ad, ad);
1498 TEST_EQUAL(ad, cd);
1499 }
1500 {
1501 FpDbl ad;
1502 const Fp c = -a;
1503 Fp ct;
1504 FpDbl::mul(ad, a, one);
1505 FpDbl::neg(ad, ad);
1506 FpDbl::mod(ct, ad);
1507 TEST_EQUAL(ct, c);
1508 }
1509 {
1510 FpDbl ad, bd;
1511 const Fp c = a - b;
1512 Fp ct;
1513 FpDbl::mul(ad, a, one);
1514 FpDbl::mul(bd, b, one);
1515 FpDbl::sub(ad, ad, bd);
1516 FpDbl::mod(ct, ad);
1517 TEST_EQUAL(ct, c);
1518 }
1519}
1520
1522{
1523 puts(__FUNCTION__);
1524 const char* as = "121311891827543957596909773033357421921766710831251548159956972926334483720";
1525 const char* bs = "4250864531853689066995024032521947485438864668614304877798137152237875276659";
1526 const char* cs = "6130604890643875446660330430071165035373943332034046310134586930404838747383";
1527 const char* cds = "515680418261778013941729031428717927558491170998041032206579966438977948938767928415397290640890254719024071470552752738210640396059153581666931491480";
1528 {
1529 mie::Vuint ai(as), bi(bs), ci(cs);
1530 Fp x, y, z, zt;
1531 Fp::setDirect(x, ai);
1532 Fp::setDirect(y, bi);
1533 Fp::setDirect(z, ci);
1534 zt = x * y;
1535 FpDbl w, zd(cds);
1536 FpDbl::mul(w, x, y);
1537 TEST_EQUAL(w, zd);
1538 Fp s;
1539 FpDbl::mod(s, w);
1540 TEST_EQUAL(z, s);
1541 TEST_EQUAL(zt, s);
1542 }
1543}
1544
1546{
1547 puts(__FUNCTION__);
1548 Fp2Dbl dummy;
1549 TEST_EQUAL(sizeof(dummy), Fp2Dbl::SIZE);
1550 TEST_EQUAL(uintptr_t(&dummy), uintptr_t(&dummy.a_));
1551 const Fp2 a(
1552 Fp("11670776793662220163659381041821071042189526350599853354176183114948400476854"),
1553 Fp("16720058771622958239847090974706681762823587016948988460920422070188238301920"));
1554 const Fp2Dbl ad(
1555 "43365626183362451296144273927903491721178106337019849480533874426567558421999199112585229298328261724838400974530624189976754698034274243846379138263798",
1556 "146841205705169330240495767599698200797060877501089277217144673667296710106404940569619328012833781922979497600339156163032435697636816808188620084421142");
1557 {
1558 Fp2 at;
1559 Fp2Dbl::mod(at, ad);
1560 TEST_EQUAL(at, a);
1561 }
1562 {
1563 const Fp2 a(Fp("0"), Fp("1"));
1564 const Fp2 b(Fp("0"), Fp("1"));
1565 Fp2 c, ct;
1566 Fp2Dbl cd;
1567 c = a * b;
1568 Fp2Dbl::mulOpt2(cd, a, b);
1569 Fp2Dbl::mod(ct, cd);
1570 TEST_EQUAL(c, ct);
1571 }
1572 {
1573 const Fp2 b(Fp("123"), Fp("456"));
1574 Fp2 c, ct;
1575 Fp2Dbl cd;
1576 c = a * b;
1577 Fp2Dbl::mulOpt2(cd, a, b);
1578 Fp2Dbl::mod(ct, cd);
1579 TEST_EQUAL(c, ct);
1580 }
1581}
1582
1583void testFp2Dbl_add_sub(bool allBench)
1584{
1585 puts(__FUNCTION__);
1586 const Fp2 one(Fp("1"), Fp("0"));
1587 const Fp2 a(
1588 Fp("0x19cd6cf2a9dc668d011b54f13a92591457dcdd5b946cf92af95ca820077972b6"),
1589 Fp("0x24f737c85b07fa5103d2dfa5a44d0a9c2ee6138de25c709cdd2f526dab19eae0"));
1590 const Fp2Dbl ad(
1591 "0xd3f77def5c0d18d7f1449afb9c117dfeb51c1fe1208d056ad21c679c5ec71c4642b58a8c4f44ce7ed74f49cf92ae8428d5741cc65ee00bf090ec506c952af6",
1592 "0x2cdbeaf4c89f0e69e52a72dddfc13f8ca9ee571933484140d9e3c395bf9056b44719b54117e71bb62f41ed10ccec31240535f52ea74b4829c2a5fded0e52216");
1593 const Fp2 b(
1594 Fp("0x26dbd9018fa1dc1a7b555a80895ba00a4fbfb7ba8bcf7d3deb53452d65180c0"),
1595 Fp("0x20618bd9d595b08223a03e66294e8a4a10e688a696c0af9daca0faa041d884a7"));
1596 const Fp2Dbl bd(
1597 "0x2dfa943203451554f15ba5a92717a16a0f9a97dbec7d0dae70dc2ea57ff90d04e8c9f1ebfa99415ad41e9ac35c33b297b9fb4da61ff1b550dfc28c584e912d8",
1598 "0x23f0eb05bb2bc09bd2f9b1a71d6e2b94b28a4d1b6321dcfd44e8e72c1d7a992ad361a7b73aaf1cf5feca656ac0bddf20f549594ae1e65e9e567839d4f482176");
1599 {
1600 Fp2 at;
1601 Fp2Dbl::mod(at, ad);
1602 TEST_EQUAL(at, a);
1603 Fp2 bt;
1604 Fp2Dbl::mod(bt, bd);
1605 TEST_EQUAL(bt, b);
1606 }
1607 {
1608 mie::Vuint t0, t1;
1609 Fp2Dbl ad, bd, cd;
1610 t0 = 1; t1 = 2;
1611 ad.setDirect(t0, t1);
1612 t0 = 3; t1 = 4;
1613 bd.setDirect(t0, t1);
1614 t0 = 4; t1 = 6;
1615 cd.setDirect(t0, t1);
1616 Fp2Dbl td;
1617 Fp2Dbl::add(td, ad, bd);
1618 TEST_EQUAL(td, cd);
1619 }
1620 {
1621 const Fp2 c = a + b;
1622 const Fp2 cc(
1623 Fp("12769297135811847170252627178279277434270214741555565448692771341243685466998"),
1624 Fp("14568310576098881131032985368780468502614655635084870456076855826537822449524"));
1625 TEST_EQUAL(c, cc);
1626 Fp2 ct;
1627 Fp2Dbl adt(ad);
1628 Fp2Dbl::add(adt, adt, bd);
1629 Fp2Dbl::mod(ct, adt);
1630 TEST_EQUAL(ct, c);
1631 TEST_EQUAL(ct, cc);
1632 }
1633 {
1634 const Fp2 c = a - b;
1635 Fp2 ct;
1636 Fp2Dbl adt(ad);
1637 Fp2Dbl::sub(adt, adt, bd);
1638 Fp2Dbl::mod(ct, adt);
1639 TEST_EQUAL(ct, c);
1640 }
1641 {
1642 const Fp2 a(Fp("1"), Fp("0"));
1643 Fp2 c; Fp2::mul_xi(c, a);
1644 Fp2 ct;
1645 Fp2Dbl ad, cd;
1646 Fp2Dbl::mulOpt2(ad, a, one);
1647 Fp2Dbl::mul_xi(cd, ad);
1648 Fp2Dbl::mod(ct, cd);
1649 TEST_EQUAL(ct, c);
1650 }
1651 {
1652 Fp2 c; Fp2::mul_xi(c, a);
1653 Fp2 ct;
1654 Fp2Dbl ad, cd;
1655 Fp2Dbl::mulOpt2(ad, a, one);
1656 Fp2Dbl::mul_xi(cd, ad);
1657 Fp2Dbl::mod(ct, cd);
1658 TEST_EQUAL(ct, c);
1659 }
1660 if (allBench) {
1661 Fp2Dbl cd;
1662 CYBOZU_BENCH("Fp2Dbl::add ", Fp2Dbl::add, cd, ad, bd);
1663 CYBOZU_BENCH("Fp2Dbl::sub ", Fp2Dbl::sub, cd, ad, bd);
1664 CYBOZU_BENCH("Fp2Dbl::addNC ", Fp2Dbl::addNC, cd, ad, bd);
1665 CYBOZU_BENCH("Fp2Dbl::subNC ", Fp2Dbl::subNC, cd, ad, bd);
1666 CYBOZU_BENCH("Fp2Dbl::neg ", Fp2Dbl::neg, cd, ad);
1667 CYBOZU_BENCH("Fp2Dbl::mul_xi ", Fp2Dbl::mul_xi, cd, ad);
1668 CYBOZU_BENCH("Fp2Dbl::mulOpt1", Fp2Dbl::mulOpt1, cd, a, b);
1669 CYBOZU_BENCH("Fp2Dbl::mulOpt2", Fp2Dbl::mulOpt2, cd, a, b);
1670 CYBOZU_BENCH("Fp2Dbl::square ", Fp2Dbl::square, cd, a);
1671 Fp2 c;
1672 CYBOZU_BENCH("Fp2Dbl::mod ", Fp2Dbl::mod, c, ad);
1673 }
1674}
1675
1677{
1678 puts(__FUNCTION__);
1679 const Fp2 a(
1680 Fp("0x19cd6cf2a9dc668d011b54f13a92591457dcdd5b946cf92af95ca820077972b6"),
1681 Fp("0x24f737c85b07fa5103d2dfa5a44d0a9c2ee6138de25c709cdd2f526dab19eae0"));
1682 const Fp2Dbl ad(
1683 "0xd3f77def5c0d18d7f1449afb9c117dfeb51c1fe1208d056ad21c679c5ec71c4642b58a8c4f44ce7ed74f49cf92ae8428d5741cc65ee00bf090ec506c952af6",
1684 "0x2cdbeaf4c89f0e69e52a72dddfc13f8ca9ee571933484140d9e3c395bf9056b44719b54117e71bb62f41ed10ccec31240535f52ea74b4829c2a5fded0e52216");
1685 const Fp2 b(
1686 Fp("0x26dbd9018fa1dc1a7b555a80895ba00a4fbfb7ba8bcf7d3deb53452d65180c0"),
1687 Fp("0x20618bd9d595b08223a03e66294e8a4a10e688a696c0af9daca0faa041d884a7"));
1688 const Fp2Dbl bd(
1689 "0x2dfa943203451554f15ba5a92717a16a0f9a97dbec7d0dae70dc2ea57ff90d04e8c9f1ebfa99415ad41e9ac35c33b297b9fb4da61ff1b550dfc28c584e912d8",
1690 "0x23f0eb05bb2bc09bd2f9b1a71d6e2b94b28a4d1b6321dcfd44e8e72c1d7a992ad361a7b73aaf1cf5feca656ac0bddf20f549594ae1e65e9e567839d4f482176");
1691 {
1692 Fp2 at;
1693 Fp2Dbl::mod(at, ad);
1694 TEST_EQUAL(at, a);
1695 Fp2 bt;
1696 Fp2Dbl::mod(bt, bd);
1697 TEST_EQUAL(bt, b);
1698 }
1699 {
1700 const Fp2 c = a * b;
1701 Fp2Dbl cd;
1702 Fp2Dbl::mulOpt2(cd, a, b);
1703 Fp2 ct;
1704 Fp2Dbl::mod(ct, cd);
1705 TEST_EQUAL(ct, c);
1706 }
1707 {
1708 const Fp2 c = a * a;
1709 Fp2Dbl cd;
1710 Fp2Dbl::square(cd, a);
1711 Fp2 ct;
1712 Fp2Dbl::mod(ct, cd);
1713 TEST_EQUAL(ct, c);
1714 }
1715}
1716
1718{
1719 puts(__FUNCTION__);
1720 {
1721 const mie::Vuint p_ok("16798108731015832284940804142231733909889187121439069848933715426072753864723");
1722 const mie::Vuint& p = Fp::getModulo();
1723 const mie::Vuint& param_p = Param::p;
1724 TEST_EQUAL(p, p_ok);
1725 TEST_EQUAL(param_p, p_ok);
1726 }
1727 {
1728 const mie::Vuint r_ok("16798108731015832284940804142231733909759579603404752749028378864165570215949");
1729 const mie::Vuint& r = Param::r;
1730 TEST_EQUAL(r, r_ok);
1731 }
1732 {
1733 const Fp Z_ok("1807136345283977465813277102364620289631804529403213381639");
1734 Fp t = Z_ok * Z_ok + Z_ok + 1;
1735 TEST_ASSERT(t.isZero());
1736 t = Z_ok * Z_ok * Z_ok;
1737 TEST_EQUAL(t, 1);
1738 const Fp& Z = Param::Z;
1739 t = Z * Z + Z + 1;
1740 TEST_ASSERT(t.isZero());
1741 t = Z * Z * Z;
1742 TEST_EQUAL(t, 1);
1743 TEST_EQUAL(Z, Z_ok);
1744 }
1745 {
1746 const Fp2 W2p_ok(
1747 Fp(0),
1748 Fp("16798108731015832283133667796947756444075910019074449559301910896669540483083"));
1749 const Fp2& W2p = Param::W2p;
1750 TEST_EQUAL(W2p, W2p_ok);
1751 }
1752 {
1753 const Fp2 W3p_ok(
1754 Fp("16226349498735898878582721725794281106152147739300925444201528929117996286405"),
1755 Fp("16226349498735898878582721725794281106152147739300925444201528929117996286405"));
1756 const Fp2& W3p = Param::W3p;
1757 TEST_EQUAL(W3p, W3p_ok);
1758 }
1759 struct Fp2_str {
1760 const char* a;
1761 const char* b;
1762 };
1763 {
1764#ifdef BN_SUPPORT_SNARK
1765 const Fp2 (&gammar)[6] = Param::gammar;
1766#else
1767 const Fp2 (&gammar)[5] = Param::gammar;
1768#endif
1769 const Fp2_str gammar_str[] = {
1770 {
1771 "12310438583873020660552735091161044116898065562217439662059245424880585960937",
1772 "4487670147142811624388069051070689792991121559221630186874470001192167903786"
1773 },
1774 {
1775 "0",
1776 "16798108731015832283133667796947756444075910019074449559301910896669540483083"
1777 },
1778 {
1779 "16226349498735898878582721725794281106152147739300925444201528929117996286405",
1780 "16226349498735898878582721725794281106152147739300925444201528929117996286405"
1781 },
1782 {
1783 "16798108731015832283133667796947756444075910019074449559301910896669540483084",
1784 "0"
1785 },
1786 {
1787 "11738679351593087254194652674723591313161026180079295257327058927925828382619",
1788 "5059429379422745030746151467508142596728160941359774591606656498146925482104"
1789 },
1790 };
1791 Fp2 gammar_ok[5];
1792
1793 for (size_t i = 0; i < sizeof(gammar_ok) / sizeof(*gammar_ok); ++i) {
1794 gammar_ok[i].get()[0].set(gammar_str[i].a);
1795 gammar_ok[i].get()[1].set(gammar_str[i].b);
1796
1797 if (gammar[i] != gammar_ok[i]) {
1798 PUT(i);
1799 TEST_EQUAL(gammar[i], gammar_ok[i]);
1800 }
1801 }
1802 }
1803 {
1804 const Fp2 (&gammar2)[5] = Param::gammar2;
1805 const Fp2_str gammar2_str[] = {
1806 {
1807 "1807136345283977465813277102364620289631804529403213381640", "0"
1808 },
1809 {
1810 "1807136345283977465813277102364620289631804529403213381639", "0"
1811 },
1812 {
1813 "16798108731015832284940804142231733909889187121439069848933715426072753864722", "0"
1814 },
1815 {
1816 "16798108731015832283133667796947756444075910019074449559301910896669540483083", "0"
1817 },
1818 {
1819 "16798108731015832283133667796947756444075910019074449559301910896669540483084", "0"
1820 },
1821 };
1822 Fp2 gammar2_ok[5];
1823
1824 for (size_t i = 0; i < sizeof(gammar2_ok) / sizeof(*gammar2_ok); ++i) {
1825 gammar2_ok[i].get()[0].set(gammar2_str[i].a);
1826 gammar2_ok[i].get()[1].set(gammar2_str[i].b);
1827
1828 if (gammar2[i] != gammar2_ok[i]) {
1829 PUT(i);
1830 TEST_EQUAL(gammar2[i], gammar2_ok[i]);
1831 }
1832 }
1833 }
1834 {
1835 const Fp2 (&gammar3)[5] = Param::gammar3;
1836 const Fp2_str gammar3_str[] = {
1837 {
1838 "571759232279933406358082416437452803737039382138144404732186496954757578318",
1839 "16226349498735898878582721725794281106152147739300925444201528929117996286405"
1840 },
1841 { "0", "1" },
1842 {
1843 "571759232279933406358082416437452803737039382138144404732186496954757578318",
1844 "571759232279933406358082416437452803737039382138144404732186496954757578318"
1845 },
1846 {
1847 "16798108731015832284940804142231733909889187121439069848933715426072753864722", "0"
1848 },
1849 {
1850 "16226349498735898878582721725794281106152147739300925444201528929117996286405",
1851 "571759232279933406358082416437452803737039382138144404732186496954757578318"
1852 },
1853 };
1854 Fp2 gammar3_ok[5];
1855
1856 for (size_t i = 0; i < sizeof(gammar3_ok) / sizeof(*gammar3_ok); ++i) {
1857 gammar3_ok[i].get()[0].set(gammar3_str[i].a);
1858 gammar3_ok[i].get()[1].set(gammar3_str[i].b);
1859
1860 if (gammar3[i] != gammar3_ok[i]) {
1861 PUT(i);
1862 TEST_EQUAL(gammar3[i], gammar3_ok[i]);
1863 }
1864 }
1865 }
1866}
1867
1869{
1870 Fp2 g2[3] = {
1871 Fp2(
1872 Fp("12723517038133731887338407189719511622662176727675373276651903807414909099441"),
1873 Fp("4168783608814932154536427934509895782246573715297911553964171371032945126671")
1874 ),
1875 Fp2(
1876 Fp("13891744915211034074451795021214165905772212241412891944830863846330766296736"),
1877 Fp("7937318970632701341203597196594272556916396164729705624521405069090520231616")
1878 ),
1879 Fp2(Fp("1"), Fp("0"))
1880 };
1881 Fp g1[3] = {
1882 Fp("1674578968009266105367653690721407808692458796109485353026408377634195183292"),
1883 Fp("8299158460239932124995104248858950945965255982743525836869552923398581964065"),
1884 Fp("1")
1885 };
1886 Fp12 e;
1887 // opt_atePairingJac sample
1888 {
1889 Fp Zero[3];
1890 Zero[2] = 0;
1891 opt_atePairingJac<Fp>(e, g2, Zero);
1892 printf(" e(g2, 0) = 1 : %s\n", e == 1 ? "ok" : "ng");
1893 }
1894 {
1895 Fp2 Zero[3];
1896 Zero[2] = 0;
1897 opt_atePairingJac<Fp>(e, Zero, g1);
1898 printf(" e(0, g1) = 1 : %s\n", e == 1 ? "ok" : "ng");
1899 }
1900 {
1901 opt_atePairingJac<Fp>(e, g2, g1);
1902 // make unnormalized Jacobi
1903 {
1904 const int z = 17;
1905 g2[0] *= z * z;
1906 g2[1] *= z * z * z;
1907 g2[2] *= z;
1908 }
1909 {
1910 const int z = 13;
1911 g1[0] *= z * z;
1912 g1[1] *= z * z * z;
1913 g1[2] *= z;
1914 }
1915 Fp12 e1;
1916 opt_atePairingJac<Fp>(e1, g2, g1);
1917 printf(" e(g2, g1) : %s\n", e1 == e ? "ok" : "ng");
1918 }
1919 CYBOZU_BENCH("Fp12::mul", Fp12::mul, e, e, e);
1920}
1921
1923{
1924 const char* ads = "0x10e6616f9d658d62913a152516a1930d3b95eb1c4f69dd334c286bf2e322e34fab44d283e8ef4e6491c7fef40ca63362182fb3be3aad38785109f6b1a568c24";
1925 const char* bds = "0x18440289e040f84f0f8bb27b1f5607ad646bfeccbd737684bfdfeae964fd3bb4c5bb9f032044cb265788331de43a90e842b3b1e88eb9817676c8fe4934a8632";
1926 FpDbl ad(ads), bd(bds);
1927 CYBOZU_BENCH("FpDbl::add ", FpDbl::add, ad, ad, bd);
1928 CYBOZU_BENCH("FpDbl::sub ", FpDbl::sub, ad, ad, bd);
1929 CYBOZU_BENCH("FpDbl::addNC", FpDbl::addNC, ad, ad, bd);
1930 CYBOZU_BENCH("FpDbl::subNC", FpDbl::subNC, ad, ad, bd);
1931 CYBOZU_BENCH("FpDbl::neg ", FpDbl::neg, ad, ad);
1932}
1933
1935{
1936 Fp6 x, y;
1937
1938 for (int i = 0; i < 6; i++) {
1939 x.get()[i] = i * i + 3;
1940 }
1941 CYBOZU_BENCH("Fp6::add ", Fp6::add, x, x, y);
1942 CYBOZU_BENCH("Fp6::sub ", Fp6::sub, x, x, y);
1943 CYBOZU_BENCH("Fp6::mul ", Fp6::mul, x, x, y);
1944 CYBOZU_BENCH("Fp6::inverse", x.inverse);
1945}
1947{
1948 Fp12 x, y;
1949
1950 for (int i = 0; i < 12; i++) {
1951 x.get()[i] = i * i + 3;
1952 }
1953 CYBOZU_BENCH("Fp12::add ", Fp12::add, x, x, y);
1954 CYBOZU_BENCH("Fp12::sub ", Fp12::sub, x, x, y);
1955 CYBOZU_BENCH("Fp12::mul ", Fp12::mul, x, x, y);
1956 CYBOZU_BENCH("Fp12::inverse", x.inverse);
1957}
1959{
1960 const Fp P[] = { genPx(), genPy(), Fp(1) };
1961 const mie::Vuint m("9347746330740818252600716999005395295745642941583534686803606077666502");
1962 Fp Q[3];
1963 ECDouble(Q, P);
1964 CYBOZU_BENCH("G1:ECDouble ", ECDouble<Fp>, Q, Q);
1965 CYBOZU_BENCH("G1:ECAdd ", ECAdd<Fp>, Q, P, Q);
1966 CYBOZU_BENCH("G1:ScalarMult", (ScalarMult<Fp, mie::Vuint>), Q, P, m);
1967}
1969{
1970 const Fp2 P[] = { genQx(), genQy(), Fp2(Fp(1), Fp(0)) };
1971 const mie::Vuint m("9347746330740818252600716999005395295745642941583534686803606077666502");
1972 Fp2 Q[3];
1973 ECDouble(Q, P);
1974 CYBOZU_BENCH("G2:ECDouble ", ECDouble<Fp2>, Q, Q);
1975 CYBOZU_BENCH("G2:ECAdd ", ECAdd<Fp2>, Q, P, Q);
1976 CYBOZU_BENCH("G2:ScalarMult", (ScalarMult<Fp2, mie::Vuint>), Q, P, m);
1977}
1979{
1980 Fp6Dbl x("999111", "999222", "999333", "999444", "999555", "999666");
1981 Fp6Dbl y("1999111", "9919222", "9199333", "9919444", "9919555", "9919666");
1982 Fp6 a;
1983 for (int i = 0; i < 6; i++) {
1984 a.get()[i] = i * i + 3;
1985 }
1986 CYBOZU_BENCH("Fp6Dbl::add ", Fp6Dbl::add, x, x, x);
1987 CYBOZU_BENCH("Fp6Dbl::sub ", Fp6Dbl::sub, x, x, y);
1988 CYBOZU_BENCH("Fp6Dbl::mul ", Fp6Dbl::mul, x, a, a);
1989 CYBOZU_BENCH("Fp6Dbl::mod ", Fp6Dbl::mod, a, x);
1990 CYBOZU_BENCH("Fp6Dbl::addNC", Fp6Dbl::addNC, x, x, x);
1991 CYBOZU_BENCH("Fp6Dbl::subNC", Fp6Dbl::subNC, x, x, y);
1992 CYBOZU_BENCH("Fp6Dbl::neg ", Fp6Dbl::neg, x, x);
1993}
1995{
1996 benchFp();
1997 if (!benchAll) return;
1998 benchFp2();
1999 benchFpDbl();
2000 benchFp6();
2001 benchFp12();
2002 benchFp6Dbl();
2003 benchEcFp();
2004 benchEcFp2();
2005}
2006
2008{
2009 puts("squreRoot");
2010 Fp x = genPx();
2011 Fp yy = x * x * x + 2;
2012 Fp y;
2013 if (Fp::squareRoot(y, yy)) {
2014 if (y != genPy()) {
2015 y = -y;
2016 }
2017 TEST_EQUAL(y, genPy());
2018 } else {
2019 puts("no squareRoot");
2020 }
2021 for (int i = 1; i < 100; i++) {
2022 x = i;
2023 if (Fp::squareRoot(y, x)) {
2024 TEST_EQUAL(y * y, x);
2025 }
2026 }
2027}
2028int main(int argc, char* argv[]) try
2029{
2030 argc--, argv++;
2031 int mode = -1;
2032 bool useMulx = true;
2033 bool allBench = false;
2034
2035 while (argc > 0) {
2036 if (argc > 1 && strcmp(*argv, "-m") == 0) {
2037 argc--, argv++;
2038 mode = atoi(*argv);
2039 } else
2040 if (argc > 1 && strcmp(*argv, "-mulx") == 0) {
2041 argc--, argv++;
2042 useMulx = atoi(*argv) == 1;
2043 } else
2044 if (strcmp(*argv, "-all") == 0) {
2045 allBench = true;
2046 } else
2047 {
2048 printf("bn [-m (0|1)][-mulx (0|1)][-all]\n");
2049 return 1;
2050 }
2051 argc--, argv++;
2052 }
2053
2054 Param::init(mode, useMulx);
2056 testFp();
2058 testDbl();
2061 testFp2();
2062 testFp2Dbl();
2063 testFp2Dbl_add_sub(allBench);
2065 testFp6();
2066 testFp6Dbl();
2067 testFp12();
2068 test_pointDblLineEval(allBench);
2069 test_pointAddLineEval(allBench);
2070 test_compression(allBench);
2071 test_compressed_square(allBench);
2073 test_sqru(allBench);
2074 test_FrobEndOnTwist_1(allBench);
2075 test_FrobEndOnTwist_2(allBench);
2076 testECDouble();
2077 testECAdd();
2079 testECOperationsG1(allBench);
2084 testPairing();
2086 benchAll(allBench);
2087
2088 if (sclk.getCount()) printf("sclk:%.2fclk(%dtimes)\n", sclk.getClock() / double(sclk.getCount()), sclk.getCount());
2089
2090 printf("err=%d(test=%d)\n", s_errNum, s_testNum);
2091 return 0;
2092
2093} catch (std::exception& e) {
2094 fprintf(stderr, "std::exception %s\n", e.what());
2095 return 1;
2096}
2097
2098/*
2099 Local Variables:
2100 c-basic-offset: 4
2101 indent-tabs-mode: t
2102 tab-width: 4
2103 End:
2104*/
2105#endif
std::string one()
measure exec time of function
#define CYBOZU_BENCH(msg, func,...)
#define CYBOZU_BENCH_C(msg, _N, func,...)
void testFp()
Definition bn.cpp:1235
void testPairing()
Definition bn.cpp:1201
const Fp genPx()
Definition bn.cpp:118
void montgomery(mie::Vuint &z, const mie::Vuint &x, const mie::Vuint &y)
Definition bn.cpp:1320
void testPairingJac()
Definition bn.cpp:1868
void benchFp6()
Definition bn.cpp:1934
void testECOperationsG2()
Definition bn.cpp:602
void testFp6Dbl()
Definition bn.cpp:786
void test_final_exp()
Definition bn.cpp:896
#define NUM_OF_ARRAY(x)
Definition bn.cpp:14
void testParameters()
Definition bn.cpp:1717
void testFp2()
Definition bn.cpp:425
void testFp2Dbl_add_sub(bool allBench)
Definition bn.cpp:1583
void benchFp2()
Definition bn.cpp:45
void test_compressed_fixed_power(bool allBench)
Definition bn.cpp:1100
void testDbl()
Definition bn.cpp:1370
void benchFp6Dbl()
Definition bn.cpp:1978
void test_pointAddLineEval(bool allBench)
Definition bn.cpp:993
void test_pointDblLineEval(bool allBench)
Definition bn.cpp:956
void testECDouble()
Definition bn.cpp:159
void benchAll(bool benchAll)
Definition bn.cpp:1994
void test_FrobEndOnTwist_2(bool allBench)
Definition bn.cpp:1173
void testFp2Dbl()
Definition bn.cpp:1545
const Fp2 & genQy()
Definition bn.cpp:570
void testDbl_add_sub()
Definition bn.cpp:1426
#define TEST_EQUAL(x, y)
Definition bn.cpp:22
void benchEcFp()
Definition bn.cpp:1958
void testFpDbl_mul_mod()
Definition bn.cpp:1521
const Fp genP2y()
Definition bn.cpp:143
#define TEST_ASSERT(x)
Definition bn.cpp:23
void testECAdd()
Definition bn.cpp:206
const Fp2 & genQ2x()
Definition bn.cpp:582
const mie::Vuint & p
Definition bn.cpp:27
void test_FrobEndOnTwist_1(bool allBench)
Definition bn.cpp:1144
void test_compression(bool allBench)
Definition bn.cpp:1047
void benchFp()
Definition bn.cpp:30
void test_sqru(bool allBench)
Definition bn.cpp:1119
const Fp2 & genQx()
Definition bn.cpp:559
const Fp genP2x()
Definition bn.cpp:135
void testECOperationsG1(bool allBench)
Definition bn.cpp:304
void testFp12()
Definition bn.cpp:855
void test_multi(const bn::CurveParam &cp)
Definition bn.cpp:65
const Fp2 & genQ2y()
Definition bn.cpp:593
void benchFp12()
Definition bn.cpp:1946
void testFp6()
Definition bn.cpp:745
void testFp_add_sub()
Definition bn.cpp:1291
const Fp genPy()
Definition bn.cpp:126
void SetJacobi(F out[3], const F *in)
Definition bn.cpp:150
void test_compressed_square(bool allBench)
Definition bn.cpp:1074
void benchFpDbl()
Definition bn.cpp:1922
void testFp2Dbl_mul_mod()
Definition bn.cpp:1676
const mie::Vuint & r
Definition bn.cpp:28
void benchEcFp2()
Definition bn.cpp:1968
void testSquareRoot()
Definition bn.cpp:2007
Xbyak::util::Clock sclk
BN parameter.
void set(const std::string &str)
Definition bn254_if.hpp:105
void set(int x)
Definition bn254_if.hpp:68
std::string toString() const
Definition bn254_if.hpp:73
int getCount() const
Definition xbyak_util.h:400
uint64 getClock() const
Definition xbyak_util.h:401
static void(* add)(Fp &out, const Fp &x, const Fp &y)
Definition zm2.h:83
static void(* mul)(Fp &out, const Fp &x, const Fp &y)
Definition zm2.h:93
static void inv(Fp &out, const Fp &x)
Definition zm2.h:165
static const mie::Vuint & getModulo()
Definition zm2.h:262
@ N
Definition zm2.h:26
static void divBy2(Fp &z, const Fp &x)
Definition zm2.h:216
static void(* neg)(Fp &out, const Fp &x)
Definition zm2.h:92
static void divBy4(Fp &z, const Fp &x)
Definition zm2.h:223
static void(* sub)(Fp &out, const Fp &x, const Fp &y)
Definition zm2.h:91
static MIE_FORCE_INLINE void setDirect(Fp &out, const T &in)
Definition zm2.h:238
static bool squareRoot(Fp &y, const Fp &x)
Definition zm2.h:297
static void absolute(V &out, const VsintT &in)
Definition zm.h:1144
bool isNegative() const
Definition zm.h:1032
void set(const ZmZ &x)
Definition zm.h:1197
std::string toString(int base=10) const
Definition zm.h:1324
const struct Ptn tbl[]
#define P
Definition dtoa.c:437
char ** argv
#define PUT(x)
Definition java_api.cpp:8
LOGGING_API void printf(Category category, const char *format,...)
Definition Logging.cpp:30
void millerLoop(Fp12 &f, const std::vector< Fp6 > &Qcoeff, const Fp precP[2])
Definition bn.h:3060
void precomputeG2(std::vector< Fp6 > &coeff, Fp2 Q[3], const Fp2 inQ[3])
Definition bn.h:2997
void ECDouble(FF *out, const FF *in)
Definition bn.h:2497
bool isOnTwistECJac3(const Fp2T< Fp > *P)
Definition bn.h:2409
bool isOnECHom3(const Fp *P)
Definition bn.h:2392
void copy(FF *out, const FF *in)
Definition bn.h:2350
void FrobEndOnTwist_2(Fp2T< Fp > *Q, const Fp2T< Fp > *P)
Definition bn.h:2679
void ScalarMult(FF *out, const FF *in, const INT &m)
Definition bn.h:2590
bool isOnTwistECHom3(const Fp2T< Fp > *P)
Definition bn.h:2439
void NormalizeJac(FF *out, const FF *in)
Definition bn.h:2451
void NormalizeHom(FF *out, const FF *in)
Definition bn.h:2475
bool isOnTwistECHom2(const Fp2T< Fp > *P)
Definition bn.h:2427
void ECAdd(FF *out, const FF *a, const FF *b)
Definition bn.h:2526
bool isOnECJac3(const Fp *P)
Definition bn.h:2361
bool isOnECHom2(const Fp *P)
Definition bn.h:2380
void FrobEndOnTwist_1(Fp2T< Fp > *Q, const Fp2T< Fp > *P)
Definition bn.h:2650
Definition bn.h:56
Fp6T< Fp2 > Fp6
Definition bn.h:2957
void opt_atePairingJac(Fp12T< Fp6T< Fp2T< Fp > > > &f, const Fp2T< Fp > _Q[3], const Fp _P[3])
Definition bn.h:2795
mie::Fp Fp
Definition bn.h:2952
const CurveParam CurveFp254BNb
Definition bn.h:84
Fp12T< Fp6 > Fp12
Definition bn.h:2959
void opt_atePairing(Fp12T< Fp6T< Fp2T< Fp > > > &f, const Fp2T< Fp > Q[2], const Fp P[2])
Definition bn.h:2720
Fp2T< Fp > Fp2
Definition bn.h:2954
uint32_t Unit
Definition zm.h:66
T power(const T &x, const S &y)
Definition zm.h:1389
VuintT< local::FixedBuffer< mie::Unit, MIE_ZM_VUINT_BIT_LEN > > Vuint
Definition zm.h:1161
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
const int N
Definition quantize.cpp:54
_W64 unsigned int uintptr_t
Definition stdint.h:165
_W64 signed int intptr_t
Definition stdint.h:164
struct Point::G2 g2
struct Point::G1 g1
Fp2 & g2_
Definition bn.h:2139
static void fixed_power(Fp12 &z, const Fp12 &x)
Definition bn.h:2310
static void(* square_n)(CompressT &z, int n)
Definition bn.h:2338
Fp12 & z_
Definition bn.h:2137
Fp2 & g5_
Definition bn.h:2142
Fp2 & g1_
Definition bn.h:2138
Fp2 & g4_
Definition bn.h:2141
void decompress()
Definition bn.h:2220
Fp2 & g3_
Definition bn.h:2140
int b
Definition bn.h:67
static void(* mul)(Fp12T &z, const Fp12T &x, const Fp12T &y)
Definition bn.h:1449
static void add(Fp12T &z, const Fp12T &x, const Fp12T &y)
Definition bn.h:1432
static void sub(Fp12T &z, const Fp12T &x, const Fp12T &y)
Definition bn.h:1437
static void(* square)(Fp12T &z)
Definition bn.h:1475
static bin_op * sub
Definition bn.h:654
static void(* mod)(Fp2T &z, const Dbl &x)
Definition bn.h:660
static bin_op * subNC
Definition bn.h:655
static bin_op * addNC
Definition bn.h:652
static uni_op * mul_xi
Definition bn.h:662
static bin_op * add
Definition bn.h:651
void setDirect(const mie::Vuint &a, const mie::Vuint &b)
Definition bn.h:620
static void(* square)(Dbl &z, const Fp2T &x)
Definition bn.h:659
static void(* mulOpt1)(Dbl &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:657
static void(* mulOpt2)(Dbl &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:658
static uni_op * neg
Definition bn.h:653
static void neg(Fp2T &z, const Fp2T &x)
Definition bn.h:400
static void(* square)(Fp2T &z, const Fp2T &x)
Definition bn.h:373
static void mul_Fp_1(Fp2T &z, const Fp &y_b)
Definition bn.h:575
static void(* addNC)(Fp2T &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:369
static void(* divBy2)(Fp2T &z, const Fp2T &x)
Definition bn.h:376
static void divBy4(Fp2T &z, const Fp2T &x)
Definition bn.h:434
static void(* mul_Fp_0)(Fp2T &z, const Fp2T &x, const Fp &b)
Definition bn.h:375
static void(* sub)(Fp2T &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:370
static void(* mul_xi)(Fp2T &z, const Fp2T &x)
Definition bn.h:374
static void(* add)(Fp2T &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:368
static void(* mul)(Fp2T &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:372
static void sub(Dbl &z, const Dbl &x, const Dbl &y)
Definition bn.h:1249
static void(* mul)(Dbl &, const Fp6T &x, const Fp6T &y)
Definition bn.h:1262
static void subNC(Dbl &z, const Dbl &x, const Dbl &y)
Definition bn.h:1256
static void neg(Dbl &z, const Dbl &x)
Definition bn.h:1242
static void mod(Fp6T &z, const Dbl &x)
Definition bn.h:1328
static void addNC(Dbl &z, const Dbl &x, const Dbl &y)
Definition bn.h:1235
static void add(Dbl &z, const Dbl &x, const Dbl &y)
Definition bn.h:1228
Definition bn.h:837
static void square(Fp6T &z, const Fp6T &x)
Definition bn.h:914
static void pointAddLineEval(Fp6T &l, Fp2 *R, const Fp2 *Q, const Fp *P)
Definition bn.h:1143
static void(* pointDblLineEval)(Fp6T &l, Fp2 *R, const Fp *P)
Definition bn.h:986
Fp * get()
Definition bn.h:869
static void(* sub)(Fp6T &z, const Fp6T &x, const Fp6T &y)
Definition bn.h:983
static void(* add)(Fp6T &z, const Fp6T &x, const Fp6T &y)
Definition bn.h:982
void inverse()
Definition bn.h:937
static void(* mul)(Fp6T &z, const Fp6T &x, const Fp6T &y)
Definition bn.h:984
static Fp Z
Definition bn.h:186
static mie::Vuint p
Definition bn.h:182
static mie::Vuint r
Definition bn.h:183
static Fp2 W2p
Definition bn.h:187
static Fp2 W3p
Definition bn.h:188
static Fp2 gammar[5]
Definition bn.h:189
static Fp2 gammar2[5]
Definition bn.h:190
static Fp2 gammar3[5]
Definition bn.h:191
static mie::Vsint z
Definition bn.h:181
static void init(const CurveParam &cp, int mode=-1, bool useMulx=true)
Definition bn.h:206
static Fp half
Definition bn.h:196
static MIE_FORCE_INLINE void setDirect(Dbl &out, const mie::Vuint &in)
Definition zm2.h:312
static uni_op * neg
Definition zm2.h:374
static void(* mod)(Fp &z, const Dbl &x)
Definition zm2.h:398
static bin_op * sub
Definition zm2.h:379
mie::Vuint getDirect() const
Definition zm2.h:339
static bin_op * subNC
Definition zm2.h:380
static bin_op * addNC
Definition zm2.h:372
static void(* mul)(Dbl &z, const Fp &x, const Fp &y)
Definition zm2.h:393
static bin_op * add
Definition zm2.h:371
void set(T x)
Definition zm.h:341
std::string toStr(int base=10) const
Definition zm.h:514
#define R
const Point & selectPoint(const bn::CurveParam &cp)
void bt(const Operand &op, const Reg &reg)
CK_ULONG d
char * s
uint16_t j
int l