Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
bn.h
Go to the documentation of this file.
1#pragma once
9#include <stdexcept>
10#include <vector>
11
12#include "zm2.h"
13
14//#define BN_SUPPORT_SNARK
15
16#ifdef MIE_ATE_USE_GMP
17#include <gmpxx.h>
18
19namespace mie {
20
21inline size_t M_bitLen(const mpz_class& x)
22{
23 return mpz_sizeinbase(x.get_mpz_t(), 2);
24}
25inline size_t M_blockSize(const mpz_class& x)
26{
27 return x.get_mpz_t()->_mp_size;
28}
29inline mp_limb_t M_block(const mpz_class& x, size_t i)
30{
31 return x.get_mpz_t()->_mp_d[i];
32}
33inline uint32_t M_low32bit(const mpz_class& x)
34{
35 return (uint32_t)M_block(x, 0);
36}
37
38namespace util {
39template<>
40struct IntTag<mpz_class> {
41 typedef mp_limb_t value_type;
42 static inline value_type getBlock(const mpz_class& x, size_t i)
43 {
44 return M_block(x, i);
45 }
46 static inline size_t getBlockSize(const mpz_class& x)
47 {
48 return M_blockSize(x);
49 }
50};
51} } // mie::util
52#endif
53
54extern uint64_t debug_buf[128]; // for debug
55
56namespace bn {
57
58struct CurveParam {
59 /*
60 y^2 = x^3 + b
61 u^2 = -1
62 xi = xi_a + xi_b u
63 v^3 = xi
64 w^2 = v
65 */
67 int b; // Y^2 + X^3 + b
68 int xi_a;
69 int xi_b; // xi = xi_a + xi_b u
70 bool operator==(const CurveParam& rhs) const { return z == rhs.z && b == rhs.b && xi_a == rhs.xi_a && xi_b == rhs.xi_b; }
71 bool operator!=(const CurveParam& rhs) const { return !operator==(rhs); }
72};
73
74/*
75 the current version supports only the following parameters
76*/
77#ifdef BN_SUPPORT_SNARK
78const CurveParam CurveSNARK1 = { 4965661367192848881, 3, 9, 1 };
79
80// b/xi = 82 / (9 + u) = 9 - u
81const CurveParam CurveSNARK2 = { 4965661367192848881, 82, 9, 1 };
82#else
83// b/xi = 2 / (1 - u) = 1 + u
84const CurveParam CurveFp254BNb = { -((1LL << 62) + (1LL << 55) + (1LL << 0)), 2, 1, 1 };
85#endif
86
87namespace util {
88
89template<class T>
90void put(const T& x, size_t len)
91{
92 for (size_t i = 0; i < len; i++) {
93 printf("% 2d,", x[i]);
94 }
95 printf("\n");
96}
97template<class T>
98void put(const T& x)
99{
100 put(x, x.size());
101}
102template<class Vec>
103void convertToBinary(Vec& v, const mie::Vuint& x)
104{
105 const size_t len = x.bitLen();
106 v.clear();
107 for (size_t i = 0; i < len; i++) {
108 v.push_back(x.testBit(len - 1 - i) ? 1 : 0);
109 }
110}
111template<class Vec>
112size_t getContinuousVal(const Vec& v, size_t pos, int val)
113{
114 while (pos >= 2) {
115 if (v[pos] != val) break;
116 pos--;
117 }
118 return pos;
119}
120template<class Vec>
121void convertToNAF(Vec& v, const Vec& in)
122{
123 v = in;
124 size_t pos = v.size() - 1;
125 for (;;) {
126 size_t p = getContinuousVal(v, pos, 0);
127 if (p == 1) return;
128 assert(v[p] == 1);
129 size_t q = getContinuousVal(v, p, 1);
130 if (q == 1) return;
131 assert(v[q] == 0);
132 if (p - q <= 1) {
133 pos = p - 1;
134 continue;
135 }
136 v[q] = 1;
137 for (size_t i = q + 1; i < p; i++) {
138 v[i] = 0;
139 }
140 v[p] = -1;
141 pos = q;
142 }
143}
144template<class Vec>
145size_t getNumOfNonZeroElement(const Vec& v)
146{
147 size_t w = 0;
148 for (size_t i = 0; i < v.size(); i++) {
149 if (v[i]) w++;
150 }
151 return w;
152}
153
154/*
155 compute a repl of x which has smaller Hamming weights.
156 return true if naf is selected
157*/
158template<class Vec>
159bool getGoodRepl(Vec& v, const mie::Vuint& x)
160{
161 Vec bin;
162 util::convertToBinary(bin, x);
163 Vec naf;
164 util::convertToNAF(naf, bin);
165 const size_t binW = util::getNumOfNonZeroElement(bin);
166 const size_t nafW = util::getNumOfNonZeroElement(naf);
167 if (nafW < binW) {
168 v.swap(naf);
169 return true;
170 } else {
171 v.swap(bin);
172 return false;
173 }
174}
175
176} // bn::util
177
178template<class Fp2>
179struct ParamT {
180 typedef typename Fp2::Fp Fp;
181 static mie::Vsint z;
182 static mie::Vuint p;
183 static mie::Vuint r;
184 static mie::Vuint t; /* trace of Frobenius */
185 static mie::Vsint largest_c; /* 6z + 2, the largest coefficient of short vector */
186 static Fp Z;
187 static Fp2 W2p;
188 static Fp2 W3p;
189 static Fp2 gammar[5];
190 static Fp2 gammar2[5];
191 static Fp2 gammar3[5];
192 static Fp i0; // 0
193 static Fp i1; // 1
194 static int b;
195 static Fp2 b_invxi; // b/xi of twist E' : Y^2 = X^3 + b/xi
196 static Fp half;
197
198 // Loop parameter for the Miller loop part of opt. ate pairing.
199 typedef std::vector<signed char> SignVec;
201 static bool useNAF;
202#ifdef BN_SUPPORT_SNARK
203 static SignVec zReplTbl;
204#endif
205
206 static inline void init(const CurveParam& cp, int mode = -1, bool useMulx = true)
207 {
208#ifdef BN_SUPPORT_SNARK
209 bool supported = cp == CurveSNARK1 || cp == CurveSNARK2;
210#else
211 bool supported = cp == CurveFp254BNb;
212#endif
213 if (!supported) {
214 fprintf(stderr, "not supported parameter\n");
215 exit(1);
216 }
217 mie::zmInit();
218 const int64_t org_z = cp.z; // NOTE: hard-coded Fp12::pow_neg_t too.
219 const int pCoff[] = { 1, 6, 24, 36, 36 };
220 const int rCoff[] = { 1, 6, 18, 36, 36 };
221 const int tCoff[] = { 1, 0, 6, 0, 0 };
222 z.set(org_z);
223 eval(p, z, pCoff);
224 eval(r, z, rCoff);
225 eval(t, z, tCoff);
226 largest_c = 6 * z + 2;
227 b = cp.b; // set b before calling Fp::setModulo
228 Fp::setModulo(p, mode, useMulx);
229 half = Fp(1) / Fp(2);
230 /*
231 b_invxi = b / xi
232 */
233 Fp2 xi(cp.xi_a, cp.xi_b);
234 b_invxi = xi;
236 b_invxi *= Fp2(b, 0);
237 gammar[0] = mie::power(xi, (p - 1) / 6);
238
239 for (size_t i = 1; i < sizeof(gammar) / sizeof(*gammar); ++i) {
240 gammar[i] = gammar[i - 1] * gammar[0];
241 }
242
243 for (size_t i = 0; i < sizeof(gammar2) / sizeof(*gammar2); ++i) {
244 gammar2[i] = Fp2(gammar[i].a_, -gammar[i].b_) * gammar[i];
245 }
246
247 for (size_t i = 0; i < sizeof(gammar2) / sizeof(*gammar2); ++i) {
248 gammar3[i] = gammar[i] * gammar2[i];
249 }
250
251 W2p = mie::power(xi, (p - 1) / 3);
252 W3p = mie::power(xi, (p - 1) / 2);
253 Fp2 temp = mie::power(xi, (p * p - 1) / 6);
254 assert(temp.b_.isZero());
255 Fp::square(Z, -temp.a_);
256 i0 = 0;
257 i1 = 1;
258
260#ifdef BN_SUPPORT_SNARK
261 util::getGoodRepl(zReplTbl, z.abs());
262#endif
263 }
264 static inline void init(int mode = -1, bool useMulx = true)
265 {
266#ifdef BN_SUPPORT_SNARK
267 init(CurveSNARK1, mode, useMulx);
268#else
269 init(CurveFp254BNb, mode, useMulx);
270#endif
271 }
272
273 // y = sum_{i=0}^4 c_i x^i
274 // @todo Support signed integer substitution.
275 template<class T, class U>
276 static void eval(T& y, const U& x, const int* c) {
277 U tmp = (((c[4] * x + c[3]) * x + c[2]) * x + c[1]) * x + c[0];
278 y = tmp.get();
279 }
280};
281
282template<class Fp2>
284template<class Fp2>
286template<class Fp2>
288template<class Fp2>
290template<class Fp2>
292
293template<class Fp2>
294typename Fp2::Fp ParamT<Fp2>::Z;
295template<class Fp2>
296typename Fp2::Fp ParamT<Fp2>::i0;
297template<class Fp2>
298typename Fp2::Fp ParamT<Fp2>::i1;
299template<class Fp2>
301template<class Fp2>
303
304template<class Fp2>
306
307template<class Fp2>
309template<class Fp2>
311
312template<class Fp2>
314template<class Fp2>
316template<class Fp2>
318
319template<class Fp2>
321template<class Fp2>
323
324#ifdef BN_SUPPORT_SNARK
325template<class Fp2>
326typename ParamT<Fp2>::SignVec ParamT<Fp2>::zReplTbl;
327#endif
328
329/*
330 mul_gamma(z, x) + z += y;
331*/
332template<class F, class G>
333void mul_gamma_add(F& z, const F& x, const F& y)
334{
335 G::mul_xi(z.a_, x.c_);
336 z.a_ += y.a_;
337 G::add(z.b_, x.a_, y.b_);
338 G::add(z.c_, x.b_, y.c_);
339}
340
341/*
342 beta = -1
343 Fp2 = F[u] / (u^2 + 1)
344 x = a_ + b_ u
345*/
346template<class T>
347struct Fp2T : public mie::local::addsubmul<Fp2T<T>
348 , mie::local::hasNegative<Fp2T<T> > > {
349 typedef T Fp;
351 Fp2T() { }
352 Fp2T(int x)
353 : a_(x)
354 , b_(0)
355 {
356 }
357 Fp2T(const Fp& a, const Fp& b)
358 : a_(a)
359 , b_(b)
360 {
361 }
362 Fp* get() { return &a_; }
363 const Fp* get() const { return &a_; }
364 bool isZero() const
365 {
366 return a_.isZero() && b_.isZero();
367 }
368 static void (*add)(Fp2T& z, const Fp2T& x, const Fp2T& y);
369 static void (*addNC)(Fp2T& z, const Fp2T& x, const Fp2T& y);
370 static void (*sub)(Fp2T& z, const Fp2T& x, const Fp2T& y);
371 static void (*subNC)(Fp2T& z, const Fp2T& x, const Fp2T& y);
372 static void (*mul)(Fp2T& z, const Fp2T& x, const Fp2T& y);
373 static void (*square)(Fp2T& z, const Fp2T& x);
374 static void (*mul_xi)(Fp2T& z, const Fp2T& x);
375 static void (*mul_Fp_0)(Fp2T& z, const Fp2T& x, const Fp& b);
376 static void (*divBy2)(Fp2T& z, const Fp2T& x);
377
378 static inline void addC(Fp2T& z, const Fp2T& x, const Fp2T& y)
379 {
380 Fp::add(z.a_, x.a_, y.a_);
381 Fp::add(z.b_, x.b_, y.b_);
382 }
383 static inline void addNC_C(Fp2T& z, const Fp2T& x, const Fp2T& y)
384 {
385 Fp::addNC(z.a_, x.a_, y.a_);
386 Fp::addNC(z.b_, x.b_, y.b_);
387 }
388
389 static inline void subNC_C(Fp2T& z, const Fp2T& x, const Fp2T& y)
390 {
391 Fp::subNC(z.a_, x.a_, y.a_);
392 Fp::subNC(z.b_, x.b_, y.b_);
393 }
394
395 static inline void subC(Fp2T& z, const Fp2T& x, const Fp2T& y)
396 {
397 Fp::sub(z.a_, x.a_, y.a_);
398 Fp::sub(z.b_, x.b_, y.b_);
399 }
400 static inline void neg(Fp2T& z, const Fp2T& x)
401 {
402 Fp::neg(z.a_, x.a_);
403 Fp::neg(z.b_, x.b_);
404 }
405
406 /*
407 (a + b u)(c + d u) = (a c - b d) + (a d + b c)u
408 = (a c - b d) + ((a + b)(c + d) - a c - b d)u
409 N = 1 << 256
410 7p < N then 7(p-1)(p-1) < pN
411 */
412 static inline void mulC(Fp2T& z, const Fp2T& x, const Fp2T& y)
413 {
414 typename Fp::Dbl d[3];
415 Fp s, t;
416 Fp::addNC(s, x.a_, x.b_); // a + b
417 Fp::addNC(t, y.a_, y.b_); // c + d
418 Fp::Dbl::mul(d[0], s, t); // (a + b)(c + d)
419 Fp::Dbl::mul(d[1], x.a_, y.a_); // ac
420 Fp::Dbl::mul(d[2], x.b_, y.b_); // bd
421 Fp::Dbl::subNC(d[0], d[0], d[1]); // (a + b)(c + d) - ac
422 Fp::Dbl::subNC(d[0], d[0], d[2]); // (a + b)(c + d) - ac - bd
423 Fp::Dbl::mod(z.b_, d[0]); // set z[1]
424 Fp::Dbl::sub(d[1], d[1], d[2]); // ac - bd
425 Fp::Dbl::mod(z.a_, d[1]); // set z[0]
426 }
427
428 static inline void divBy2C(Fp2T& z, const Fp2T& x)
429 {
430 Fp::divBy2(z.a_, x.a_);
431 Fp::divBy2(z.b_, x.b_);
432 }
433
434 static inline void divBy4(Fp2T& z, const Fp2T& x)
435 {
436 Fp::divBy4(z.a_, x.a_);
437 Fp::divBy4(z.b_, x.b_);
438 }
439
440#ifdef BN_SUPPORT_SNARK
441 /*
442 XITAG
443 u^2 = -1
444 xi = 9 + u
445 (a + bu)(9 + u) = (9a - b) + (a + 9b)u
446 */
447 static inline void mul_xiC(Fp2T& z, const Fp2T& x)
448 {
449 assert(&z != &x);
450 Fp::add(z.a_, x.a_, x.a_); // 2
451 Fp::add(z.a_, z.a_, z.a_); // 4
452 Fp::add(z.a_, z.a_, z.a_); // 8
453 Fp::add(z.a_, z.a_, x.a_); // 9
454 Fp::sub(z.a_, z.a_, x.b_);
455
456 Fp::add(z.b_, x.b_, x.b_); // 2
457 Fp::add(z.b_, z.b_, z.b_); // 4
458 Fp::add(z.b_, z.b_, z.b_); // 8
459 Fp::add(z.b_, z.b_, x.b_); // 9
460 Fp::add(z.b_, z.b_, x.a_);
461 }
462#else
463 /*
464 u^2 = -1
465 xi = 1 + u
466 (a + bu)(1 + u) = (a - b) + (a + b)u
467
468 2 * Fp add/sub
469 */
470 static inline void mul_xiC(Fp2T& z, const Fp2T& x)
471 {
472 assert(&z != &x);
473 Fp::sub(z.a_, x.a_, x.b_);
474 Fp::add(z.b_, x.a_, x.b_);
475 }
476#endif
477
478 /*
479 (a + bu)^2 = (a - b)(a + b) + 2abu
480 */
481 static inline void squareC(Fp2T& z, const Fp2T& x)
482 {
483#ifdef BN_SUPPORT_SNARK
484 Fp t, tt;
485 Fp::add(t, x.b_, x.b_); // 2b
486 t *= x.a_; // 2ab
487 Fp::sub(tt, x.a_, x.b_); // a - b
488 Fp::add(z.a_, x.a_, x.b_); // a + b
489 z.a_ *= tt; // (a - b)(a + b)
490 z.b_ = t;
491#else
492 Fp t, tt;
493 Fp::addNC(t, x.b_, x.b_); // 2b
494 t *= x.a_; // 2ab
495 Fp::sub(tt, x.a_, x.b_); // a - b
496 Fp::addNC(z.a_, x.a_, x.a_); // a + b
497 z.a_ *= tt; // (a - b)(a + b)
498 z.b_ = t;
499#endif
500 }
501
502 /*
503 1 / (a + b u) = (a - b u) / (a^2 + b^2)
504 */
505 void inverse()
506 {
507 Fp t; Fp::mul(t, b_, b_);
508 Fp aa; Fp::mul(aa, a_, a_);
509 t += aa;
510 Fp::inv(t, t); // 7.5K@i7, 10Kclk@Opteron
511 a_ *= t;
512 Fp::neg(b_, b_);
513 b_ *= t;
514 }
515 void clear()
516 {
517 a_.clear();
518 b_.clear();
519 }
520
521 std::string toString(int base = 10) const
522 {
523 return ("[" + a_.toString(base) + "," + b_.toString(base) + "]");
524 }
525 friend std::ostream& operator<<(std::ostream& os, const Fp2T& x)
526 {
527 return os << x.toString();
528 }
529 friend std::istream& operator>>(std::istream& is, Fp2T& x)
530 {
531 char cl, cm, cr;
532 is >> cl >> x.a_ >> cm >> x.b_ >> cr;
533 if (cl == '[' && cm == ',' && cr == ']') return is;
534 throw std::ios_base::failure("bad Fp2");
535 }
536 bool operator==(const Fp2T& rhs) const
537 {
538 return a_ == rhs.a_ && b_ == rhs.b_;
539 }
540 bool operator!=(const Fp2T& rhs) const { return !operator==(rhs); }
541
542 void set(const std::string& str)
543 {
544 std::istringstream iss(str);
545 iss >> *this;
546 }
547
548 // z = x * b
549 static inline void mul_Fp_0C(Fp2T& z, const Fp2T& x, const Fp& b)
550 {
551 Fp::mul(z.a_, x.a_, b);
552 Fp::mul(z.b_, x.b_, b);
553 }
554
555 /*
556 u^2 = -1
557 (a + b)u = -b + au
558
559 1 * Fp neg
560 */
561 void mul_x()
562 {
563 Fp t = b_;
564 b_ = a_;
565 Fp::neg(a_, t);
566 }
567
568 /*
569 (a + bu)cu = -bc + acu,
570 where u is u^2 = -1.
571
572 2 * Fp mul
573 1 * Fp neg
574 */
575 static inline void mul_Fp_1(Fp2T& z, const Fp& y_b)
576 {
577 Fp t;
578 Fp::mul(t, z.b_, y_b);
579 Fp::mul(z.b_, z.a_, y_b);
580 Fp::neg(z.a_, t);
581 }
582
583 struct Dbl : public mie::local::addsubmul<Dbl, mie::local::hasNegative<Dbl> > {
584 typedef typename Fp::Dbl FpDbl;
585 enum { SIZE = FpDbl::SIZE * 2 };
586
588
589 std::string toString(int base = 10) const
590 {
591 return ("[" + a_.toString(base) + "," + b_.toString(base) + "]");
592 }
593 friend inline std::ostream& operator<<(std::ostream& os, const Dbl& x)
594 {
595 return os << x.toString();
596 }
597
598 Dbl() { }
599 Dbl(const Fp2T& x)
600 : a_(x.a_)
601 , b_(x.b_)
602 {
603 }
604 Dbl(const Fp& a, const Fp& b)
605 : a_(a)
606 , b_(b)
607 {
608 }
609 Dbl(const FpDbl& a, const FpDbl& b)
610 : a_(a)
611 , b_(b)
612 {
613 }
614 Dbl(const std::string& a, const std::string& b)
615 : a_(a)
616 , b_(b)
617 {
618 }
619
620 void setDirect(const mie::Vuint& a, const mie::Vuint& b)
621 {
624 }
625 void setDirect(const FpDbl& a, const FpDbl& b)
626 {
627 a_ = a;
628 b_ = b;
629 }
630 FpDbl* get() { return &a_; }
631 const FpDbl* get() const { return &a_; }
632 void clear()
633 {
634 a_.clear();
635 b_.clear();
636 }
637 bool isZero() const
638 {
639 return a_.isZero() && b_.isZero();
640 }
641
642 friend inline bool operator==(const Dbl& x, const Dbl& y)
643 {
644 return x.a_ == y.a_ && x.b_ == y.b_;
645 }
646 friend inline bool operator!=(const Dbl& x, const Dbl& y) { return !(x == y); }
647
648 typedef void (uni_op)(Dbl&, const Dbl&);
649 typedef void (bin_op)(Dbl&, const Dbl&, const Dbl&);
650
651 static bin_op* add;
652 static bin_op* addNC;
653 static uni_op* neg;
654 static bin_op* sub;
655 static bin_op* subNC;
656
657 static void (*mulOpt1)(Dbl& z, const Fp2T& x, const Fp2T& y);
658 static void (*mulOpt2)(Dbl& z, const Fp2T& x, const Fp2T& y);
659 static void (*square)(Dbl& z, const Fp2T& x);
660 static void (*mod)(Fp2T& z, const Dbl& x);
661
662 static uni_op* mul_xi;
663
664 static void addC(Dbl& z, const Dbl& x, const Dbl& y)
665 {
666 FpDbl::add(z.a_, x.a_, y.a_);
667 FpDbl::add(z.b_, x.b_, y.b_);
668 }
669
670 static void addNC_C(Dbl& z, const Dbl& x, const Dbl& y)
671 {
672 FpDbl::addNC(z.a_, x.a_, y.a_);
673 FpDbl::addNC(z.b_, x.b_, y.b_);
674 }
675
676 static void negC(Dbl& z, const Dbl& x)
677 {
678 FpDbl::neg(z.a_, x.a_);
679 FpDbl::neg(z.b_, x.b_);
680 }
681
682 static void subC(Dbl& z, const Dbl& x, const Dbl& y)
683 {
684 FpDbl::sub(z.a_, x.a_, y.a_);
685 FpDbl::sub(z.b_, x.b_, y.b_);
686 }
687
688 static void subNC_C(Dbl& z, const Dbl& x, const Dbl& y)
689 {
690 FpDbl::subNC(z.a_, x.a_, y.a_);
691 FpDbl::subNC(z.b_, x.b_, y.b_);
692 }
693
694#ifdef BN_SUPPORT_SNARK
695 /*
696 XITAG
697 u^2 = -1
698 xi = 9 + u
699 (a + bu)(9 + u) = (9a - b) + (a + 9b)u
700 */
701 static void mul_xiC(Dbl& z, const Dbl& x)
702 {
703 assert(&z != &x);
704 FpDbl::add(z.a_, x.a_, x.a_); // 2
705 FpDbl::add(z.a_, z.a_, z.a_); // 4
706 FpDbl::add(z.a_, z.a_, z.a_); // 8
707 FpDbl::add(z.a_, z.a_, x.a_); // 9
708 FpDbl::sub(z.a_, z.a_, x.b_);
709
710 FpDbl::add(z.b_, x.b_, x.b_); // 2
711 FpDbl::add(z.b_, z.b_, z.b_); // 4
712 FpDbl::add(z.b_, z.b_, z.b_); // 8
713 FpDbl::add(z.b_, z.b_, x.b_); // 9
714 FpDbl::add(z.b_, z.b_, x.a_);
715 }
716#else
717 static void mul_xiC(Dbl& z, const Dbl& x)
718 {
719 assert(&z != &x);
720 FpDbl::sub(z.a_, x.a_, x.b_);
721 FpDbl::add(z.b_, x.b_, x.a_);
722 }
723#endif
724
725 static void mulOptC(Dbl& z, const Fp2T& x, const Fp2T& y, int mode)
726 {
727 FpDbl d0;
728 Fp s, t;
729 Fp::addNC(s, x.a_, x.b_);
730 Fp::addNC(t, y.a_, y.b_);
731 FpDbl::mul(d0, x.b_, y.b_);
732 FpDbl::mul(z.a_, x.a_, y.a_);
733 FpDbl::mul(z.b_, s, t);
734 FpDbl::subNC(z.b_, z.b_, z.a_);
735 FpDbl::subNC(z.b_, z.b_, d0);
736
737 if (mode == 1) {
738 FpDbl::subOpt1(z.a_, z.a_, d0);
739
740 } else {
741 FpDbl::sub(z.a_, z.a_, d0);
742 }
743 }
744
745 static void mulOpt1C(Dbl& z, const Fp2T& x, const Fp2T& y)
746 {
747 mulOptC(z, x, y, 1);
748 }
749
750 static void mulOpt2C(Dbl& z, const Fp2T& x, const Fp2T& y)
751 {
752 mulOptC(z, x, y, 2);
753 }
754
755 static void squareC(Dbl& z, const Fp2T& x)
756 {
757 Fp t0, t1;
758 Fp::addNC(t0, x.b_, x.b_);
759 FpDbl::mul(z.b_, t0, x.a_);
760 Fp::addNC(t1, x.a_, Fp::getDirectP(1)); // RRR
761 Fp::subNC(t1, t1, x.b_);
762 Fp::addNC(t0, x.a_, x.b_);
763 FpDbl::mul(z.a_, t0, t1);
764 }
765
766 static void modC(Fp2T& z, const Dbl& x)
767 {
768 FpDbl::mod(z.a_, x.a_);
769 FpDbl::mod(z.b_, x.b_);
770 }
771 };
772};
773
774template<class Fp>
775void (*Fp2T<Fp>::add)(Fp2T<Fp>& out, const Fp2T<Fp>& x, const Fp2T<Fp>& y) = &(Fp2T<Fp>::addC);
776
777template<class Fp>
778void (*Fp2T<Fp>::addNC)(Fp2T<Fp>& out, const Fp2T<Fp>& x, const Fp2T<Fp>& y) = &(Fp2T<Fp>::addNC_C);
779
780template<class Fp>
781void (*Fp2T<Fp>::sub)(Fp2T<Fp>& out, const Fp2T<Fp>& x, const Fp2T<Fp>& y) = &(Fp2T<Fp>::subC);
782
783template<class Fp>
784void (*Fp2T<Fp>::subNC)(Fp2T<Fp>& out, const Fp2T<Fp>& x, const Fp2T<Fp>& y) = &(Fp2T<Fp>::subNC_C);
785
786template<class Fp>
787void (*Fp2T<Fp>::mul)(Fp2T<Fp>& out, const Fp2T<Fp>& x, const Fp2T<Fp>& y) = &(Fp2T<Fp>::mulC);
788
789template<class Fp>
790void (*Fp2T<Fp>::mul_xi)(Fp2T<Fp>& out, const Fp2T<Fp>& x) = &(Fp2T<Fp>::mul_xiC);
791
792template<class Fp>
793void (*Fp2T<Fp>::square)(Fp2T<Fp>& out, const Fp2T<Fp>& x) = &(Fp2T<Fp>::squareC);
794
795template<class Fp>
796void (*Fp2T<Fp>::mul_Fp_0)(Fp2T<Fp>& z, const Fp2T<Fp>& x, const Fp& y) = &(Fp2T<Fp>::mul_Fp_0C);
797
798template<class Fp>
799void (*Fp2T<Fp>::divBy2)(Fp2T<Fp>& out, const Fp2T<Fp>& x) = &(Fp2T<Fp>::divBy2C);
800
801template<class Fp>
803
804template<class Fp>
806
807template<class Fp>
809
810template<class Fp>
812
813template<class Fp>
815
816template<class Fp>
818
819template<class Fp>
820void (*Fp2T<Fp>::Dbl::mulOpt1)(Dbl&, const Fp2T&, const Fp2T&) = &(Fp2T<Fp>::Dbl::mulOpt1C);
821
822template<class Fp>
823void (*Fp2T<Fp>::Dbl::mulOpt2)(Dbl&, const Fp2T&, const Fp2T&) = &(Fp2T<Fp>::Dbl::mulOpt2C);
824
825template<class Fp>
826void (*Fp2T<Fp>::Dbl::square)(Dbl&, const Fp2T&) = &(Fp2T<Fp>::Dbl::squareC);
827
828template<class Fp>
829void (*Fp2T<Fp>::Dbl::mod)(Fp2T&, const Dbl&) = &(Fp2T<Fp>::Dbl::modC);
830
831/*
832 Fp6T = Fp2[v] / (v^3 - Xi), Xi = -u - 1
833 x = a_ + b_ v + c_ v^2
834*/
835template<class T>
836struct Fp6T : public mie::local::addsubmul<Fp6T<T>,
837 mie::local::hasNegative<Fp6T<T> > > {
838 typedef T Fp2;
839 typedef typename T::Fp Fp;
841 typedef typename Fp2::Dbl Fp2Dbl;
843 Fp6T() { }
844 Fp6T(int x)
845 : a_(x)
846 , b_(0)
847 , c_(0)
848 {
849 }
850 Fp6T(const Fp2& a, const Fp2& b, const Fp2& c)
851 : a_(a)
852 , b_(b)
853 , c_(c)
854 {
855 }
856 Fp6T(const Fp& a0, const Fp& a1, const Fp& a2, const Fp& a3, const Fp& a4, const Fp& a5)
857 : a_(a0, a1)
858 , b_(a2, a3)
859 , c_(a4, a5)
860 {
861 }
862 void clear()
863 {
864 a_.clear();
865 b_.clear();
866 c_.clear();
867 }
868
869 Fp* get() { return a_.get(); }
870 const Fp* get() const { return a_.get(); }
871 Fp2* getFp2() { return &a_; }
872 const Fp2* getFp2() const { return &a_; }
873 void set(const Fp2& v0, const Fp2& v1, const Fp2& v2)
874 {
875 a_ = v0;
876 b_ = v1;
877 c_ = v2;
878 }
879 bool isZero() const
880 {
881 return a_.isZero() && b_.isZero() && c_.isZero();
882 }
883
884 static inline void addC(Fp6T& z, const Fp6T& x, const Fp6T& y)
885 {
886 Fp2::add(z.a_, x.a_, y.a_);
887 Fp2::add(z.b_, x.b_, y.b_);
888 Fp2::add(z.c_, x.c_, y.c_);
889 }
890 static inline void subC(Fp6T& z, const Fp6T& x, const Fp6T& y)
891 {
892 Fp2::sub(z.a_, x.a_, y.a_);
893 Fp2::sub(z.b_, x.b_, y.b_);
894 Fp2::sub(z.c_, x.c_, y.c_);
895 }
896 static inline void neg(Fp6T& z, const Fp6T& x)
897 {
898 Fp2::neg(z.a_, x.a_);
899 Fp2::neg(z.b_, x.b_);
900 Fp2::neg(z.c_, x.c_);
901 }
902
903 // 2120clk x 128
904 static inline void mulC(Fp6T& z, const Fp6T& x, const Fp6T& y)
905 {
906 Dbl zd;
907 Dbl::mul(zd, x, y);
908 Dbl::mod(z, zd);
909 }
910
911 /*
912 1944clk * 2
913 */
914 static void square(Fp6T& z, const Fp6T& x)
915 {
916 assert(&z != &x);
917 Fp2 v3, v4, v5;
918 Fp2::add(v4, x.a_, x.a_);
919 Fp2::mul(v4, v4, x.b_);
920 Fp2::square(v5, x.c_);
921 Fp2::mul_xi(z.b_, v5);
922 z.b_ += v4;
923 Fp2::sub(z.c_, v4, v5);
924 Fp2::square(v3, x.a_);
925 Fp2::sub(v4, x.a_, x.b_);
926 v4 += x.c_;
927 Fp2::add(v5, x.b_, x.b_);
928 Fp2::mul(v5, v5, x.c_);
929 Fp2::square(v4, v4);
930 Fp2::mul_xi(z.a_, v5);
931 z.a_ += v3;
932 z.c_ += v4;
933 z.c_ += v5;
934 z.c_ -= v3;
935 }
936
937 void inverse()
938 {
939 Fp6T z;
940 Fp2 t0, t1, t2, t4, t5;
941 Fp2::mul(t0, b_, c_);
942 Fp2::mul_xi(z.a_, t0);
943 Fp2::square(t0, a_);
944 Fp2::sub(z.a_, t0, z.a_);
945 Fp2::square(t1, b_);
946 Fp2::mul(t5, a_, c_);
947 Fp2::sub(z.c_, t1, t5);
948 Fp2::square(t2, c_);
949 Fp2::mul(t4, a_, b_);
950 Fp2::mul_xi(z.b_, t2);
951 z.b_ -= t4;
952 Fp2::mul(t1, a_, z.a_);
953 Fp2::mul(t5, c_, z.b_);
954 Fp2::mul_xi(t4, t5);
955 t1 += t4;
956 Fp2::mul(t5, b_, z.c_);
957 Fp2::mul_xi(t4, t5);
958 t1 += t4;
959 t1.inverse();
960 Fp2::mul(a_, z.a_, t1);
961 Fp2::mul(b_, z.b_, t1);
962 Fp2::mul(c_, z.c_, t1);
963 }
964
965 bool operator==(const Fp6T& rhs) const
966 {
967 return a_ == rhs.a_ && b_ == rhs.b_ && c_ == rhs.c_;
968 }
969 bool operator!=(const Fp6T& rhs) const { return !operator==(rhs); }
970 friend std::ostream& operator<<(std::ostream& os, const Fp6T& x)
971 {
972 return os << "[" << x.a_ << ",\n " << x.b_ << ",\n " << x.c_ << "]";
973 }
974 friend std::istream& operator>>(std::istream& is, Fp6T& x)
975 {
976 char c1, c2, c3, c4;
977 is >> c1 >> x.a_ >> c2 >> x.b_ >> c3 >> x.c_ >> c4;
978 if (c1 == '[' && c2 == ',' && c3 == ',' && c4 == ']') return is;
979 throw std::ios_base::failure("bad Fp6");
980 }
981
982 static void (*add)(Fp6T& z, const Fp6T& x, const Fp6T& y);
983 static void (*sub)(Fp6T& z, const Fp6T& x, const Fp6T& y);
984 static void (*mul)(Fp6T& z, const Fp6T& x, const Fp6T& y);
985
986 static void (*pointDblLineEval)(Fp6T& l, Fp2* R, const Fp* P);
987 static void (*pointDblLineEvalWithoutP)(Fp6T& l, Fp2* R);
988 /*
989 Algorithm 11 in App.B of Aranha et al. ePrint 2010/526
990
991 NOTE:
992 The original version uses precomputed and stored value of -P[1].
993 But, we do not use that, this algorithm always calculates it.
994
995 input P[0..2], R[0..2]
996 R <- [2]R,
997 (l00, 0, l02, 0, l11, 0) = f_{R,R}(P),
998 l = (a,b,c) = (l00, l11, l02)
999 where P[2] == 1
1000 */
1002 {
1003 Fp2 t0, t1, t2, t3, t4, t5;
1004 Fp2Dbl T0, T1, T2;
1005 // X1, Y1, Z1 == R[0], R[1], R[2]
1006 // xp, yp = P[0], P[1]
1007
1008 // # 1
1009 Fp2::square(t0, R[2]);
1010 Fp2::mul(t4, R[0], R[1]);
1011 Fp2::square(t1, R[1]);
1012 // # 2
1013 Fp2::add(t3, t0, t0);
1014 Fp2::divBy2(t4, t4);
1015 Fp2::add(t5, t0, t1);
1016 // # 3
1017 t0 += t3;
1018 // # 4
1019#ifdef BN_SUPPORT_SNARK
1020 if (ParamT<Fp2>::b == 82) {
1021 // (a + bu) * (9 - u) = (9a + b) + (9b - a)u
1022 t3.a_ = t0.b_;
1023 t3.b_ = t0.a_;
1024 Fp2::mul_xi(t0, t3);
1025 t2.a_ = t0.b_;
1026 t2.b_ = t0.a_;
1027 } else {
1028 // (a + bu) * binv_xi
1030 }
1031#else
1032 // (a + bu)(1 - u) = (a + b) + (b - a)u
1033 Fp::add(t2.a_, t0.a_, t0.b_);
1034 Fp::sub(t2.b_, t0.b_, t0.a_);
1035#endif
1036 // # 5
1037 Fp2::square(t0, R[0]);
1038 Fp2::add(t3, t2, t2);
1039 // ## 6
1040 t3 += t2;
1041 Fp2::addNC(l.c_, t0, t0);
1042 // ## 7
1043 Fp2::sub(R[0], t1, t3);
1044 Fp2::addNC(l.c_, l.c_, t0);
1045 t3 += t1;
1046 // # 8
1047 R[0] *= t4;
1048 Fp2::divBy2(t3, t3);
1049 // ## 9
1050 Fp2Dbl::square(T0, t3);
1051 Fp2Dbl::square(T1, t2);
1052 // # 10
1053 Fp2Dbl::addNC(T2, T1, T1);
1054 Fp2::add(t3, R[1], R[2]);
1055 // # 11
1056#ifdef BN_SUPPORT_SNARK
1057 Fp2Dbl::add(T2, T2, T1);
1058#else
1059 Fp2Dbl::addNC(T2, T2, T1);
1060#endif
1061 Fp2::square(t3, t3);
1062 // # 12
1063 t3 -= t5;
1064 // # 13
1065 T0 -= T2;
1066 // # 14
1067 Fp2Dbl::mod(R[1], T0);
1068 Fp2::mul(R[2], t1, t3);
1069 t2 -= t1;
1070 // # 15
1071 Fp2::mul_xi(l.a_, t2);
1072 Fp2::neg(l.b_, t3);
1073 }
1074 static void mulFp6_24_Fp_01(Fp6T& l, const Fp* P)
1075 {
1076 Fp2::mul_Fp_0(l.c_, l.c_, P[0]);
1077 Fp2::mul_Fp_0(l.b_, l.b_, P[1]);
1078 }
1079 static void pointDblLineEvalC(Fp6T& l, Fp2* R, const Fp* P)
1080 {
1082 // # 16, #17
1084 }
1085 /*
1086 Algorithm 12 in App.B of Aranha et al. ePrint 2010/526
1087
1088 input : P[0..1], Q[0..1], R[0..2]
1089 R <- R + Q
1090 (l00, 0, l02, 0, l11, 0) = f_{R,Q}(P),
1091 l = (a,b,c) = (l00, l11, l02)
1092 where Q[2] == 1, and P[2] == 1
1093 */
1094 static void pointAddLineEvalWithoutP(Fp6T& l, Fp2* R, const Fp2* Q)
1095 {
1096 Fp2 t1, t2, t3, t4;
1097 Fp2Dbl T1, T2;
1098 // # 1
1099 Fp2::mul(t1, R[2], Q[0]);
1100 Fp2::mul(t2, R[2], Q[1]);
1101 // # 2
1102 Fp2::sub(t1, R[0], t1);
1103 Fp2::sub(t2, R[1], t2);
1104 // # 3
1105 Fp2::square(t3, t1);
1106 // # 4
1107 Fp2::mul(R[0], t3, R[0]);
1108 Fp2::square(t4, t2);
1109 // # 5
1110 t3 *= t1;
1111 t4 *= R[2];
1112 // # 6
1113 t4 += t3;
1114 // # 7
1115 t4 -= R[0];
1116 // # 8
1117 t4 -= R[0];
1118 // # 9
1119 R[0] -= t4;
1120 // # 10
1121 Fp2Dbl::mulOpt1(T1, t2, R[0]);
1122 Fp2Dbl::mulOpt1(T2, t3, R[1]);
1123 // # 11
1124 Fp2Dbl::sub(T2, T1, T2);
1125 // # 12
1126 Fp2Dbl::mod(R[1], T2);
1127 Fp2::mul(R[0], t1, t4);
1128 Fp2::mul(R[2], t3, R[2]);
1129 // # 14
1130 Fp2::neg(l.c_, t2);
1131 // # 15
1132 Fp2Dbl::mulOpt1(T1, t2, Q[0]);
1133 Fp2Dbl::mulOpt1(T2, t1, Q[1]);
1134 // # 16
1135 Fp2Dbl::sub(T1, T1, T2);
1136 // # 17
1137 Fp2Dbl::mod(t2, T1);
1138 // ### @note: Be careful, below fomulas are typo.
1139 // # 18
1140 Fp2::mul_xi(l.a_, t2);
1141 l.b_ = t1;
1142 }
1143 static void pointAddLineEval(Fp6T& l, Fp2* R, const Fp2* Q, const Fp* P)
1144 {
1146 // # 13, #19
1148 }
1149 static void mul_Fp_b(Fp6T& z, const Fp& x)
1150 {
1151 Fp2::mul_Fp_0(z.b_, z.b_, x);
1152 }
1153 static void mul_Fp_c(Fp6T& z, const Fp& x)
1154 {
1155 Fp2::mul_Fp_0(z.c_, z.c_, x);
1156 }
1157
1158 struct Dbl : public mie::local::addsubmul<Dbl, mie::local::hasNegative<Dbl> > {
1159 typedef typename Fp::Dbl FpDbl;
1160 typedef typename Fp2::Dbl Fp2Dbl;
1161 enum { SIZE = Fp2Dbl::SIZE * 3 };
1162
1164
1165 std::string toString(int base = 10) const
1166 {
1167 return ("[" + a_.toString(base) + ",\n" + b_.toString(base) + ",\n" + c_.toString() + "]");
1168 }
1169 friend inline std::ostream& operator<<(std::ostream& os, const Dbl& x)
1170 {
1171 return os << x.toString();
1172 }
1173
1174 Dbl() { }
1175 Dbl(const Fp6T& x)
1176 : a_(x.a_)
1177 , b_(x.b_)
1178 , c_(x.c_)
1179 {
1180 }
1181 Dbl(const Fp2& a, const Fp2& b, const Fp2& c)
1182 : a_(a)
1183 , b_(b)
1184 , c_(c)
1185 {
1186 }
1187 Dbl(const Fp2Dbl& a, const Fp2Dbl& b, const Fp2Dbl& c)
1188 : a_(a)
1189 , b_(b)
1190 , c_(c)
1191 {
1192 }
1193 Dbl(const std::string& a0, const std::string& a1, const std::string& b0, const std::string& b1, const std::string& c0, const std::string& c1)
1194 : a_(a0, a1)
1195 , b_(b0, b1)
1196 , c_(c0, c1)
1197 {
1198 }
1199
1200 void setDirect(const mie::Vuint& v0, const mie::Vuint& v1, const mie::Vuint& v2, const mie::Vuint& v3, const mie::Vuint& v4, const mie::Vuint& v5)
1201 {
1202 a_.setDirect(v0, v1);
1203 b_.setDirect(v2, v3);
1204 c_.setDirect(v4, v5);
1205 }
1206 void setDirect(const Fp2Dbl& a, const Fp2Dbl& b, const Fp2Dbl& c)
1207 {
1208 a_ = a;
1209 b_ = b;
1210 c_ = c;
1211 }
1212 Fp2Dbl* get() { return &a_; }
1213 const Fp2Dbl* get() const { return &a_; }
1214 bool isZero() const
1215 {
1216 return a_.isZero() && b_.isZero() && c_.isZero();
1217 }
1218
1219 friend inline bool operator==(const Dbl& x, const Dbl& y)
1220 {
1221 return x.a_ == y.a_ && x.b_ == y.b_ && x.c_ == y.c_;
1222 }
1223 friend inline bool operator!=(const Dbl& x, const Dbl& y) { return !(x == y); }
1224
1225 typedef void (uni_op)(Dbl&, const Dbl&);
1226 typedef void (bin_op)(Dbl&, const Dbl&, const Dbl&);
1227
1228 static void add(Dbl& z, const Dbl& x, const Dbl& y)
1229 {
1230 Fp2Dbl::add(z.a_, x.a_, y.a_);
1231 Fp2Dbl::add(z.b_, x.b_, y.b_);
1232 Fp2Dbl::add(z.c_, x.c_, y.c_);
1233 }
1234
1235 static void addNC(Dbl& z, const Dbl& x, const Dbl& y)
1236 {
1237 Fp2Dbl::addNC(z.a_, x.a_, y.a_);
1238 Fp2Dbl::addNC(z.b_, x.b_, y.b_);
1239 Fp2Dbl::addNC(z.c_, x.c_, y.c_);
1240 }
1241
1242 static void neg(Dbl& z, const Dbl& x)
1243 {
1244 Fp2Dbl::neg(z.a_, x.a_);
1245 Fp2Dbl::neg(z.b_, x.b_);
1246 Fp2Dbl::neg(z.c_, x.c_);
1247 }
1248
1249 static void sub(Dbl& z, const Dbl& x, const Dbl& y)
1250 {
1251 Fp2Dbl::sub(z.a_, x.a_, y.a_);
1252 Fp2Dbl::sub(z.b_, x.b_, y.b_);
1253 Fp2Dbl::sub(z.c_, x.c_, y.c_);
1254 }
1255
1256 static void subNC(Dbl& z, const Dbl& x, const Dbl& y)
1257 {
1258 Fp2Dbl::subNC(z.a_, x.a_, y.a_);
1259 Fp2Dbl::subNC(z.b_, x.b_, y.b_);
1260 Fp2Dbl::subNC(z.c_, x.c_, y.c_);
1261 }
1262 static void (*mul)(Dbl&, const Fp6T& x, const Fp6T& y);
1263
1264 /*
1265 1978clk * 262 ; QQQ
1266 => 1822clk => 1580clk
1267 */
1268 static void mulC(Dbl& z, const Fp6T& x, const Fp6T& y)
1269 {
1270 Fp2 t0, t1;
1271 Fp2Dbl T0, T1, T2;
1272 // # 1
1273 Fp2Dbl::mulOpt1(T0, x.a_, y.a_);
1274 Fp2Dbl::mulOpt1(T1, x.b_, y.b_);
1275 Fp2Dbl::mulOpt1(T2, x.c_, y.c_);
1276 // # 2
1277 Fp2::addNC(t0, x.b_, x.c_);
1278 Fp2::addNC(t1, y.b_, y.c_);
1279 // # 3
1280 Fp2Dbl::mulOpt2(z.c_, t0, t1);
1281 // # 4
1282 Fp2Dbl::addNC(z.b_, T1, T2);
1283 // # 5
1284 FpDbl::sub(z.c_.a_, z.c_.a_, z.b_.a_);
1285 // # 6
1286 FpDbl::subNC(z.c_.b_, z.c_.b_, z.b_.b_);
1287 // # 7
1288 Fp2Dbl::mul_xi(z.b_, z.c_);
1289 // # 8
1290 Fp2Dbl::add(z.a_, z.b_, T0);
1291 // # 9
1292 Fp2::addNC(t0, x.a_, x.b_);
1293 Fp2::addNC(t1, y.a_, y.b_);
1294 // # 10
1295 Fp2Dbl::mulOpt2(z.c_, t0, t1);
1296 // # 11
1297 Fp2Dbl::addNC(z.b_, T0, T1);
1298 // # 12
1299 FpDbl::sub(z.c_.a_, z.c_.a_, z.b_.a_);
1300 // # 13
1301 FpDbl::subNC(z.c_.b_, z.c_.b_, z.b_.b_);
1303 // # 14, 15
1304#ifdef BN_SUPPORT_SNARK
1305 Fp2Dbl::mul_xi(z.b_, T2); // store xi * t2 term
1306#else
1307 FpDbl::subOpt1(z.b_.a_, T2.a_, T2.b_);
1308 FpDbl::add(z.b_.b_, T2.a_, T2.b_);
1309#endif
1310 // # 16
1311 Fp2Dbl::add(z.b_, z.b_, z.c_);
1312 // # 17
1313 Fp2::addNC(t0, x.a_, x.c_);
1314 Fp2::addNC(t1, y.a_, y.c_);
1315 // # 18
1316 Fp2Dbl::mulOpt2(z.c_, t0, t1);
1317 // # 19
1318 Fp2Dbl::addNC(T2, T2, T0);
1319 // # 20
1320 FpDbl::sub(z.c_.a_, z.c_.a_, T2.a_);
1321 // # 22
1322 FpDbl::add(z.c_.a_, z.c_.a_, T1.a_);
1323 // # 21
1324 FpDbl::subNC(z.c_.b_, z.c_.b_, T2.b_);
1325 // # 23
1326 FpDbl::addNC(z.c_.b_, z.c_.b_, T1.b_);
1327 }
1328 static void mod(Fp6T& z, const Dbl& x)
1329 {
1330 Fp2Dbl::mod(z.a_, x.a_);
1331 Fp2Dbl::mod(z.b_, x.b_);
1332 Fp2Dbl::mod(z.c_, x.c_);
1333 }
1334 };
1335};
1336
1337template<class Fp2>
1338void (*Fp6T<Fp2>::add)(Fp6T<Fp2>& z, const Fp6T<Fp2>& x, const Fp6T<Fp2>& y) = &(Fp6T<Fp2>::addC);
1339
1340template<class Fp2>
1341void (*Fp6T<Fp2>::sub)(Fp6T<Fp2>& z, const Fp6T<Fp2>& x, const Fp6T<Fp2>& y) = &(Fp6T<Fp2>::subC);
1342
1343template<class Fp2>
1344void (*Fp6T<Fp2>::mul)(Fp6T<Fp2>& z, const Fp6T<Fp2>& x, const Fp6T<Fp2>& y) = &(Fp6T<Fp2>::mulC);
1345
1346template<class Fp2>
1347void (*Fp6T<Fp2>::pointDblLineEval)(Fp6T<Fp2>& z, Fp2* x, const typename Fp2::Fp* y) = &(Fp6T<Fp2>::pointDblLineEvalC);
1348
1349template<class Fp2>
1351
1352template<class Fp2>
1353void (*Fp6T<Fp2>::Dbl::mul)(Dbl& z, const Fp6T& x, const Fp6T& y) = &(Fp6T<Fp2>::Dbl::mulC);
1354
1355template<class Fp2>
1356struct CompressT;
1357
1358/*
1359 Fp12T = Fp6[w] / (w^2 - v)
1360 x = a_ + b_ w
1361*/
1362template<class T>
1363struct Fp12T : public mie::local::addsubmul<Fp12T<T> > {
1364 typedef T Fp6;
1365 typedef typename Fp6::Fp2 Fp2;
1366 typedef typename Fp6::Fp Fp;
1368 typedef typename Fp2::Dbl Fp2Dbl;
1369 typedef typename Fp6::Dbl Fp6Dbl;
1370
1372 Fp12T() { }
1373 Fp12T(int x)
1374 : a_(x)
1375 , b_(0)
1376 {
1377 }
1378 Fp12T(const Fp6& a, const Fp6& b)
1379 : a_(a)
1380 , b_(b)
1381 {
1382 }
1383 Fp12T(const Fp& a0, const Fp& a1, const Fp& a2, const Fp& a3, const Fp& a4, const Fp& a5,
1384 const Fp& a6, const Fp& a7, const Fp& a8, const Fp& a9, const Fp& a10, const Fp& a11)
1385 : a_(a0, a1, a2, a3, a4, a5)
1386 , b_(a6, a7, a8, a9, a10, a11)
1387 {
1388 }
1389
1390 Fp12T(const Fp2& a0, const Fp2& a1, const Fp2& a2, const Fp2& a3, const Fp2& a4, const Fp2& a5)
1391 : a_(a0, a1, a2)
1392 , b_(a3, a4, a5)
1393 {
1394 }
1395
1396 void clear()
1397 {
1398 a_.clear();
1399 b_.clear();
1400 }
1401
1402 Fp* get() { return a_.get(); }
1403 const Fp* get() const { return a_.get(); }
1404 Fp2* getFp2() { return a_.getFp2(); }
1405 const Fp2* getFp2() const { return a_.getFp2(); }
1406 void set(const Fp2& v0, const Fp2& v1, const Fp2& v2, const Fp2& v3, const Fp2& v4, const Fp2& v5)
1407 {
1408 a_.set(v0, v1, v2);
1409 b_.set(v3, v4, v5);
1410 }
1411
1412 bool isZero() const
1413 {
1414 return a_.isZero() && b_.isZero();
1415 }
1416 bool operator==(const Fp12T& rhs) const
1417 {
1418 return a_ == rhs.a_ && b_ == rhs.b_;
1419 }
1420 bool operator!=(const Fp12T& rhs) const { return !operator==(rhs); }
1421 friend std::ostream& operator<<(std::ostream& os, const Fp12T& x)
1422 {
1423 return os << "[" << x.a_ << ",\n " << x.b_ << "]";
1424 }
1425 friend std::istream& operator>>(std::istream& is, Fp12T& x)
1426 {
1427 char c1, c2, c3;
1428 is >> c1 >> x.a_ >> c2 >> x.b_ >> c3;
1429 if (c1 == '[' && c2 == ',' && c3 == ']') return is;
1430 throw std::ios_base::failure("bad Fp12");
1431 }
1432 static inline void add(Fp12T& z, const Fp12T& x, const Fp12T& y)
1433 {
1434 Fp6::add(z.a_, x.a_, y.a_);
1435 Fp6::add(z.b_, x.b_, y.b_);
1436 }
1437 static inline void sub(Fp12T& z, const Fp12T& x, const Fp12T& y)
1438 {
1439 Fp6::sub(z.a_, x.a_, y.a_);
1440 Fp6::sub(z.b_, x.b_, y.b_);
1441 }
1442 static inline void neg(Fp12T& z, const Fp12T& x)
1443 {
1444 Fp6::neg(z.a_, x.a_);
1445 Fp6::neg(z.b_, x.b_);
1446 }
1447
1448 // 6.4k x 22
1449 static void (*mul)(Fp12T& z, const Fp12T& x, const Fp12T& y);
1450 static inline void mulC(Fp12T& z, const Fp12T& x, const Fp12T& y)
1451 {
1452 Dbl zd;
1453 Fp6 t0, t1;
1454 Fp6Dbl T0, T1, T2;
1455 // # 1
1456 Fp6Dbl::mul(T0, x.a_, y.a_);
1457 Fp6Dbl::mul(T1, x.b_, y.b_);
1458 Fp6::add(t0, x.a_, x.b_);
1459 Fp6::add(t1, y.a_, y.b_);
1460 // # 2
1461 Fp6Dbl::mul(zd.a_, t0, t1);
1462 // # 3
1463 Fp6Dbl::add(T2, T0, T1);
1464 // # 4
1465 Fp6Dbl::sub(zd.b_, zd.a_, T2);
1466 // #6, 7, 8
1468 Dbl::mod(z, zd);
1469 }
1470
1471 /*
1472 z = *this * *this
1473 4800clk x 64
1474 */
1475 static void (*square)(Fp12T& z);
1476 static void squareC(Fp12T& z)
1477 {
1478 Fp6 t0, t1;
1479 // # 1, 2
1480 Fp6::add(t0, z.a_, z.b_);
1481 // b_.mul_gamma(t1); t1 += a_; # 3
1482 mul_gamma_add<Fp6, Fp2>(t1, z.b_, z.a_);
1483 // # 4
1484 z.b_ *= z.a_;
1485 Fp6::mul(z.a_, t0, t1);
1486 // # 5, 6, 7 @note It's typo.
1487 mul_gamma_add<Fp6, Fp2>(t1, z.b_, z.b_);
1488 // # 8
1489 z.a_ -= t1;
1490 z.b_ += z.b_;
1491 }
1492
1493 /*
1494 square over Fp4
1495 Operation Count:
1496
1497 3 * Fp2Dbl::square
1498 2 * Fp2Dbl::mod
1499 1 * Fp2Dbl::mul_xi == 1 * (2 * Fp2::add/sub) == 2 * Fp2::add/sub
1500 3 * Fp2Dbl::add/sub == 3 * (2 * Fp2::add/sub) == 6 * Fp2::add/sub
1501 1 * Fp2::add/sub
1502
1503 Total:
1504
1505 3 * Fp2Dbl::square
1506 2 * Fp2Dbl::mod
1507 9 * Fp2::add/sub
1508 */
1509 static inline void sq_Fp4UseDbl(Fp2& z0, Fp2& z1, const Fp2& x0, const Fp2& x1)
1510 {
1511 Fp2Dbl T0, T1, T2;
1512 Fp2Dbl::square(T0, x0);
1513 Fp2Dbl::square(T1, x1);
1514 Fp2Dbl::mul_xi(T2, T1);
1515 T2 += T0;
1516 Fp2::add(z1, x0, x1);
1517 Fp2Dbl::mod(z0, T2);
1518 // overwrite z[0] (position 0).
1519 Fp2Dbl::square(T2, z1);
1520 T2 -= T0;
1521 T2 -= T1;
1522 Fp2Dbl::mod(z1, T2);
1523 }
1524
1525 /*
1526 square over only cyclotomic subgroup
1527 z_ = x_^2
1528 output to z_
1529
1530 It is based on:
1531 - Robert Granger and Michael Scott.
1532 Faster squaring in the cyclotomic subgroup of sixth degree extensions.
1533 PKC2010, pp. 209--223. doi:10.1007/978-3-642-13013-7_13.
1534 */
1535 /*
1536 Operation Count:
1537 3 * sq_Fp4UseDbl == 3 * (
1538 3 * Fp2Dbl::square
1539 2 * Fp2Dbl::mod
1540 9 * Fp2::add/sub
1541 ) == (
1542 9 * Fp2Dbl::square
1543 6 * Fp2Dbl::mod
1544 27 * Fp2::add/sub
1545 )
1546 18 * Fp2::add/sub
1547 1 * Fp2::mul_xi
1548
1549 Total:
1550
1551 9 * Fp2Dbl::square
1552 6 * Fp2Dbl::mod
1553 46 * Fp2::add/sub
1554 3260k x 4
1555 */
1556 void Fp2_2z_add_3x(Fp2& z, const Fp2& x)
1557 {
1558 Fp::_2z_add_3x(z.a_, x.a_);
1559 Fp::_2z_add_3x(z.b_, x.b_);
1560 }
1561 void sqru()
1562 {
1563 Fp2& z0(a_.a_);
1564 Fp2& z4(a_.b_);
1565 Fp2& z3(a_.c_);
1566 Fp2& z2(b_.a_);
1567 Fp2& z1(b_.b_);
1568 Fp2& z5(b_.c_);
1569 Fp2 t0, t1;
1570 sq_Fp4UseDbl(t0, t1, z0, z1); // a^2 = t0 + t1*y
1571 // For A
1572 Fp2::sub(z0, t0, z0);
1573 z0 += z0;
1574 z0 += t0;
1575#if 0
1576 Fp2_2z_add_3x(z1, t1);
1577#else
1578 Fp2::add(z1, t1, z1);
1579 z1 += z1;
1580 z1 += t1;
1581#endif
1582 // t0 and t1 are unnecessary from here.
1583 Fp2 t2, t3;
1584 sq_Fp4UseDbl(t0, t1, z2, z3); // b^2 = t0 + t1*y
1585 sq_Fp4UseDbl(t2, t3, z4, z5); // c^2 = t2 + t3*y
1586 // For C
1587 Fp2::sub(z4, t0, z4);
1588 z4 += z4;
1589 z4 += t0;
1590#if 0
1591 Fp2_2z_add_3x(z5, t1);
1592#else
1593 Fp2::add(z5, t1, z5);
1594 z5 += z5;
1595 z5 += t1;
1596#endif
1597 // For B
1598 Fp2::mul_xi(t0, t3);
1599#if 0
1600 Fp2_2z_add_3x(z2, t0);
1601#else
1602 Fp2::add(z2, t0, z2);
1603 z2 += z2;
1604 z2 += t0;
1605#endif
1606 Fp2::sub(z3, t2, z3);
1607 z3 += z3;
1608 z3 += t2;
1609 }
1610
1611 /*
1612 This is same as sqru, but output given reference.
1613 */
1614 void sqru(Fp12T& zz) const
1615 {
1616 zz = *this;
1617 zz.sqru();
1618 }
1619
1620 void inverse()
1621 {
1622 Fp6 tmp0;
1623 Fp6 tmp1;
1624 Fp2 tmp2;
1625 Fp6::square(tmp0, a_);
1626 Fp6::square(tmp1, b_);
1627 Fp2::mul_xi(tmp2, tmp1.c_);
1628 tmp0.a_ -= tmp2;
1629 tmp0.b_ -= tmp1.a_;
1630 tmp0.c_ -= tmp1.b_;
1631 tmp0.inverse();
1632 Fp6::mul(a_, a_, tmp0);
1633 Fp6::mul(b_, b_, tmp0);
1634 Fp6::neg(b_, b_);
1635 }
1636
1637 /*
1638 (a + bw) -> (a - bw) gammar
1639 */
1640 void Frobenius(Fp12T& z) const
1641 {
1642 /* this assumes (q-1)/6 is odd */
1643 if (&z != this) {
1644 z.a_.a_.a_ = a_.a_.a_;
1645 z.a_.b_.a_ = a_.b_.a_;
1646 z.a_.c_.a_ = a_.c_.a_;
1647 z.b_.a_.a_ = b_.a_.a_;
1648 z.b_.b_.a_ = b_.b_.a_;
1649 z.b_.c_.a_ = b_.c_.a_;
1650 }
1651 Fp::neg(z.a_.a_.b_, a_.a_.b_);
1652 Fp::neg(z.a_.b_.b_, a_.b_.b_);
1653 Fp::neg(z.a_.c_.b_, a_.c_.b_);
1654 Fp::neg(z.b_.a_.b_, b_.a_.b_);
1655 Fp::neg(z.b_.b_.b_, b_.b_.b_);
1656 Fp::neg(z.b_.c_.b_, b_.c_.b_);
1657#ifdef BN_SUPPORT_SNARK
1658 z.a_.b_ *= Param::gammar[1];
1659 z.a_.c_ *= Param::gammar[3];
1660#else
1661 assert(Param::gammar[1].a_ == 0);
1662 assert(Param::gammar[3].b_ == 0);
1663 Fp2::mul_Fp_1(z.a_.b_, Param::gammar[1].b_);
1664 Fp2::mul_Fp_0(z.a_.c_, z.a_.c_, Param::gammar[3].a_);
1665#endif
1666 z.b_.a_ *= Param::gammar[0];
1667 z.b_.b_ *= Param::gammar[2];
1668 z.b_.c_ *= Param::gammar[4];
1669 }
1670
1671 /*
1672 gammar = c + dw
1673 a + bw -> t = (a - bw)(c + dw)
1674 ~t = (a + bw)(c - dw)
1675 ~t * (c + dw) = (a + bw) * ((c + dw)(c - dw))
1676 gammar2 = (c + dw)(c - dw) in Fp6
1677 */
1678 void Frobenius2(Fp12T& z) const
1679 {
1680#if 0
1681 Frobenius(z);
1682 z.Frobenius(z);
1683#else
1684 if (&z != this) {
1685 z.a_.a_ = a_.a_;
1686 }
1687 z.a_.a_ = a_.a_;
1688 Fp2::mul_Fp_0(z.a_.b_, a_.b_, Param::gammar2[1].a_);
1689 Fp2::mul_Fp_0(z.a_.c_, a_.c_, Param::gammar2[3].a_);
1690 Fp2::mul_Fp_0(z.b_.a_, b_.a_, Param::gammar2[0].a_);
1691 Fp2::mul_Fp_0(z.b_.b_, b_.b_, Param::gammar2[2].a_);
1692 Fp2::mul_Fp_0(z.b_.c_, b_.c_, Param::gammar2[4].a_);
1693#endif
1694 }
1695
1696 void Frobenius3(Fp12T& z) const
1697 {
1698#if 0
1699 Frobenius2(z);
1700 z.Frobenius(z);
1701#else
1702 z.a_.a_.a_ = a_.a_.a_;
1703 z.a_.b_.a_ = a_.b_.a_;
1704 z.a_.c_.a_ = a_.c_.a_;
1705 z.b_.a_.a_ = b_.a_.a_;
1706 z.b_.b_.a_ = b_.b_.a_;
1707 z.b_.c_.a_ = b_.c_.a_;
1708 Fp::neg(z.a_.a_.b_, a_.a_.b_);
1709 Fp::neg(z.a_.b_.b_, a_.b_.b_);
1710 Fp::neg(z.a_.c_.b_, a_.c_.b_);
1711 Fp::neg(z.b_.a_.b_, b_.a_.b_);
1712 Fp::neg(z.b_.b_.b_, b_.b_.b_);
1713 Fp::neg(z.b_.c_.b_, b_.c_.b_);
1714
1715#ifdef BN_SUPPORT_SNARK
1716 z.a_.b_ *= Param::gammar3[1];
1717 z.a_.c_ *= Param::gammar3[3];
1718#else
1719 z.a_.b_.mul_x();
1720 Fp2::mul_Fp_0(z.a_.c_, z.a_.c_, Param::gammar3[3].a_);
1721#endif
1722 z.b_.a_ *= Param::gammar3[0];
1723 z.b_.b_ *= Param::gammar3[2];
1724 z.b_.c_ *= Param::gammar3[4];
1725#endif
1726 }
1727
1728 /*
1729 @note destory *this
1730 */
1732 {
1733 // (a + b*i) -> ((a - b*i) * (a + b*i)^(-1))^(q^2+1)
1734 //
1735 // See Beuchat page 9: raising to 6-th power is the same as
1736 // conjugation, so this entire function computes
1737 // z^((p^6-1) * (p^2+1))
1738 z.a_ = a_;
1739 Fp6::neg(z.b_, b_);
1740 inverse();
1741 z *= *this;
1742 z.Frobenius2(*this);
1743 z *= *this;
1744 }
1745
1746 /*
1747 Final exponentiation based on:
1748 - Laura Fuentes-Casta{\~n}eda, Edward Knapp, and Francisco
1749 Rodr\'{\i}guez-Henr\'{\i}quez.
1750 Faster hashing to $\mathbb{G}_2$.
1751 SAC 2011, pp. 412--430. doi:10.1007/978-3-642-28496-0_25.
1752
1753 *this = final_exp(*this)
1754 */
1755#ifdef BN_SUPPORT_SNARK
1756 static void pow_neg_t(Fp12T &out, const Fp12T &in)
1757 {
1758 out = in;
1759 Fp12T inConj;
1760 inConj.a_ = in.a_;
1761 Fp6::neg(inConj.b_, in.b_); // in^-1 == in^(p^6)
1762
1763 for (size_t i = 1; i < Param::zReplTbl.size(); i++) {
1764 out.sqru();
1765 if (Param::zReplTbl[i] > 0) {
1766 Fp12T::mul(out, out, in);
1767 } else if (Param::zReplTbl[i] < 0) {
1768 Fp12T::mul(out, out, inConj);
1769 }
1770 }
1771 // invert by conjugation
1772 Fp6::neg(out.b_, out.b_);
1773 }
1774#endif
1775
1777 {
1778 Fp12T f, f2z, f6z, f6z2, f12z3;
1779 Fp12T a, b;
1780 Fp12T& z = *this;
1781 mapToCyclo(f);
1782
1783#ifdef BN_SUPPORT_SNARK
1784 Fp12T::pow_neg_t(f2z, f);
1785 f2z.sqru(); // f2z = f^(-2*z)
1786 f2z.sqru(f6z);
1787 f6z *= f2z; // f6z = f^(-6*z)
1788 Fp12T::pow_neg_t(f6z2, f6z);
1789 // A variable a is unnecessary only here.
1790 f6z2.sqru(a);
1791 // Compress::fixed_power(f12z3, a); // f12z3 = f^(-12*z^3)
1792 Fp12T::pow_neg_t(f12z3, a);
1793 // It will compute inversion of f2z, thus, conjugation free.
1794 Fp6::neg(f6z.b_, f6z.b_); // f6z = f^(6z)
1795 Fp6::neg(f12z3.b_, f12z3.b_); // f12z3 = f^(12*z^3)
1796 // Computes a and b.
1797 Fp12T::mul(a, f12z3, f6z2); // a = f^(12*z^3 + 6z^2)
1798 a *= f6z; // a = f^(12*z^3 + 6z^2 + 6z)
1799 Fp12T::mul(b, a, f2z); // b = f^(12*z^3 + 6z^2 + 4z)w
1800 // @note f2z, f6z, and f12z are unnecessary from here.
1801 // Last part.
1802 Fp12T::mul(z, a, f6z2); // z = f^(12*z^3 + 12z^2 + 6z)
1803 z *= f; // z = f^(12*z^3 + 12z^2 + 6z + 1)
1804 b.Frobenius(f2z); // f2z = f^(q(12*z^3 + 6z^2 + 4z))
1805 z *= f2z; // z = f^(q(12*z^3 + 6z^2 + 4z) + (12*z^3 + 12z^2 + 6z + 1))
1806 a.Frobenius2(f2z); // f2z = f^(q^2(12*z^3 + 6z^2 + 6z))
1807 z *= f2z; // z = f^(q^2(12*z^3 + 6z^2 + 6z) + q(12*z^3 + 6z^2 + 4z) + (12*z^3 + 12z^2 + 6z + 1))
1808 Fp6::neg(f.b_, f.b_); // f = -f
1809 b *= f; // b = f^(12*z^3 + 6z^2 + 4z - 1)
1810 b.Frobenius3(f2z); // f2z = f^(q^3(12*z^3 + 6z^2 + 4z - 1))
1811 z *= f2z;
1812 // z = f^(q^3(12*z^3 + 6z^2 + 4z - 1) +
1813 // q^2(12*z^3 + 6z^2 + 6z) +
1814 // q(12*z^3 + 6z^2 + 4z) +
1815 // (12*z^3 + 12z^2 + 6z + 1))
1816 // see page 6 in the "Faster hashing to G2" paper
1817#else
1818 // Hard part starts from here.
1819 // Computes addition chain.
1820 typedef CompressT<Fp2> Compress;
1822 f2z.sqru();
1823 f2z.sqru(f6z);
1824 f6z *= f2z;
1825 Compress::fixed_power(f6z2, f6z);
1826 // A variable a is unnecessary only here.
1827 f6z2.sqru(a);
1828 Compress::fixed_power(f12z3, a);
1829 // It will compute inversion of f2z, thus, conjugation free.
1830 Fp6::neg(f6z.b_, f6z.b_);
1831 Fp6::neg(f12z3.b_, f12z3.b_);
1832 // Computes a and b.
1833 Fp12T::mul(a, f12z3, f6z2);
1834 a *= f6z;
1835 Fp12T::mul(b, a, f2z);
1836 // @note f2z, f6z, and f12z are unnecessary from here.
1837 // Last part.
1838 Fp12T::mul(z, a, f6z2);
1839 z *= f;
1840 b.Frobenius(f2z);
1841 z *= f2z;
1842 a.Frobenius2(f2z);
1843 z *= f2z;
1844 Fp6::neg(f.b_, f.b_);
1845 b *= f;
1846 b.Frobenius3(f2z);
1847 z *= f2z;
1848#endif
1849 }
1850
1851 struct Dbl : public mie::local::addsubmul<Dbl, mie::local::hasNegative<Dbl> > {
1852 typedef typename Fp2::Dbl Fp2Dbl;
1853 typedef typename Fp6::Dbl Fp6Dbl;
1854 enum { SIZE = Fp6Dbl::SIZE * 2 };
1855
1857
1858 std::string toString(int base = 10) const
1859 {
1860 return ("[" + a_.toString(base) + ",\n" + b_.toString(base) + "]");
1861 }
1862 friend inline std::ostream& operator<<(std::ostream& os, const Dbl& x)
1863 {
1864 return os << x.toString();
1865 }
1866
1867 Dbl() { }
1868 Dbl(const Fp12T& x)
1869 : a_(x.a_)
1870 , b_(x.b_)
1871 {
1872 }
1873 Dbl(const Fp6& a, const Fp6& b)
1874 : a_(a)
1875 , b_(b)
1876 {
1877 }
1878 Dbl(const Fp6Dbl& a, const Fp6Dbl& b)
1879 : a_(a)
1880 , b_(b)
1881 {
1882 }
1883 Dbl(const std::string& a, const std::string& b)
1884 : a_(a)
1885 , b_(b)
1886 {
1887 }
1888
1889 void setDirect(const Fp6Dbl& a, const Fp6Dbl& b)
1890 {
1891 a_ = a;
1892 b_ = b;
1893 }
1894 Fp6Dbl* get() { return &a_; }
1895 const Fp6Dbl* get() const { return &a_; }
1896 bool isZero() const { return a_.isZero() && b_.isZero(); }
1897
1898 friend inline bool operator==(const Dbl& x, const Dbl& y)
1899 {
1900 return x.a_ == y.a_ && x.b_ == y.b_;
1901 }
1902 friend inline bool operator!=(const Dbl& x, const Dbl& y)
1903 {
1904 return ! (x == y);
1905 }
1906
1907 typedef void (uni_op)(Dbl&, const Dbl&);
1908 typedef void (bin_op)(Dbl&, const Dbl&, const Dbl&);
1909
1910 static void add(Dbl& z, const Dbl& x, const Dbl& y)
1911 {
1912 Fp6Dbl::add(z.a_, x.a_, y.a_);
1913 Fp6Dbl::add(z.b_, x.b_, y.b_);
1914 }
1915
1916 static void addNC(Dbl& z, const Dbl& x, const Dbl& y)
1917 {
1918 Fp6Dbl::addNC(z.a_, x.a_, y.a_);
1919 Fp6Dbl::addNC(z.b_, x.b_, y.b_);
1920 }
1921
1922 static void neg(Dbl& z, const Dbl& x)
1923 {
1924 Fp6Dbl::neg(z.a_, x.a_);
1925 Fp6Dbl::neg(z.b_, x.b_);
1926 }
1927
1928 static void sub(Dbl& z, const Dbl& x, const Dbl& y)
1929 {
1930 Fp6Dbl::sub(z.a_, x.a_, y.a_);
1931 Fp6Dbl::sub(z.b_, x.b_, y.b_);
1932 }
1933
1934 static void subNC(Dbl& z, const Dbl& x, const Dbl& y)
1935 {
1936 Fp6Dbl::subNC(z.a_, x.a_, y.a_);
1937 Fp6Dbl::subNC(z.b_, x.b_, y.b_);
1938 }
1939
1940 /*
1941 z *= x,
1942 position: 0 1 2 3 4 5
1943 x = (l00, 0, l02) + (0, l11, 0)*w
1944 x is represented as:
1945 (x.a_, x.b_, x.c_) = (l00, l11, l02)
1946 4800clk * 66
1947 */
1948 /*
1949 Operation Count:
1950
1951 13 * Fp2Dbl::mulOpt2
1952 6 * Fp2Dbl::mod
1953 10 * Fp2::add/sub
1954 19 * Fp2Dbl::add/sub == 19 * (2 * Fp2::add/sub) == 38 * Fp2::add/sub
1955 4 * Fp2Dbl::mul_xi == 4 * (2 * Fp2::add/sub) == 8 * Fp2::add/sub
1956
1957 Total:
1958
1959 13 * Fp2Dbl::mulOpt2
1960 6 * Fp2Dbl::mod
1961 56 * Fp2::add/sub
1962 */
1963 static void (*mul_Fp2_024)(Fp12T& z, const Fp6& x);
1964 static void mul_Fp2_024C(Fp12T& z, const Fp6& x)
1965 {
1966 Fp2& z0 = z.a_.a_;
1967 Fp2& z1 = z.a_.b_;
1968 Fp2& z2 = z.a_.c_;
1969 Fp2& z3 = z.b_.a_;
1970 Fp2& z4 = z.b_.b_;
1971 Fp2& z5 = z.b_.c_;
1972 const Fp2& x0 = x.a_;
1973 const Fp2& x2 = x.c_;
1974 const Fp2& x4 = x.b_;
1975 Fp2 t0, t1, t2;
1976 Fp2 s0;
1977 Fp2Dbl T3, T4;
1978 Fp2Dbl D0, D2, D4;
1979 Fp2Dbl S1;
1980 Fp2Dbl::mulOpt2(D0, z0, x0);
1981 Fp2Dbl::mulOpt2(D2, z2, x2);
1982 Fp2Dbl::mulOpt2(D4, z4, x4);
1983 Fp2::add(t2, z0, z4);
1984 Fp2::add(t1, z0, z2);
1985 Fp2::add(s0, z1, z3);
1986 s0 += z5;
1987 // For z.a_.a_ = z0.
1988 Fp2Dbl::mulOpt2(S1, z1, x2);
1989 Fp2Dbl::add(T3, S1, D4);
1990 Fp2Dbl::mul_xi(T4, T3);
1991 T4 += D0;
1992 Fp2Dbl::mod(z0, T4);
1993 // For z.a_.b_ = z1.
1994 Fp2Dbl::mulOpt2(T3, z5, x4);
1995 S1 += T3;
1996 T3 += D2;
1997 Fp2Dbl::mul_xi(T4, T3);
1998 Fp2Dbl::mulOpt2(T3, z1, x0);
1999 S1 += T3;
2000 T4 += T3;
2001 Fp2Dbl::mod(z1, T4);
2002 // For z.a_.c_ = z2.
2003 Fp2::add(t0, x0, x2);
2004 Fp2Dbl::mulOpt2(T3, t1, t0);
2005 T3 -= D0;
2006 T3 -= D2;
2007 Fp2Dbl::mulOpt2(T4, z3, x4);
2008 S1 += T4;
2009 T3 += T4;
2010 // z3 needs z2.
2011 // For z.b_.a_ = z3.
2012 Fp2::add(t0, z2, z4);
2013 Fp2Dbl::mod(z2, T3);
2014 Fp2::add(t1, x2, x4);
2015 Fp2Dbl::mulOpt2(T3, t0, t1);
2016 T3 -= D2;
2017 T3 -= D4;
2018 Fp2Dbl::mul_xi(T4, T3);
2019 Fp2Dbl::mulOpt2(T3, z3, x0);
2020 S1 += T3;
2021 T4 += T3;
2022 Fp2Dbl::mod(z3, T4);
2023 // For z.b_.b_ = z4.
2024 Fp2Dbl::mulOpt2(T3, z5, x2);
2025 S1 += T3;
2026 Fp2Dbl::mul_xi(T4, T3);
2027 Fp2::add(t0, x0, x4);
2028 Fp2Dbl::mulOpt2(T3, t2, t0);
2029 T3 -= D0;
2030 T3 -= D4;
2031 T4 += T3;
2032 Fp2Dbl::mod(z4, T4);
2033 // For z.b_.c_ = z5.
2034 Fp2::add(t0, x0, x2);
2035 t0 += x4;
2036 Fp2Dbl::mulOpt2(T3, s0, t0);
2037 T3 -= S1;
2038 Fp2Dbl::mod(z5, T3);
2039 }
2040
2041 /*
2042 z = cv2 * cv3,
2043 position:0 1 2 3 4 5
2044 cv2 = (l00, 0, l02) + (0, l11, 0)*w
2045 cv3 = (l00, 0, l02) + (0, l11, 0)*w
2046 these are represented as:
2047 (cv*.a_, cv*.b_, cv*.c_) = (l00, l11, l02)
2048 */
2049 /*
2050 Operation Count:
2051
2052 6 * Fp2Dbl::mulOpt2
2053 5 * Fp2Dbl::mod
2054 6 * Fp2::add/sub
2055 7 * Fp2Dbl::add/sub == 7 * (2 * Fp2::add/sub) == 14 * Fp2::add/sub
2056 3 * Fp2Dbl::mul_xi == 3 * (2 * Fp2::add/sub) == 6 * Fp2::add/sub
2057
2058 Total:
2059
2060 6 * Fp2Dbl::mulOpt2
2061 5 * Fp2Dbl::mod
2062 26 * Fp2::add/sub
2063 call:2
2064 */
2065 static void mul_Fp2_024_Fp2_024(Fp12T& z, const Fp6& cv2, const Fp6& cv3)
2066 {
2067 Fp2& z0 = z.a_.a_;
2068 Fp2& z1 = z.a_.b_;
2069 Fp2& z2 = z.a_.c_;
2070 Fp2& z3 = z.b_.a_;
2071 Fp2& z4 = z.b_.b_;
2072 Fp2& z5 = z.b_.c_;
2073 const Fp2& x0 = cv2.a_;
2074 const Fp2& x2 = cv2.c_;
2075 const Fp2& x4 = cv2.b_;
2076 const Fp2& y0 = cv3.a_;
2077 const Fp2& y2 = cv3.c_;
2078 const Fp2& y4 = cv3.b_;
2079 Fp2Dbl T00, T22, T44, T02, T24, T40;
2080 Fp2Dbl::mulOpt2(T00, x0, y0);
2081 Fp2Dbl::mulOpt2(T22, x2, y2);
2082 Fp2Dbl::mulOpt2(T44, x4, y4);
2083 Fp2::add(z0, x0, x2);
2084 Fp2::add(z1, y0, y2);
2085 Fp2Dbl::mulOpt2(T02, z0, z1);
2086 T02 -= T00;
2087 T02 -= T22;
2088 Fp2Dbl::mod(z2, T02);
2089 Fp2::add(z0, x2, x4);
2090 Fp2::add(z1, y2, y4);
2091 Fp2Dbl::mulOpt2(T24, z0, z1);
2092 T24 -= T22;
2093 T24 -= T44;
2094 Fp2Dbl::mul_xi(T02, T24);
2095 Fp2Dbl::mod(z3, T02);
2096 Fp2::add(z0, x4, x0);
2097 Fp2::add(z1, y4, y0);
2098 Fp2Dbl::mulOpt2(T40, z0, z1);
2099 T40 -= T00;
2100 T40 -= T44;
2101 Fp2Dbl::mod(z4, T40);
2102 Fp2Dbl::mul_xi(T02, T22);
2103 Fp2Dbl::mod(z1, T02);
2104 Fp2Dbl::mul_xi(T02, T44);
2105 T02 += T00;
2106 Fp2Dbl::mod(z0, T02);
2107 z5.clear();
2108 }
2109
2110 static void mod(Fp12T& z, Dbl& x)
2111 {
2112 Fp6Dbl::mod(z.a_, x.a_);
2113 Fp6Dbl::mod(z.b_, x.b_);
2114 }
2115 };
2116};
2117
2118template<class Fp6>
2120
2121template<class Fp6>
2123
2124template<class Fp6>
2125void (*Fp12T<Fp6>::mul)(Fp12T& z, const Fp12T& x, const Fp12T& y) = &(Fp12T<Fp6>::mulC);
2126
2127template<class T>
2129 typedef T Fp2;
2130 typedef typename Fp2::Fp Fp;
2132 typedef typename Fp2::Dbl Fp2Dbl;
2135 enum { N = 4 };
2136
2137 Fp12& z_; // must be top for asm !!!
2143
2144 // z is output area
2145 CompressT(Fp12& z, const Fp12& x)
2146 : z_(z)
2147 , g1_(z.getFp2()[4])
2148 , g2_(z.getFp2()[3])
2149 , g3_(z.getFp2()[2])
2150 , g4_(z.getFp2()[1])
2151 , g5_(z.getFp2()[5])
2152 {
2153 g2_ = x.getFp2()[3];
2154 g3_ = x.getFp2()[2];
2155 g4_ = x.getFp2()[1];
2156 g5_ = x.getFp2()[5];
2157 }
2159 : z_(z)
2160 , g1_(z.getFp2()[4])
2161 , g2_(z.getFp2()[3])
2162 , g3_(z.getFp2()[2])
2163 , g4_(z.getFp2()[1])
2164 , g5_(z.getFp2()[5])
2165 {
2166 g2_ = c.g2_;
2167 g3_ = c.g3_;
2168 g4_ = c.g4_;
2169 g5_ = c.g5_;
2170 }
2171
2172 friend std::ostream& operator<<(std::ostream& os, const CompressT& x)
2173 {
2174 os << "C[" << x.g2_ << ",\n" << x.g3_ << ",\n" << x.g4_ << ",\n" << x.g5_ << ",\n" << "]";
2175 return os;
2176 }
2177
2178private:
2179 void decompressBeforeInv(Fp2& nume, Fp2& denomi) const
2180 {
2181 assert(&nume != &denomi);
2182
2183 if (g2_.isZero()) {
2184 Fp2::add(nume, g4_, g4_);
2185 nume *= g5_;
2186 denomi = g3_;
2187 } else {
2188 Fp2 t;
2189 Fp2::square(nume, g5_);
2190 Fp2::mul_xi(denomi, nume);
2191 Fp2::square(nume, g4_);
2192 Fp2::sub(t, nume, g3_);
2193 t += t;
2194 t += nume;
2195 Fp2::add(nume, denomi, t);
2196 Fp2::divBy4(nume, nume);
2197 denomi = g2_;
2198 }
2199 }
2200
2201 // output to z
2202 void decompressAfterInv()
2203 {
2204 Fp2& g0 = z_.getFp2()[0];
2205 Fp2 t0, t1;
2206 // Compute g0.
2207 Fp2::square(t0, g1_);
2208 Fp2::mul(t1, g3_, g4_);
2209 t0 -= t1;
2210 t0 += t0;
2211 t0 -= t1;
2212 Fp2::mul(t1, g2_, g5_);
2213 t0 += t1;
2214 Fp2::mul_xi(g0, t0);
2215 g0.a_ += Param::i1;
2216 }
2217
2218public:
2219 // not used
2221 {
2222 Fp2 nume, denomi;
2223 decompressBeforeInv(nume, denomi);
2224 denomi.inverse();
2225 g1_ = nume * denomi; // g1 is recoverd.
2226 decompressAfterInv();
2227 }
2228
2229 /*
2230 2275clk * 186 = 423Kclk QQQ
2231 */
2232 static void squareC(CompressT& z)
2233 {
2234 Fp2 t0, t1, t2;
2235 Fp2Dbl T0, T1, T2, T3;
2236 Fp2Dbl::square(T0, z.g4_);
2237 Fp2Dbl::square(T1, z.g5_);
2238 // # 7
2239 Fp2Dbl::mul_xi(T2, T1);
2240 // # 8
2241 T2 += T0;
2242 // # 9
2243 Fp2Dbl::mod(t2, T2);
2244 // # 1
2245 Fp2::add(t0, z.g4_, z.g5_);
2246 Fp2Dbl::square(T2, t0);
2247 // # 2
2248 T0 += T1;
2249// Fp2Dbl::addNC(T0, T0, T1); // QQQ : OK?
2250 T2 -= T0;
2251 // # 3
2252 Fp2Dbl::mod(t0, T2);
2253 Fp2::add(t1, z.g2_, z.g3_);
2254 Fp2Dbl::square(T3, t1);
2255 Fp2Dbl::square(T2, z.g2_);
2256 // # 4
2257 Fp2::mul_xi(t1, t0);
2258#if 1 // RRR
2259 Fp::_3z_add_2xC(z.g2_.a_, t1.a_);
2260 Fp::_3z_add_2xC(z.g2_.b_, t1.b_);
2261#else
2262 // # 5
2263 z.g2_ += t1;
2264 z.g2_ += z.g2_;
2265 // # 6
2266 z.g2_ += t1;
2267#endif
2268 Fp2::sub(t1, t2, z.g3_);
2269 t1 += t1;
2270 // # 11 !!!!
2271 Fp2Dbl::square(T1, z.g3_);
2272 // # 10 !!!!
2273 Fp2::add(z.g3_, t1, t2);
2274 // # 12
2275 Fp2Dbl::mul_xi(T0, T1);
2276 // # 13
2277 T0 += T2;
2278// Fp2Dbl::addNC(T0, T0, T2); // QQQ : OK?
2279 // # 14
2280 Fp2Dbl::mod(t0, T0);
2281 Fp2::sub(z.g4_, t0, z.g4_);
2282 z.g4_ += z.g4_;
2283 // # 15
2284 z.g4_ += t0;
2285 // # 16
2286 Fp2Dbl::addNC(T2, T2, T1);
2287 T3 -= T2;
2288 // # 17
2289 Fp2Dbl::mod(t0, T3);
2290#if 1 // RRR
2291 Fp::_3z_add_2xC(z.g5_.a_, t0.a_);
2292 Fp::_3z_add_2xC(z.g5_.b_, t0.b_);
2293#else
2294 z.g5_ += t0;
2295 z.g5_ += z.g5_;
2296 z.g5_ += t0; // # 18
2297#endif
2298 }
2299 static void square_nC(CompressT& z, int n)
2300 {
2301 for (int i = 0; i < n; i++) {
2302 squareC(z);
2303 }
2304 }
2305
2306 /*
2307 Exponentiation over compression for:
2308 z = x^Param::z.abs()
2309 */
2310 static void fixed_power(Fp12& z, const Fp12& x)
2311 {
2312#if 0
2313 z = power(x, Param::z.abs());
2314#else
2315 assert(&z != &x);
2316 Fp12 d62;
2317 Fp2 c55nume, c55denomi, c62nume, c62denomi;
2318 CompressT c55(z, x);
2319 CompressT::square_n(c55, 55); // 106k
2320 c55.decompressBeforeInv(c55nume, c55denomi);
2321 CompressT c62(d62, c55);
2322 CompressT::square_n(c62, 62 - 55); // 13.6k
2323 c62.decompressBeforeInv(c62nume, c62denomi);
2324 Fp2 acc;
2325 Fp2::mul(acc, c55denomi, c62denomi);
2326 acc.inverse();
2327 Fp2 t;
2328 Fp2::mul(t, acc, c62denomi);
2329 Fp2::mul(c55.g1_, c55nume, t);
2330 c55.decompressAfterInv(); // 1.1k
2331 Fp2::mul(t, acc, c55denomi);
2332 Fp2::mul(c62.g1_, c62nume, t);
2333 c62.decompressAfterInv();
2334 z *= x; // 6.5k
2335 z *= d62;
2336#endif
2337 }
2338 static void (*square_n)(CompressT& z, int n);
2339private:
2340 CompressT(const CompressT&);
2341 void operator=(const CompressT&);
2342};
2343
2344template<class Fp2>
2346
2347namespace ecop {
2348
2349template<class FF>
2350inline void copy(FF* out, const FF* in)
2351{
2352 out[0] = in[0];
2353 out[1] = in[1];
2354 out[2] = in[2];
2355}
2356
2357/*
2358 @memo Jacobian coordinates: Y^2 = X^3 + b*Z^6
2359*/
2360template<class Fp>
2361inline bool isOnECJac3(const Fp* P)
2362{
2363 typedef Fp2T<Fp> Fp2;
2364 typedef ParamT<Fp2> Param;
2365 if (P[2] == 0) return true;
2366
2367 Fp Z6p_2;
2368 Fp::square(Z6p_2, P[2]);
2369 Fp::mul(Z6p_2, Z6p_2, P[2]);
2370 Fp::square(Z6p_2, Z6p_2);
2371 Z6p_2 *= Param::b;
2372 return P[1] * P[1] == P[0] * P[0] * P[0] + Z6p_2;
2373}
2374
2375/*
2376 @memo Y^2=X^3+b
2377 Homogeneous.
2378*/
2379template<class Fp>
2380inline bool isOnECHom2(const Fp* P)
2381{
2382 typedef Fp2T<Fp> Fp2;
2383 typedef ParamT<Fp2> Param;
2384 return P[1] * P[1] == P[0] * P[0] * P[0] + Param::b;
2385}
2386
2387/*
2388 @memo Y^2=X^3+b
2389 Homogeneous.
2390*/
2391template<class Fp>
2392inline bool isOnECHom3(const Fp* P)
2393{
2394 typedef Fp2T<Fp> Fp2;
2395 typedef ParamT<Fp2> Param;
2396 if (P[2] == 0) return true;
2397
2398 Fp ZZZ;
2399 Fp::square(ZZZ, P[2]);
2400 Fp::mul(ZZZ, ZZZ, P[2]);
2401 ZZZ *= Param::b;
2402 return P[1] * P[1] * P[2] == P[0] * P[0] * P[0] + ZZZ;
2403}
2404
2405/*
2406 @memo Y^2=X^3+b/xi
2407*/
2408template<class Fp>
2409inline bool isOnTwistECJac3(const Fp2T<Fp>* P)
2410{
2411 typedef Fp2T<Fp> Fp2;
2412 typedef ParamT<Fp2> Param;
2413
2414 if (P[2] == 0) return true;
2415 Fp2 Z6p;
2416 Fp2::square(Z6p, P[2]);
2417 Fp2::mul(Z6p, Z6p, P[2]);
2418 Fp2::square(Z6p, Z6p);
2419 return P[1] * P[1] == P[0] * P[0] * P[0] + Param::b_invxi * Z6p;
2420}
2421
2422/*
2423 @memo Y^2=X^3+b/xi
2424 Homogeneous.
2425*/
2426template<class Fp>
2427inline bool isOnTwistECHom2(const Fp2T<Fp>* P)
2428{
2429 typedef Fp2T<Fp> Fp2;
2430 typedef ParamT<Fp2> Param;
2431 return P[1] * P[1] == (P[0] * P[0] * P[0] + Param::b_invxi);
2432}
2433
2434/*
2435 @memo Y^2=X^3+b/xi
2436 Homogeneous.
2437*/
2438template<class Fp>
2439inline bool isOnTwistECHom3(const Fp2T<Fp>* P)
2440{
2441 typedef Fp2T<Fp> Fp2;
2442 typedef ParamT<Fp2> Param;
2443 if (P[2] == 0) return true;
2444 return P[1] * P[1] * P[2] == (P[0] * P[0] * P[0] + Param::b_invxi * P[2] * P[2] * P[2]);
2445}
2446
2447/*
2448 For Jacobian coordinates
2449*/
2450template<class FF>
2451inline void NormalizeJac(FF* out, const FF* in)
2452{
2453 if (in[2] == 0) {
2454 out[0].clear();
2455 out[1].clear();
2456 out[2].clear();
2457 } else if (in[2] == 1) {
2458 copy(out, in);
2459 } else {
2460 FF A, AA, t0;
2461 A = in[2];
2462 A.inverse();
2463 FF::square(AA, A);
2464 FF::mul(out[0], in[0], AA);
2465 FF::mul(t0, AA, A);
2466 FF::mul(out[1], in[1], t0);
2467 out[2] = 1;
2468 }
2469}
2470
2471/*
2472 For Homogeneous
2473*/
2474template<class FF>
2475inline void NormalizeHom(FF* out, const FF* in)
2476{
2477 if (in[2] == 0) {
2478 out[0].clear();
2479 out[1].clear();
2480 out[2].clear();
2481 } else if (in[2] == 1) {
2482 copy(out, in);
2483 } else {
2484 FF A = in[2];
2485 A.inverse();
2486 FF::mul(out[0], in[0], A);
2487 FF::mul(out[1], in[1], A);
2488 out[2] = 1;
2489 }
2490}
2491
2492/*
2493 Jacobi coordinate
2494 (out[0], out[1], out[2]) = 2(in[0], in[1], in[2])
2495*/
2496template<class FF>
2497inline void ECDouble(FF* out, const FF* in)
2498{
2499 FF A, B, C, D, E, F, t0, t1, t2, t3, t4, t5, t6, t7, t8;
2500 FF::square(A, in[0]);
2501 FF::square(B, in[1]);
2502 FF::square(C, B);
2503 FF::add(t0, in[0], B);
2504 FF::square(t1, t0);
2505 FF::sub(t2, t1, A);
2506 FF::sub(t3, t2, C);
2507 FF::add(D, t3, t3);
2508 FF::add(E, A, A);
2509 FF::add(E, E, A);
2510 FF::square(F, E);
2511 FF::add(t4, D, D);
2512 FF::sub(out[0], F, t4);
2513 FF::sub(t5, D, out[0]);
2514 t6 = C; t6 += t6; t6 += t6; t6 += t6; // t6 = 8*C
2515 FF::mul(t7, E, t5);
2516 FF::mul(t8, in[1], in[2]);
2517 FF::sub(out[1], t7, t6);
2518 FF::add(out[2], t8, t8);
2519}
2520
2521/*
2522 Jacobi coordinate
2523 (out[0], out[1], out[2]) = (a[0], a[1], a[2]) + (b[0], b[1], b[2])
2524*/
2525template<class FF>
2526inline void ECAdd(FF* out, const FF* a, const FF* b)
2527{
2528 if (a[2].isZero()) {
2529 copy(out, b);
2530 return;
2531 }
2532 if (b[2].isZero()) {
2533 copy(out, a);
2534 return;
2535 }
2536 FF Z1Z1, Z2Z2, U1, U2, t0, S1, t1, S2, H, t2, I, J, t3, r, V, t4, t5;
2537 FF t6, t7, t8, t9, t10, t11, t12, t13, t14;
2538 FF::square(Z1Z1, a[2]);
2539 FF::square(Z2Z2, b[2]);
2540 FF::mul(U1, a[0], Z2Z2);
2541 FF::mul(U2, b[0], Z1Z1);
2542 FF::mul(t0, b[2], Z2Z2);
2543 FF::mul(S1, a[1], t0);
2544 FF::mul(t1, a[2], Z1Z1);
2545 FF::mul(S2, b[1], t1);
2546 FF::sub(H, U2, U1);
2547 FF::sub(t3, S2, S1);
2548
2549 if (H.isZero()) {
2550 if (t3.isZero()) {
2551 ECDouble(out, a);
2552 } else {
2553 out[2].clear();
2554 }
2555 return;
2556 }
2557
2558 FF::add(t2, H, H);
2559 FF::square(I, t2);
2560 FF::mul(J, H, I);
2561 FF::add(r, t3, t3);
2562 FF::mul(V, U1, I);
2563 FF::square(t4, r);
2564 FF::add(t5, V, V);
2565 FF::sub(t6, t4, J);
2566 FF::sub(out[0], t6, t5);
2567 FF::sub(t7, V, out[0]);
2568 FF::mul(t8, S1, J);
2569 FF::add(t9, t8, t8);
2570 FF::mul(t10, r, t7);
2571 FF::sub(out[1], t10, t9);
2572 FF::add(t11, a[2], b[2]);
2573 FF::square(t12, t11);
2574 FF::sub(t13, t12, Z1Z1);
2575 FF::sub(t14, t13, Z2Z2);
2576 FF::mul(out[2], t14, H);
2577}
2578
2579/*
2580 out = in * m
2581 @param out [out] Jacobi coord (out[0], out[1], out[2])
2582 @param in [in] Jacobi coord (in[0], in[1], in[2])
2583 @param m [in] scalar
2584 @note MSB first binary method.
2585
2586 @note don't use Fp as INT
2587 the inner format of Fp is not compatible with mie::Vuint
2588*/
2589template<class FF, class INT>
2590inline void ScalarMult(FF* out, const FF* in, const INT& m)
2591{
2592 typedef typename mie::util::IntTag<INT> Tag;
2593 typedef typename Tag::value_type value_type;
2594
2595 if (m == 0) {
2596 out[0].clear();
2597 out[1].clear();
2598 out[2].clear();
2599 return;
2600 }
2601 FF inCopy[3];
2602 if (out == in) {
2603 ecop::copy(inCopy, in);
2604 in = inCopy;
2605 }
2606
2607 const int mSize = (int)Tag::getBlockSize(m);
2608 const int vSize = (int)sizeof(value_type) * 8;
2609 const value_type mask = value_type(1) << (vSize - 1);
2610 assert(mSize > 0); // if mSize == 0, it had been returned.
2611 /*
2612 Extract and process for MSB of most significant word.
2613 */
2614 value_type v = Tag::getBlock(m, mSize - 1);
2615 int j = 0;
2616
2617 while ((v != 0) && (!(v & mask))) {
2618 v <<= 1;
2619 ++j;
2620 }
2621
2622 v <<= 1;
2623 ++j;
2624 ecop::copy(out, in);
2625 /*
2626 Process for most significant word.
2627 */
2628 for (; j != vSize; ++j, v <<= 1) {
2629 ECDouble(out, out);
2630 if (v & mask) {
2631 ECAdd(out, out, in);
2632 }
2633 }
2634
2635 /*
2636 Process for non most significant words.
2637 */
2638 for (int i = mSize - 2; i >= 0; --i) {
2639 v = Tag::getBlock(m, i);
2640 for (j = 0; j != vSize; ++j, v <<= 1) {
2641 ECDouble(out, out);
2642 if (v & mask) {
2643 ECAdd(out, out, in);
2644 }
2645 }
2646 }
2647}
2648
2649template<class Fp>
2651{
2652 typedef Fp2T<Fp> Fp2;
2653 typedef ParamT<Fp2> Param;
2654 // applying Q[0] <- P[0]^q
2655#ifdef BN_SUPPORT_SNARK
2656 Q[0].a_ = P[0].a_;
2657 Fp::neg(Q[0].b_, P[0].b_);
2658
2659 // Q[0] *= xi^((p-1)/3)
2660 Q[0] *= Param::gammar[1];
2661
2662 // applying Q[1] <- P[1]^q
2663 Q[1].a_ = P[1].a_;
2664 Fp::neg(Q[1].b_, P[1].b_);
2665
2666 // Q[1] *= xi^((p-1)/2)
2667 Q[1] *= Param::gammar[2];
2668#else
2669 Q[0].a_ = P[0].a_;
2670 Fp::neg(Q[0].b_, P[0].b_);
2671 Fp2::mul_Fp_1(Q[0], Param::W2p.b_);
2672 Q[1].a_ = P[1].a_;
2673 Fp::neg(Q[1].b_, P[1].b_);
2674 Q[1] *= Param::W3p;
2675#endif
2676}
2677
2678template<class Fp>
2680{
2681#ifdef BN_SUPPORT_SNARK
2682 Fp2T<Fp> scratch[2];
2683 FrobEndOnTwist_1(scratch, P);
2684 FrobEndOnTwist_1(Q, scratch);
2685#else
2686 typedef Fp2T<Fp> Fp2;
2687 typedef ParamT<Fp2> Param;
2688 Fp2::mul_Fp_0(Q[0], P[0], Param::Z);
2689 Fp2::neg(Q[1], P[1]);
2690#endif
2691}
2692
2693template<class Fp>
2695{
2696#ifdef BN_SUPPORT_SNARK
2697 Fp2T<Fp> scratch2[2], scratch4[2], scratch6[2];
2698 FrobEndOnTwist_2(scratch2, P);
2699 FrobEndOnTwist_2(scratch4, scratch2);
2700 FrobEndOnTwist_2(scratch6, scratch4);
2701 FrobEndOnTwist_2(Q, scratch6);
2702#else
2703 typedef Fp2T<Fp> Fp2;
2704 typedef ParamT<Fp2> Param;
2705 Fp2::mul_Fp_0(Q[0], P[0], Param::Z);
2706 Q[1] = P[1];
2707#endif
2708}
2709
2710} // namespace ecop
2711
2712/*
2713 calc optimal ate pairing
2714 @param f [out] e(Q, P)
2715 @param Q [in] affine coord. (Q[0], Q[1])
2716 @param P [in] affine coord. (P[0], P[1])
2717 @note not defined for infinity point
2718*/
2719template<class Fp>
2720void opt_atePairing(Fp12T<Fp6T<Fp2T<Fp> > >& f, const Fp2T<Fp> Q[2], const Fp P[2])
2721{
2722 typedef Fp2T<Fp> Fp2;
2723 typedef ParamT<Fp2> Param;
2724 typedef Fp6T<Fp2> Fp6;
2725 typedef Fp12T<Fp6> Fp12;
2726 Fp2 T[3];
2727 T[0] = Q[0];
2728 T[1] = Q[1];
2729 T[2] = Fp2(1);
2730 Fp2 Qneg[2];
2731 if (Param::useNAF) {
2732 Qneg[0] = Q[0];
2733 Fp2::neg(Qneg[1], Q[1]);
2734 }
2735 // at 1.
2736 Fp6 d;
2738 Fp6 e;
2739 assert(Param::siTbl[1] == 1);
2740 Fp6::pointAddLineEval(e, T, Q, P);
2741 Fp12::Dbl::mul_Fp2_024_Fp2_024(f, d, e);
2742 // loop from 2.
2743 Fp6 l;
2744 // 844kclk
2745 for (size_t i = 2; i < Param::siTbl.size(); i++) {
2746 // 3.6k x 63
2748 // 4.7k x 63
2749 Fp12::square(f);
2750 // 4.48k x 63
2751 Fp12::Dbl::mul_Fp2_024(f, l);
2752
2753 if (Param::siTbl[i] > 0) {
2754 // 9.8k x 3
2755 // 5.1k
2756 Fp6::pointAddLineEval(l, T, Q, P);
2757 Fp12::Dbl::mul_Fp2_024(f, l);
2758 }
2759 else if (Param::siTbl[i] < 0) {
2760 Fp6::pointAddLineEval(l, T, Qneg, P);
2761 Fp12::Dbl::mul_Fp2_024(f, l);
2762 }
2763 }
2764
2765 // addition step
2766 Fp2 Q1[2];
2768 Fp2 Q2[2];
2769#ifdef BN_SUPPORT_SNARK
2771 Fp2::neg(Q2[1], Q2[1]);
2772#else
2774 // @memo z < 0
2775 Fp6::neg(f.b_, f.b_);
2776 Fp2::neg(T[1], T[1]);
2777#endif
2778 Fp12 ft;
2779 Fp6::pointAddLineEval(d, T, Q1, P); // 5k
2780 Fp6::pointAddLineEval(e, T, Q2, P); // 5k
2781 Fp12::Dbl::mul_Fp2_024_Fp2_024(ft, d, e); // 2.7k
2782 Fp12::mul(f, f, ft); // 6.4k
2783 // final exponentiation
2784 f.final_exp();
2785}
2786
2787/*
2788 opt_atePairingJac is a wrapper function of opt_atePairing
2789 @param f [out] e(Q, P)
2790 @param Q [in] Jacobi coord. (_Q[0], _Q[1], _Q[2])
2791 @param _P [in] Jacobi coord. (_P[0], _P[1], _P[2])
2792 output : e(Q, P)
2793*/
2794template<class Fp>
2795void opt_atePairingJac(Fp12T<Fp6T<Fp2T<Fp> > >& f, const Fp2T<Fp> _Q[3], const Fp _P[3])
2796{
2797 if (_Q[2] == 0 || _P[2] == 0) {
2798 f = 1;
2799 return;
2800 }
2801
2802 Fp2T<Fp> Q[3];
2803 Fp P[3];
2804 ecop::NormalizeJac(Q, _Q);
2805 ecop::NormalizeJac(P, _P);
2806 opt_atePairing(f, Q, P);
2807}
2808
2809#ifdef _MSC_VER
2810 #pragma warning(push)
2811 #pragma warning(disable : 4127) /* const condition */
2812#endif
2813
2814template<class T>
2815class EcT {
2816public:
2817 mutable T p[3];
2818 EcT() {}
2819 EcT(const T& x, const T& y, bool verify = true)
2820 {
2821 set(x, y, verify);
2822 }
2823 EcT(const T& x, const T& y, const T& z, bool verify = true)
2824 {
2825 set(x, y, z, verify);
2826 }
2827 void normalize() const
2828 {
2829 if (isZero() || p[2] == 1) return;
2830 T r;
2831 r = p[2];
2832 r.inverse();
2833 T::square(p[2], r);
2834 p[0] *= p[2];
2835 r *= p[2];
2836 p[1] *= r;
2837 p[2] = 1;
2838 }
2839
2840 bool isValid() const;
2841
2842 void set(const T& x, const T& y, bool verify = true)
2843 {
2844 p[0] = x;
2845 p[1] = y;
2846 p[2] = 1;
2847 if (verify && !isValid()) {
2848 throw std::runtime_error("set(x, y) : bad point");
2849 }
2850 }
2851 void set(const T& x, const T& y, const T& z, bool verify = true)
2852 {
2853 p[0] = x;
2854 p[1] = y;
2855 p[2] = z;
2856 if (verify && !isValid()) {
2857 throw std::runtime_error("set(x, y, z) : bad point");
2858 }
2859 }
2860 void clear()
2861 {
2862 p[0].clear();
2863 p[1].clear();
2864 p[2].clear();
2865 }
2866
2867 static inline void dbl(EcT& R, const EcT& P)
2868 {
2869 ecop::ECDouble(R.p, P.p);
2870 }
2871 static inline void add(EcT& R, const EcT& P, const EcT& Q)
2872 {
2873 ecop::ECAdd(R.p, P.p, Q.p);
2874 }
2875 static inline void sub(EcT& R, const EcT& P, const EcT& Q)
2876 {
2877 EcT negQ;
2878 neg(negQ, Q);
2879 add(R, P, negQ);
2880 }
2881 static inline void neg(EcT& R, const EcT& P)
2882 {
2883 R.p[0] = P.p[0];
2884 T::neg(R.p[1], P.p[1]);
2885 R.p[2] = P.p[2];
2886 }
2887 template<class N>
2888 static inline void mul(EcT& R, const EcT& P, const N& y)
2889 {
2890 ecop::ScalarMult(R.p, P.p, y);
2891 }
2892 template<class N>
2893 EcT& operator*=(const N& y) { mul(*this, *this, y); return *this; }
2894 template<class N>
2895 EcT operator*(const N& y) const { EcT c; mul(c, *this, y); return c; }
2896 bool operator==(const EcT& rhs) const
2897 {
2898 normalize();
2899 rhs.normalize();
2900 if (isZero()) {
2901 if (rhs.isZero()) return true;
2902 return false;
2903 }
2904 if (rhs.isZero()) return false;
2905 return p[0] == rhs.p[0] && p[1] == rhs.p[1];
2906 }
2907 bool operator!=(const EcT& rhs) const
2908 {
2909 return !operator==(rhs);
2910 }
2911 bool isZero() const
2912 {
2913 return p[2].isZero();
2914 }
2915 friend inline std::ostream& operator<<(std::ostream& os, const EcT& self)
2916 {
2917 if (self.isZero()) {
2918 return os << '0';
2919 } else {
2920 self.normalize();
2921 return os << self.p[0].toString(16) << '_' << self.p[1].toString(16);
2922 }
2923 }
2924 friend inline std::istream& operator>>(std::istream& is, EcT& self)
2925 {
2926 std::string str;
2927 is >> str;
2928 if (str == "0") {
2929 self.clear();
2930 } else {
2931 self.p[2] = 1;
2932 size_t pos = str.find('_');
2933 if (pos == std::string::npos) {
2934 throw std::runtime_error("operator>>:bad format");
2935 }
2936 str[pos] = '\0';
2937 self.p[0].set(&str[0]);
2938 self.p[1].set(&str[pos + 1]);
2939 }
2940 return is;
2941 }
2942 EcT& operator+=(const EcT& rhs) { add(*this, *this, rhs); return *this; }
2943 EcT& operator-=(const EcT& rhs) { sub(*this, *this, rhs); return *this; }
2944 friend EcT operator+(const EcT& a, const EcT& b) { EcT c; EcT::add(c, a, b); return c; }
2945 friend EcT operator-(const EcT& a, const EcT& b) { EcT c; EcT::sub(c, a, b); return c; }
2946};
2947
2948#ifdef _MSC_VER
2949 #pragma warning(pop)
2950#endif
2951
2952typedef mie::Fp Fp;
2962
2964typedef EcT<Fp> Ec1;
2965
2966inline void opt_atePairing(Fp12& f, const Ec2& Q, const Ec1& P)
2967{
2968 Q.normalize();
2969 P.normalize();
2970 if (Q.isZero() || P.isZero()) {
2971 f = 1;
2972 return;
2973 }
2974 opt_atePairing<Fp>(f, Q.p, P.p);
2975}
2976
2977template<>
2978inline bool EcT<Fp2>::isValid() const
2979{
2980 return ecop::isOnTwistECJac3(p);
2981}
2982
2983template<>
2984inline bool EcT<Fp>::isValid() const
2985{
2986 return ecop::isOnECJac3(p);
2987}
2988
2989/*
2990 see https://github.com/herumi/ate-pairing/blob/master/test/bn.cpp
2991*/
2992namespace components {
2993
2994/*
2995 inQ[3] : permit not-normalized
2996*/
2997inline void precomputeG2(std::vector<Fp6>& coeff, Fp2 Q[3], const Fp2 inQ[3])
2998{
2999 coeff.clear();
3000 bn::ecop::NormalizeJac(Q, inQ);
3001
3002 Fp2 T[3];
3003 T[0] = Q[0];
3004 T[1] = Q[1];
3005 T[2] = Fp2(1);
3006 Fp2 Qneg[2];
3007 if (Param::useNAF) {
3008 Qneg[0] = Q[0];
3009 Fp2::neg(Qneg[1], Q[1]);
3010 }
3011
3012 Fp6 d;
3014 coeff.push_back(d);
3015
3016 Fp6 e;
3017 assert(Param::siTbl[1] == 1);
3019 coeff.push_back(e);
3020
3021 bn::Fp6 l;
3022 // 844kclk
3023 for (size_t i = 2; i < Param::siTbl.size(); i++) {
3025 coeff.push_back(l);
3026
3027 if (Param::siTbl[i] > 0) {
3029 coeff.push_back(l);
3030 }
3031 else if (Param::siTbl[i] < 0) {
3033 coeff.push_back(l);
3034 }
3035 }
3036
3037 // addition step
3038 Fp2 Q1[2];
3040 Fp2 Q2[2];
3041#ifdef BN_SUPPORT_SNARK
3043 Fp2::neg(Q2[1], Q2[1]);
3044#else
3045 // @memo z < 0
3047 Fp2::neg(T[1], T[1]);
3048#endif
3049
3051 coeff.push_back(d);
3052
3054 coeff.push_back(e);
3055}
3056
3057/*
3058 precP : normalized point
3059*/
3060inline void millerLoop(Fp12& f, const std::vector<Fp6>& Qcoeff, const Fp precP[2])
3061{
3062 assert(Param::siTbl[1] == 1);
3063 size_t idx = 0;
3064
3065 Fp6 d = Qcoeff[idx];
3066 Fp6::mulFp6_24_Fp_01(d, precP);
3067 idx++;
3068
3069 Fp6 e = Qcoeff[idx];
3070 Fp6::mulFp6_24_Fp_01(e, precP);
3071 Fp12::Dbl::mul_Fp2_024_Fp2_024(f, d, e);
3072
3073 idx++;
3074 bn::Fp6 l;
3075 for (size_t i = 2; i < Param::siTbl.size(); i++) {
3076 l = Qcoeff[idx];
3077 idx++;
3078 Fp12::square(f);
3079 Fp6::mulFp6_24_Fp_01(l, precP);
3080
3081 Fp12::Dbl::mul_Fp2_024(f, l);
3082
3083 if (Param::siTbl[i]) {
3084 l = Qcoeff[idx];
3085 idx++;
3086 Fp6::mulFp6_24_Fp_01(l, precP);
3087 Fp12::Dbl::mul_Fp2_024(f, l);
3088 }
3089 }
3090
3091#ifndef BN_SUPPORT_SNARK
3092 // @memo z < 0
3093 Fp6::neg(f.b_, f.b_);
3094#endif
3095 Fp12 ft;
3096
3097 d = Qcoeff[idx];
3098 Fp6::mulFp6_24_Fp_01(d, precP);
3099 idx++;
3100
3101 e = Qcoeff[idx];
3102 Fp6::mulFp6_24_Fp_01(e, precP);
3103
3104 Fp12::Dbl::mul_Fp2_024_Fp2_024(ft, d, e);
3105 Fp12::mul(f, f, ft);
3106}
3107
3108inline void millerLoop2(Fp12& f, const std::vector<Fp6>& Q1coeff, const Fp precP1[2],
3109 const std::vector<Fp6>& Q2coeff, const Fp precP2[2])
3110{
3111 assert(Param::siTbl[1] == 1);
3112 size_t idx = 0;
3113
3114 Fp6 d1 = Q1coeff[idx];
3115 Fp6::mulFp6_24_Fp_01(d1, precP1);
3116 Fp6 d2 = Q2coeff[idx];
3117 Fp6::mulFp6_24_Fp_01(d2, precP2);
3118 idx++;
3119
3120 Fp12 f1;
3121 Fp6 e1 = Q1coeff[idx];
3122 Fp6::mulFp6_24_Fp_01(e1, precP1);
3123 Fp12::Dbl::mul_Fp2_024_Fp2_024(f1, d1, e1);
3124
3125 Fp12 f2;
3126 Fp6 e2 = Q2coeff[idx];
3127 Fp6::mulFp6_24_Fp_01(e2, precP2);
3128 Fp12::Dbl::mul_Fp2_024_Fp2_024(f2, d2, e2);
3129 Fp12::mul(f, f1, f2);
3130
3131 idx++;
3132 bn::Fp6 l1, l2;
3133 for (size_t i = 2; i < Param::siTbl.size(); i++) {
3134 l1 = Q1coeff[idx];
3135 l2 = Q2coeff[idx];
3136 idx++;
3137 Fp12::square(f);
3138
3139 Fp6::mulFp6_24_Fp_01(l1, precP1);
3140 Fp6::mulFp6_24_Fp_01(l2, precP2);
3141
3142 Fp12::Dbl::mul_Fp2_024_Fp2_024(f1, l1, l2);
3143 Fp12::mul(f, f, f1);
3144
3145 if (Param::siTbl[i]) {
3146 l1 = Q1coeff[idx];
3147 l2 = Q2coeff[idx];
3148 idx++;
3149 Fp6::mulFp6_24_Fp_01(l1, precP1);
3150 Fp6::mulFp6_24_Fp_01(l2, precP2);
3151 Fp12::Dbl::mul_Fp2_024_Fp2_024(f1, l1, l2);
3152 Fp12::mul(f, f, f1);
3153 }
3154 }
3155
3156#ifndef BN_SUPPORT_SNARK
3157 // @memo z < 0
3158 Fp6::neg(f.b_, f.b_);
3159#endif
3160
3161 d1 = Q1coeff[idx];
3162 Fp6::mulFp6_24_Fp_01(d1, precP1);
3163
3164 d2 = Q2coeff[idx];
3165 Fp6::mulFp6_24_Fp_01(d2, precP2);
3166 idx++;
3167
3168 e1 = Q1coeff[idx];
3169 Fp6::mulFp6_24_Fp_01(e1, precP1);
3170
3171 e2 = Q2coeff[idx];
3172 Fp6::mulFp6_24_Fp_01(e2, precP2);
3173
3174 Fp12::Dbl::mul_Fp2_024_Fp2_024(f1, d1, e1);
3175 Fp12::Dbl::mul_Fp2_024_Fp2_024(f2, d2, e2);
3176 Fp12::mul(f, f, f1);
3177 Fp12::mul(f, f, f2);
3178}
3179
3180} // components
3181
3182} // bn
const mie::Vuint & p
Definition bn.cpp:27
const mie::Vuint & r
Definition bn.cpp:28
uint64_t debug_buf[128]
std::string toString() const
Definition bn254_if.hpp:73
Definition bn.h:2815
T p[3]
Definition bn.h:2817
bool isValid() const
bool operator!=(const EcT &rhs) const
Definition bn.h:2907
bool isZero() const
Definition bn.h:2911
friend EcT operator+(const EcT &a, const EcT &b)
Definition bn.h:2944
EcT(const T &x, const T &y, const T &z, bool verify=true)
Definition bn.h:2823
void clear()
Definition bn.h:2860
EcT(const T &x, const T &y, bool verify=true)
Definition bn.h:2819
void set(const T &x, const T &y, const T &z, bool verify=true)
Definition bn.h:2851
EcT & operator-=(const EcT &rhs)
Definition bn.h:2943
friend std::istream & operator>>(std::istream &is, EcT &self)
Definition bn.h:2924
static void dbl(EcT &R, const EcT &P)
Definition bn.h:2867
static void sub(EcT &R, const EcT &P, const EcT &Q)
Definition bn.h:2875
EcT operator*(const N &y) const
Definition bn.h:2895
EcT & operator*=(const N &y)
Definition bn.h:2893
bool operator==(const EcT &rhs) const
Definition bn.h:2896
EcT()
Definition bn.h:2818
friend std::ostream & operator<<(std::ostream &os, const EcT &self)
Definition bn.h:2915
static void add(EcT &R, const EcT &P, const EcT &Q)
Definition bn.h:2871
EcT & operator+=(const EcT &rhs)
Definition bn.h:2942
friend EcT operator-(const EcT &a, const EcT &b)
Definition bn.h:2945
static void neg(EcT &R, const EcT &P)
Definition bn.h:2881
static void mul(EcT &R, const EcT &P, const N &y)
Definition bn.h:2888
void set(const T &x, const T &y, bool verify=true)
Definition bn.h:2842
void normalize() const
Definition bn.h:2827
Definition zm2.h:18
static void(* add)(Fp &out, const Fp &x, const Fp &y)
Definition zm2.h:83
static void(* addNC)(Fp &out, const Fp &x, const Fp &y)
Definition zm2.h:86
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 Fp & getDirectP(int n)
Definition zm2.cpp:126
static void _3z_add_2xC(Fp &z, const Fp &x)
Definition zm2.h:98
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 void(* subNC)(Fp &out, const Fp &x, const Fp &y)
Definition zm2.h:87
static void _2z_add_3x(Fp &z, const Fp &x)
Definition zm2.h:108
static void setModulo(const mie::Vuint &p, int mode, bool useMulx=true, bool definedBN_SUPPORT_SNARK=false)
Definition zm2.cpp:3592
static void square(Fp &out, const Fp &x)
Definition zm2.h:282
V abs() const
Definition zm.h:1149
void set(value_type x)
Definition zm.h:982
#define D(var, file, col, who, lev,...)
Definition debug.h:44
#define d1
#define P
Definition dtoa.c:437
#define d0
os_t os
void put()
Definition gen_code.cpp:234
void init()
Definition lib_test.cpp:3
void verify(const char *msg, const T &a, const S &b)
Definition minitest.cpp:13
void millerLoop2(Fp12 &f, const std::vector< Fp6 > &Q1coeff, const Fp precP1[2], const std::vector< Fp6 > &Q2coeff, const Fp precP2[2])
Definition bn.h:3108
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
void FrobEndOnTwist_8(Fp2T< Fp > *Q, const Fp2T< Fp > *P)
Definition bn.h:2694
bool isOnECHom2(const Fp *P)
Definition bn.h:2380
void FrobEndOnTwist_1(Fp2T< Fp > *Q, const Fp2T< Fp > *P)
Definition bn.h:2650
void convertToBinary(Vec &v, const mie::Vuint &x)
Definition bn.h:103
bool getGoodRepl(Vec &v, const mie::Vuint &x)
Definition bn.h:159
size_t getNumOfNonZeroElement(const Vec &v)
Definition bn.h:145
size_t getContinuousVal(const Vec &v, size_t pos, int val)
Definition bn.h:112
void convertToNAF(Vec &v, const Vec &in)
Definition bn.h:121
Definition bn.h:56
Fp6T< Fp2 > Fp6
Definition bn.h:2957
Fp::Dbl FpDbl
Definition bn.h:2953
void opt_atePairingJac(Fp12T< Fp6T< Fp2T< Fp > > > &f, const Fp2T< Fp > _Q[3], const Fp _P[3])
Definition bn.h:2795
CompressT< Fp2 > Compress
Definition bn.h:2961
void(* CompressT)(CompressT &, int)
Definition bn.h:2345
ParamT< Fp2 > Param
Definition bn.h:2956
mie::Fp Fp
Definition bn.h:2952
const CurveParam CurveFp254BNb
Definition bn.h:84
Fp6::Dbl Fp6Dbl
Definition bn.h:2958
Fp12::Dbl Fp12Dbl
Definition bn.h:2960
EcT< Fp2 > Ec2
Definition bn.h:2963
Fp12T< Fp6 > Fp12
Definition bn.h:2959
Fp2::Dbl Fp2Dbl
Definition bn.h:2955
void opt_atePairing(Fp12T< Fp6T< Fp2T< Fp > > > &f, const Fp2T< Fp > Q[2], const Fp P[2])
Definition bn.h:2720
EcT< Fp > Ec1
Definition bn.h:2964
void mul_gamma_add(F &z, const F &x, const F &y)
Definition bn.h:333
Fp2T< Fp > Fp2
Definition bn.h:2954
Definition zm.h:60
void zmInit()
Definition zm.cpp:557
T power(const T &x, const S &y)
Definition zm.h:1389
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
#define T(meth, val, expected)
const int N
Definition quantize.cpp:54
signed __int64 int64_t
Definition stdint.h:135
unsigned int uint32_t
Definition stdint.h:126
unsigned __int64 uint64_t
Definition stdint.h:136
Definition test_zm.cpp:19
static void squareC(CompressT &z)
Definition bn.h:2232
Fp2::Dbl Fp2Dbl
Definition bn.h:2132
CompressT(Fp12 &z, const CompressT &c)
Definition bn.h:2158
Fp2 & g2_
Definition bn.h:2139
Fp6T< Fp2 > Fp6
Definition bn.h:2133
CompressT(Fp12 &z, const Fp12 &x)
Definition bn.h:2145
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::Fp Fp
Definition bn.h:2130
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
static void square_nC(CompressT &z, int n)
Definition bn.h:2299
friend std::ostream & operator<<(std::ostream &os, const CompressT &x)
Definition bn.h:2172
Fp12T< Fp6 > Fp12
Definition bn.h:2134
ParamT< Fp2 > Param
Definition bn.h:2131
bool operator==(const CurveParam &rhs) const
Definition bn.h:70
int xi_a
Definition bn.h:68
int b
Definition bn.h:67
int64_t z
Definition bn.h:66
bool operator!=(const CurveParam &rhs) const
Definition bn.h:71
int xi_b
Definition bn.h:69
void setDirect(const Fp6Dbl &a, const Fp6Dbl &b)
Definition bn.h:1889
Fp6Dbl * get()
Definition bn.h:1894
Fp6Dbl a_
Definition bn.h:1856
Fp2::Dbl Fp2Dbl
Definition bn.h:1852
static void mod(Fp12T &z, Dbl &x)
Definition bn.h:2110
const Fp6Dbl * get() const
Definition bn.h:1895
static void subNC(Dbl &z, const Dbl &x, const Dbl &y)
Definition bn.h:1934
Dbl(const Fp6Dbl &a, const Fp6Dbl &b)
Definition bn.h:1878
Fp6Dbl b_
Definition bn.h:1856
friend std::ostream & operator<<(std::ostream &os, const Dbl &x)
Definition bn.h:1862
std::string toString(int base=10) const
Definition bn.h:1858
static void addNC(Dbl &z, const Dbl &x, const Dbl &y)
Definition bn.h:1916
Dbl(const Fp12T &x)
Definition bn.h:1868
static void add(Dbl &z, const Dbl &x, const Dbl &y)
Definition bn.h:1910
bool isZero() const
Definition bn.h:1896
friend bool operator==(const Dbl &x, const Dbl &y)
Definition bn.h:1898
static void sub(Dbl &z, const Dbl &x, const Dbl &y)
Definition bn.h:1928
friend bool operator!=(const Dbl &x, const Dbl &y)
Definition bn.h:1902
static void mul_Fp2_024_Fp2_024(Fp12T &z, const Fp6 &cv2, const Fp6 &cv3)
Definition bn.h:2065
Fp6::Dbl Fp6Dbl
Definition bn.h:1853
static void(* mul_Fp2_024)(Fp12T &z, const Fp6 &x)
Definition bn.h:1963
Dbl(const Fp6 &a, const Fp6 &b)
Definition bn.h:1873
void bin_op(Dbl &, const Dbl &, const Dbl &)
Definition bn.h:1908
static void neg(Dbl &z, const Dbl &x)
Definition bn.h:1922
void uni_op(Dbl &, const Dbl &)
Definition bn.h:1907
Dbl(const std::string &a, const std::string &b)
Definition bn.h:1883
static void mul_Fp2_024C(Fp12T &z, const Fp6 &x)
Definition bn.h:1964
T Fp6
Definition bn.h:1364
Fp12T(const Fp &a0, const Fp &a1, const Fp &a2, const Fp &a3, const Fp &a4, const Fp &a5, const Fp &a6, const Fp &a7, const Fp &a8, const Fp &a9, const Fp &a10, const Fp &a11)
Definition bn.h:1383
void inverse()
Definition bn.h:1620
Fp12T(int x)
Definition bn.h:1373
static void mulC(Fp12T &z, const Fp12T &x, const Fp12T &y)
Definition bn.h:1450
Fp2::Dbl Fp2Dbl
Definition bn.h:1368
friend std::istream & operator>>(std::istream &is, Fp12T &x)
Definition bn.h:1425
static void sq_Fp4UseDbl(Fp2 &z0, Fp2 &z1, const Fp2 &x0, const Fp2 &x1)
Definition bn.h:1509
Fp6::Fp2 Fp2
Definition bn.h:1365
Fp2 * getFp2()
Definition bn.h:1404
void set(const Fp2 &v0, const Fp2 &v1, const Fp2 &v2, const Fp2 &v3, const Fp2 &v4, const Fp2 &v5)
Definition bn.h:1406
static void squareC(Fp12T &z)
Definition bn.h:1476
Fp * get()
Definition bn.h:1402
void mapToCyclo(Fp12T &z)
Definition bn.h:1731
void Frobenius(Fp12T &z) const
Definition bn.h:1640
static void neg(Fp12T &z, const Fp12T &x)
Definition bn.h:1442
bool operator==(const Fp12T &rhs) const
Definition bn.h:1416
static void(* mul)(Fp12T &z, const Fp12T &x, const Fp12T &y)
Definition bn.h:1449
void Frobenius3(Fp12T &z) const
Definition bn.h:1696
bool operator!=(const Fp12T &rhs) const
Definition bn.h:1420
ParamT< Fp2 > Param
Definition bn.h:1367
void Fp2_2z_add_3x(Fp2 &z, const Fp2 &x)
Definition bn.h:1556
void final_exp()
Definition bn.h:1776
bool isZero() const
Definition bn.h:1412
Fp6::Fp Fp
Definition bn.h:1366
Fp12T(const Fp6 &a, const Fp6 &b)
Definition bn.h:1378
static void add(Fp12T &z, const Fp12T &x, const Fp12T &y)
Definition bn.h:1432
Fp6 a_
Definition bn.h:1371
static void sub(Fp12T &z, const Fp12T &x, const Fp12T &y)
Definition bn.h:1437
Fp6 b_
Definition bn.h:1371
void Frobenius2(Fp12T &z) const
Definition bn.h:1678
Fp12T()
Definition bn.h:1372
void sqru()
Definition bn.h:1561
void sqru(Fp12T &zz) const
Definition bn.h:1614
friend std::ostream & operator<<(std::ostream &os, const Fp12T &x)
Definition bn.h:1421
Fp6::Dbl Fp6Dbl
Definition bn.h:1369
static void(* square)(Fp12T &z)
Definition bn.h:1475
void clear()
Definition bn.h:1396
Fp12T(const Fp2 &a0, const Fp2 &a1, const Fp2 &a2, const Fp2 &a3, const Fp2 &a4, const Fp2 &a5)
Definition bn.h:1390
const Fp2 * getFp2() const
Definition bn.h:1405
const Fp * get() const
Definition bn.h:1403
static bin_op * sub
Definition bn.h:654
static void(* mod)(Fp2T &z, const Dbl &x)
Definition bn.h:660
bool isZero() const
Definition bn.h:637
static bin_op * subNC
Definition bn.h:655
Dbl(const Fp2T &x)
Definition bn.h:599
void bin_op(Dbl &, const Dbl &, const Dbl &)
Definition bn.h:649
void clear()
Definition bn.h:632
Dbl(const FpDbl &a, const FpDbl &b)
Definition bn.h:609
std::string toString(int base=10) const
Definition bn.h:589
static bin_op * addNC
Definition bn.h:652
Dbl(const Fp &a, const Fp &b)
Definition bn.h:604
static uni_op * mul_xi
Definition bn.h:662
friend std::ostream & operator<<(std::ostream &os, const Dbl &x)
Definition bn.h:593
static bin_op * add
Definition bn.h:651
void setDirect(const mie::Vuint &a, const mie::Vuint &b)
Definition bn.h:620
static void mulOptC(Dbl &z, const Fp2T &x, const Fp2T &y, int mode)
Definition bn.h:725
static void(* square)(Dbl &z, const Fp2T &x)
Definition bn.h:659
static void squareC(Dbl &z, const Fp2T &x)
Definition bn.h:755
static void mulOpt1C(Dbl &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:745
static void addC(Dbl &z, const Dbl &x, const Dbl &y)
Definition bn.h:664
friend bool operator==(const Dbl &x, const Dbl &y)
Definition bn.h:642
FpDbl * get()
Definition bn.h:630
static void subC(Dbl &z, const Dbl &x, const Dbl &y)
Definition bn.h:682
friend bool operator!=(const Dbl &x, const Dbl &y)
Definition bn.h:646
Fp::Dbl FpDbl
Definition bn.h:584
static void modC(Fp2T &z, const Dbl &x)
Definition bn.h:766
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
void uni_op(Dbl &, const Dbl &)
Definition bn.h:648
const FpDbl * get() const
Definition bn.h:631
static void mulOpt2C(Dbl &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:750
static void subNC_C(Dbl &z, const Dbl &x, const Dbl &y)
Definition bn.h:688
FpDbl a_
Definition bn.h:587
void setDirect(const FpDbl &a, const FpDbl &b)
Definition bn.h:625
static void negC(Dbl &z, const Dbl &x)
Definition bn.h:676
static void addNC_C(Dbl &z, const Dbl &x, const Dbl &y)
Definition bn.h:670
static uni_op * neg
Definition bn.h:653
FpDbl b_
Definition bn.h:587
static void mul_xiC(Dbl &z, const Dbl &x)
Definition bn.h:717
Dbl(const std::string &a, const std::string &b)
Definition bn.h:614
Definition bn.h:348
static void subC(Fp2T &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:395
std::string toString(int base=10) const
Definition bn.h:521
void mul_x()
Definition bn.h:561
Fp2T()
Definition bn.h:351
Fp a_
Definition bn.h:350
Fp * get()
Definition bn.h:362
bool isZero() const
Definition bn.h:364
void inverse()
Definition bn.h:505
static void squareC(Fp2T &z, const Fp2T &x)
Definition bn.h:481
static void neg(Fp2T &z, const Fp2T &x)
Definition bn.h:400
static void mul_xiC(Fp2T &z, const Fp2T &x)
Definition bn.h:470
static void(* square)(Fp2T &z, const Fp2T &x)
Definition bn.h:373
static void addNC_C(Fp2T &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:383
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
bool operator!=(const Fp2T &rhs) const
Definition bn.h:540
friend std::ostream & operator<<(std::ostream &os, const Fp2T &x)
Definition bn.h:525
void clear()
Definition bn.h:515
static void divBy4(Fp2T &z, const Fp2T &x)
Definition bn.h:434
Fp2T(int x)
Definition bn.h:352
static void(* mul_Fp_0)(Fp2T &z, const Fp2T &x, const Fp &b)
Definition bn.h:375
Fp2T(const Fp &a, const Fp &b)
Definition bn.h:357
Fp b_
Definition bn.h:350
static void mulC(Fp2T &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:412
bool operator==(const Fp2T &rhs) const
Definition bn.h:536
static void mul_Fp_0C(Fp2T &z, const Fp2T &x, const Fp &b)
Definition bn.h:549
static void(* sub)(Fp2T &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:370
static void subNC_C(Fp2T &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:389
static void addC(Fp2T &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:378
static void divBy2C(Fp2T &z, const Fp2T &x)
Definition bn.h:428
static void(* mul_xi)(Fp2T &z, const Fp2T &x)
Definition bn.h:374
friend std::istream & operator>>(std::istream &is, Fp2T &x)
Definition bn.h:529
static void(* add)(Fp2T &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:368
const Fp * get() const
Definition bn.h:363
void set(const std::string &str)
Definition bn.h:542
T Fp
Definition bn.h:349
static void(* mul)(Fp2T &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:372
static void(* subNC)(Fp2T &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:371
Fp2Dbl c_
Definition bn.h:1163
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
Dbl(const std::string &a0, const std::string &a1, const std::string &b0, const std::string &b1, const std::string &c0, const std::string &c1)
Definition bn.h:1193
void bin_op(Dbl &, const Dbl &, const Dbl &)
Definition bn.h:1226
static void mulC(Dbl &z, const Fp6T &x, const Fp6T &y)
Definition bn.h:1268
static void subNC(Dbl &z, const Dbl &x, const Dbl &y)
Definition bn.h:1256
Fp::Dbl FpDbl
Definition bn.h:1159
friend std::ostream & operator<<(std::ostream &os, const Dbl &x)
Definition bn.h:1169
Fp2Dbl b_
Definition bn.h:1163
static void neg(Dbl &z, const Dbl &x)
Definition bn.h:1242
Dbl(const Fp2 &a, const Fp2 &b, const Fp2 &c)
Definition bn.h:1181
void setDirect(const Fp2Dbl &a, const Fp2Dbl &b, const Fp2Dbl &c)
Definition bn.h:1206
Dbl(const Fp6T &x)
Definition bn.h:1175
void uni_op(Dbl &, const Dbl &)
Definition bn.h:1225
friend bool operator==(const Dbl &x, const Dbl &y)
Definition bn.h:1219
Fp2Dbl a_
Definition bn.h:1163
friend bool operator!=(const Dbl &x, const Dbl &y)
Definition bn.h:1223
Fp2::Dbl Fp2Dbl
Definition bn.h:1160
const Fp2Dbl * get() const
Definition bn.h:1213
static void mod(Fp6T &z, const Dbl &x)
Definition bn.h:1328
void setDirect(const mie::Vuint &v0, const mie::Vuint &v1, const mie::Vuint &v2, const mie::Vuint &v3, const mie::Vuint &v4, const mie::Vuint &v5)
Definition bn.h:1200
static void addNC(Dbl &z, const Dbl &x, const Dbl &y)
Definition bn.h:1235
bool isZero() const
Definition bn.h:1214
std::string toString(int base=10) const
Definition bn.h:1165
static void add(Dbl &z, const Dbl &x, const Dbl &y)
Definition bn.h:1228
Dbl(const Fp2Dbl &a, const Fp2Dbl &b, const Fp2Dbl &c)
Definition bn.h:1187
Fp2Dbl * get()
Definition bn.h:1212
Definition bn.h:837
static void mulFp6_24_Fp_01(Fp6T &l, const Fp *P)
Definition bn.h:1074
T::Fp Fp
Definition bn.h:839
static void(* pointDblLineEvalWithoutP)(Fp6T &l, Fp2 *R)
Definition bn.h:987
static void mul_Fp_c(Fp6T &z, const Fp &x)
Definition bn.h:1153
Fp6T(int x)
Definition bn.h:844
static void square(Fp6T &z, const Fp6T &x)
Definition bn.h:914
Fp2 c_
Definition bn.h:842
Fp2::Dbl Fp2Dbl
Definition bn.h:841
bool isZero() const
Definition bn.h:879
Fp6T()
Definition bn.h:843
Fp6T(const Fp2 &a, const Fp2 &b, const Fp2 &c)
Definition bn.h:850
static void subC(Fp6T &z, const Fp6T &x, const Fp6T &y)
Definition bn.h:890
const Fp * get() const
Definition bn.h:870
ParamT< Fp2 > Param
Definition bn.h:840
static void pointAddLineEval(Fp6T &l, Fp2 *R, const Fp2 *Q, const Fp *P)
Definition bn.h:1143
static void neg(Fp6T &z, const Fp6T &x)
Definition bn.h:896
void clear()
Definition bn.h:862
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
bool operator!=(const Fp6T &rhs) const
Definition bn.h:969
friend std::ostream & operator<<(std::ostream &os, const Fp6T &x)
Definition bn.h:970
Fp2 a_
Definition bn.h:842
Fp6T(const Fp &a0, const Fp &a1, const Fp &a2, const Fp &a3, const Fp &a4, const Fp &a5)
Definition bn.h:856
T Fp2
Definition bn.h:838
static void pointDblLineEvalWithoutPC(Fp6T &l, Fp2 *R)
Definition bn.h:1001
const Fp2 * getFp2() const
Definition bn.h:872
static void mulC(Fp6T &z, const Fp6T &x, const Fp6T &y)
Definition bn.h:904
static void(* add)(Fp6T &z, const Fp6T &x, const Fp6T &y)
Definition bn.h:982
void set(const Fp2 &v0, const Fp2 &v1, const Fp2 &v2)
Definition bn.h:873
void inverse()
Definition bn.h:937
friend std::istream & operator>>(std::istream &is, Fp6T &x)
Definition bn.h:974
Fp2 b_
Definition bn.h:842
static void addC(Fp6T &z, const Fp6T &x, const Fp6T &y)
Definition bn.h:884
static void mul_Fp_b(Fp6T &z, const Fp &x)
Definition bn.h:1149
bool operator==(const Fp6T &rhs) const
Definition bn.h:965
static void(* mul)(Fp6T &z, const Fp6T &x, const Fp6T &y)
Definition bn.h:984
static void pointDblLineEvalC(Fp6T &l, Fp2 *R, const Fp *P)
Definition bn.h:1079
static void pointAddLineEvalWithoutP(Fp6T &l, Fp2 *R, const Fp2 *Q)
Definition bn.h:1094
Fp2 * getFp2()
Definition bn.h:871
static int b
Definition bn.h:194
static void init(int mode=-1, bool useMulx=true)
Definition bn.h:264
static Fp Z
Definition bn.h:186
Fp2::Fp Fp
Definition bn.h:180
static SignVec siTbl
Definition bn.h:200
static mie::Vuint t
Definition bn.h:184
static Fp i1
Definition bn.h:193
static mie::Vuint p
Definition bn.h:182
static mie::Vsint largest_c
Definition bn.h:185
static mie::Vuint r
Definition bn.h:183
static Fp2 W2p
Definition bn.h:187
static Fp2 W3p
Definition bn.h:188
std::vector< signed char > SignVec
Definition bn.h:199
static bool useNAF
Definition bn.h:201
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 Fp i0
Definition bn.h:192
static void init(const CurveParam &cp, int mode=-1, bool useMulx=true)
Definition bn.h:206
static void eval(T &y, const U &x, const int *c)
Definition bn.h:276
static Fp half
Definition bn.h:196
static Fp2 b_invxi
Definition bn.h:195
MIE_FORCE_INLINE void clear()
Definition zm2.h:332
static void subOpt1(Dbl &z, const Dbl &x, const Dbl &y)
Definition zm2.h:382
static MIE_FORCE_INLINE void setDirect(Dbl &out, const mie::Vuint &in)
Definition zm2.h:312
std::string toString(int base=10) const
Definition zm2.h:344
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
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
size_t bitLen() const
Definition zm.h:526
bool testBit(size_t i) const
Definition zm.h:539
static size_t getBlockSize(const T &x)
Definition zm.h:1352
T::value_type value_type
Definition zm.h:1347
static value_type getBlock(const T &x, size_t i)
Definition zm.h:1348
#define R
#define A
Definition dtoa.c:306
CK_ULONG d
char * s
uint16_t j
size_t len
bool set
int l