aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/dexon-foundation/mcl/include/mcl/fp_tower.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/dexon-foundation/mcl/include/mcl/fp_tower.hpp')
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/mcl/fp_tower.hpp1364
1 files changed, 0 insertions, 1364 deletions
diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/fp_tower.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/fp_tower.hpp
deleted file mode 100644
index 95722e2d5..000000000
--- a/vendor/github.com/dexon-foundation/mcl/include/mcl/fp_tower.hpp
+++ /dev/null
@@ -1,1364 +0,0 @@
-#pragma once
-/**
- @file
- @brief finite field extension class
- @author MITSUNARI Shigeo(@herumi)
- @license modified new BSD license
- http://opensource.org/licenses/BSD-3-Clause
-*/
-#include <mcl/fp.hpp>
-
-namespace mcl {
-
-template<class Fp>
-class FpDblT : public fp::Serializable<FpDblT<Fp> > {
- typedef fp::Unit Unit;
- Unit v_[Fp::maxSize * 2];
-public:
- static size_t getUnitSize() { return Fp::op_.N * 2; }
- FpDblT() : v_()
- {
- }
- FpDblT(const FpDblT& rhs)
- {
- const size_t n = getUnitSize();
- for (size_t i = 0; i < n; i++) {
- v_[i] = rhs.v_[i];
- }
- }
- void dump() const
- {
- const size_t n = getUnitSize();
- for (size_t i = 0; i < n; i++) {
- mcl::fp::dumpUnit(v_[n - 1 - i]);
- }
- printf("\n");
- }
- template<class OutputStream>
- void save(bool *pb, OutputStream& os, int) const
- {
- char buf[1024];
- size_t n = mcl::fp::arrayToHex(buf, sizeof(buf), v_, getUnitSize());
- if (n == 0) {
- *pb = false;
- return;
- }
- cybozu::write(pb, os, buf + sizeof(buf) - n, sizeof(buf));
- }
- template<class InputStream>
- void load(bool *pb, InputStream& is, int)
- {
- char buf[1024];
- *pb = false;
- size_t n = fp::local::loadWord(buf, sizeof(buf), is);
- if (n == 0) return;
- n = fp::hexToArray(v_, getUnitSize(), buf, n);
- if (n == 0) return;
- for (size_t i = n; i < getUnitSize(); i++) v_[i] = 0;
- *pb = true;
- }
-#ifndef CYBOZU_DONT_USE_EXCEPTION
- template<class OutputStream>
- void save(OutputStream& os, int ioMode = IoSerialize) const
- {
- bool b;
- save(&b, os, ioMode);
- if (!b) throw cybozu::Exception("FpDblT:save") << ioMode;
- }
- template<class InputStream>
- void load(InputStream& is, int ioMode = IoSerialize)
- {
- bool b;
- load(&b, is, ioMode);
- if (!b) throw cybozu::Exception("FpDblT:load") << ioMode;
- }
- void getMpz(mpz_class& x) const
- {
- bool b;
- getMpz(&b, x);
- if (!b) throw cybozu::Exception("FpDblT:getMpz");
- }
- mpz_class getMpz() const
- {
- mpz_class x;
- getMpz(x);
- return x;
- }
-#endif
- void clear()
- {
- const size_t n = getUnitSize();
- for (size_t i = 0; i < n; i++) {
- v_[i] = 0;
- }
- }
- FpDblT& operator=(const FpDblT& rhs)
- {
- const size_t n = getUnitSize();
- for (size_t i = 0; i < n; i++) {
- v_[i] = rhs.v_[i];
- }
- return *this;
- }
- // QQQ : does not check range of x strictly(use for debug)
- void setMpz(const mpz_class& x)
- {
- assert(x >= 0);
- const size_t xn = gmp::getUnitSize(x);
- const size_t N2 = getUnitSize();
- if (xn > N2) {
- assert(0);
- return;
- }
- memcpy(v_, gmp::getUnit(x), xn * sizeof(Unit));
- memset(v_ + xn, 0, (N2 - xn) * sizeof(Unit));
- }
- void getMpz(bool *pb, mpz_class& x) const
- {
- gmp::setArray(pb, x, v_, Fp::op_.N * 2);
- }
-#ifdef MCL_XBYAK_DIRECT_CALL
- static void (*add)(FpDblT& z, const FpDblT& x, const FpDblT& y);
- static void (*sub)(FpDblT& z, const FpDblT& x, const FpDblT& y);
- static void (*mod)(Fp& z, const FpDblT& xy);
- static void (*addPre)(FpDblT& z, const FpDblT& x, const FpDblT& y);
- static void (*subPre)(FpDblT& z, const FpDblT& x, const FpDblT& y);
- static void addC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_add(z.v_, x.v_, y.v_, Fp::op_.p); }
- static void subC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_sub(z.v_, x.v_, y.v_, Fp::op_.p); }
- static void modC(Fp& z, const FpDblT& xy) { Fp::op_.fpDbl_mod(z.v_, xy.v_, Fp::op_.p); }
- static void addPreC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_addPre(z.v_, x.v_, y.v_); }
- static void subPreC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_subPre(z.v_, x.v_, y.v_); }
-#else
- static void add(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_add(z.v_, x.v_, y.v_, Fp::op_.p); }
- static void sub(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_sub(z.v_, x.v_, y.v_, Fp::op_.p); }
- static void mod(Fp& z, const FpDblT& xy) { Fp::op_.fpDbl_mod(z.v_, xy.v_, Fp::op_.p); }
- static void addPre(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_addPre(z.v_, x.v_, y.v_); }
- static void subPre(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_subPre(z.v_, x.v_, y.v_); }
-#endif
- static void mulPreC(FpDblT& xy, const Fp& x, const Fp& y) { Fp::op_.fpDbl_mulPre(xy.v_, x.v_, y.v_); }
- static void sqrPreC(FpDblT& xx, const Fp& x) { Fp::op_.fpDbl_sqrPre(xx.v_, x.v_); }
- /*
- mul(z, x, y) = mulPre(xy, x, y) + mod(z, xy)
- */
- static void (*mulPre)(FpDblT& xy, const Fp& x, const Fp& y);
- static void (*sqrPre)(FpDblT& xx, const Fp& x);
- static void mulUnit(FpDblT& z, const FpDblT& x, Unit y)
- {
- if (mulSmallUnit(z, x, y)) return;
- assert(0); // not supported y
- }
- static void init()
- {
- const mcl::fp::Op& op = Fp::getOp();
-#ifdef MCL_XBYAK_DIRECT_CALL
- add = fp::func_ptr_cast<void (*)(FpDblT&, const FpDblT&, const FpDblT&)>(op.fpDbl_addA_);
- if (add == 0) add = addC;
- sub = fp::func_ptr_cast<void (*)(FpDblT&, const FpDblT&, const FpDblT&)>(op.fpDbl_subA_);
- if (sub == 0) sub = subC;
- mod = fp::func_ptr_cast<void (*)(Fp&, const FpDblT&)>(op.fpDbl_modA_);
- if (mod == 0) mod = modC;
- addPre = fp::func_ptr_cast<void (*)(FpDblT&, const FpDblT&, const FpDblT&)>(op.fpDbl_addPre);
- if (addPre == 0) addPre = addPreC;
- subPre = fp::func_ptr_cast<void (*)(FpDblT&, const FpDblT&, const FpDblT&)>(op.fpDbl_subPre);
- if (subPre == 0) subPre = subPreC;
-#endif
- if (op.fpDbl_mulPreA_) {
- mulPre = fp::func_ptr_cast<void (*)(FpDblT&, const Fp&, const Fp&)>(op.fpDbl_mulPreA_);
- } else {
- mulPre = mulPreC;
- }
- if (op.fpDbl_sqrPreA_) {
- sqrPre = fp::func_ptr_cast<void (*)(FpDblT&, const Fp&)>(op.fpDbl_sqrPreA_);
- } else {
- sqrPre = sqrPreC;
- }
- }
- void operator+=(const FpDblT& x) { add(*this, *this, x); }
- void operator-=(const FpDblT& x) { sub(*this, *this, x); }
-};
-
-#ifdef MCL_XBYAK_DIRECT_CALL
-template<class Fp> void (*FpDblT<Fp>::add)(FpDblT&, const FpDblT&, const FpDblT&);
-template<class Fp> void (*FpDblT<Fp>::sub)(FpDblT&, const FpDblT&, const FpDblT&);
-template<class Fp> void (*FpDblT<Fp>::mod)(Fp&, const FpDblT&);
-template<class Fp> void (*FpDblT<Fp>::addPre)(FpDblT&, const FpDblT&, const FpDblT&);
-template<class Fp> void (*FpDblT<Fp>::subPre)(FpDblT&, const FpDblT&, const FpDblT&);
-#endif
-template<class Fp> void (*FpDblT<Fp>::mulPre)(FpDblT&, const Fp&, const Fp&);
-template<class Fp> void (*FpDblT<Fp>::sqrPre)(FpDblT&, const Fp&);
-
-template<class Fp> struct Fp12T;
-template<class Fp> class BNT;
-template<class Fp> struct Fp2DblT;
-/*
- beta = -1
- Fp2 = F[i] / (i^2 + 1)
- x = a + bi
-*/
-template<class _Fp>
-class Fp2T : public fp::Serializable<Fp2T<_Fp>,
- fp::Operator<Fp2T<_Fp> > > {
- typedef _Fp Fp;
- typedef fp::Unit Unit;
- typedef FpDblT<Fp> FpDbl;
- typedef Fp2DblT<Fp> Fp2Dbl;
- static const size_t gN = 5;
- /*
- g = xi^((p - 1) / 6)
- g[] = { g^2, g^4, g^1, g^3, g^5 }
- */
- static Fp2T g[gN];
- static Fp2T g2[gN];
- static Fp2T g3[gN];
-public:
- static const Fp2T *get_gTbl() { return &g[0]; }
- static const Fp2T *get_g2Tbl() { return &g2[0]; }
- static const Fp2T *get_g3Tbl() { return &g3[0]; }
- typedef typename Fp::BaseFp BaseFp;
- static const size_t maxSize = Fp::maxSize * 2;
- static inline size_t getByteSize() { return Fp::getByteSize() * 2; }
- void dump() const
- {
- a.dump();
- b.dump();
- }
- Fp a, b;
- Fp2T() { }
- Fp2T(int64_t a) : a(a), b(0) { }
- Fp2T(const Fp& a, const Fp& b) : a(a), b(b) { }
- Fp2T(int64_t a, int64_t b) : a(a), b(b) { }
- Fp* getFp0() { return &a; }
- const Fp* getFp0() const { return &a; }
- const Unit* getUnit() const { return a.getUnit(); }
- void clear()
- {
- a.clear();
- b.clear();
- }
- void set(const Fp &a_, const Fp &b_)
- {
- a = a_;
- b = b_;
- }
-#ifdef MCL_XBYAK_DIRECT_CALL
- static void (*add)(Fp2T& z, const Fp2T& x, const Fp2T& y);
- static void (*sub)(Fp2T& z, const Fp2T& x, const Fp2T& y);
- static void (*neg)(Fp2T& y, const Fp2T& x);
- static void (*mul)(Fp2T& z, const Fp2T& x, const Fp2T& y);
- static void (*sqr)(Fp2T& y, const Fp2T& x);
-#else
- static void add(Fp2T& z, const Fp2T& x, const Fp2T& y) { addC(z, x, y); }
- static void sub(Fp2T& z, const Fp2T& x, const Fp2T& y) { subC(z, x, y); }
- static void neg(Fp2T& y, const Fp2T& x) { negC(y, x); }
- static void mul(Fp2T& z, const Fp2T& x, const Fp2T& y) { mulC(z, x, y); }
- static void sqr(Fp2T& y, const Fp2T& x) { sqrC(y, x); }
-#endif
- static void (*mul_xi)(Fp2T& y, const Fp2T& x);
- static void addPre(Fp2T& z, const Fp2T& x, const Fp2T& y) { Fp::addPre(z.a, x.a, y.a); Fp::addPre(z.b, x.b, y.b); }
- static void inv(Fp2T& y, const Fp2T& x) { Fp::op_.fp2_inv(y.a.v_, x.a.v_); }
- static void divBy2(Fp2T& y, const Fp2T& x)
- {
- Fp::divBy2(y.a, x.a);
- Fp::divBy2(y.b, x.b);
- }
- static void divBy4(Fp2T& y, const Fp2T& x)
- {
- Fp::divBy4(y.a, x.a);
- Fp::divBy4(y.b, x.b);
- }
- static void mulFp(Fp2T& z, const Fp2T& x, const Fp& y)
- {
- Fp::mul(z.a, x.a, y);
- Fp::mul(z.b, x.b, y);
- }
- template<class S>
- void setArray(bool *pb, const S *buf, size_t n)
- {
- assert((n & 1) == 0);
- n /= 2;
- a.setArray(pb, buf, n);
- if (!*pb) return;
- b.setArray(pb, buf + n, n);
- }
- template<class InputStream>
- void load(bool *pb, InputStream& is, int ioMode)
- {
- a.load(pb, is, ioMode);
- if (!*pb) return;
- b.load(pb, is, ioMode);
- }
- /*
- Fp2T = <a> + ' ' + <b>
- */
- template<class OutputStream>
- void save(bool *pb, OutputStream& os, int ioMode) const
- {
- const char sep = *fp::getIoSeparator(ioMode);
- a.save(pb, os, ioMode);
- if (!*pb) return;
- if (sep) {
- cybozu::writeChar(pb, os, sep);
- if (!*pb) return;
- }
- b.save(pb, os, ioMode);
- }
- bool isZero() const { return a.isZero() && b.isZero(); }
- bool isOne() const { return a.isOne() && b.isZero(); }
- bool operator==(const Fp2T& rhs) const { return a == rhs.a && b == rhs.b; }
- bool operator!=(const Fp2T& rhs) const { return !operator==(rhs); }
- /*
- return true is a is odd (do not consider b)
- this function is for only compressed reprezentation of EC
- isOdd() is not good naming. QQQ
- */
- bool isOdd() const { return a.isOdd(); }
- /*
- (a + bi)^2 = (a^2 - b^2) + 2ab i = c + di
- A = a^2
- B = b^2
- A = (c +/- sqrt(c^2 + d^2))/2
- b = d / 2a
- */
- static inline bool squareRoot(Fp2T& y, const Fp2T& x)
- {
- Fp t1, t2;
- if (x.b.isZero()) {
- if (Fp::squareRoot(t1, x.a)) {
- y.a = t1;
- y.b.clear();
- } else {
- bool b = Fp::squareRoot(t1, -x.a);
- assert(b); (void)b;
- y.a.clear();
- y.b = t1;
- }
- return true;
- }
- Fp::sqr(t1, x.a);
- Fp::sqr(t2, x.b);
- t1 += t2; // c^2 + d^2
- if (!Fp::squareRoot(t1, t1)) return false;
- Fp::add(t2, x.a, t1);
- Fp::divBy2(t2, t2);
- if (!Fp::squareRoot(t2, t2)) {
- Fp::sub(t2, x.a, t1);
- Fp::divBy2(t2, t2);
- bool b = Fp::squareRoot(t2, t2);
- assert(b); (void)b;
- }
- y.a = t2;
- t2 += t2;
- Fp::inv(t2, t2);
- Fp::mul(y.b, x.b, t2);
- return true;
- }
- static void inline norm(Fp& y, const Fp2T& x)
- {
- Fp aa, bb;
- Fp::sqr(aa, x.a);
- Fp::sqr(bb, x.b);
- Fp::add(y, aa, bb);
- }
- /*
- Frobenius
- i^2 = -1
- (a + bi)^p = a + bi^p in Fp
- = a + bi if p = 1 mod 4
- = a - bi if p = 3 mod 4
- */
- static void Frobenius(Fp2T& y, const Fp2T& x)
- {
- if (Fp::getOp().pmod4 == 1) {
- if (&y != &x) {
- y = x;
- }
- } else {
- if (&y != &x) {
- y.a = x.a;
- }
- Fp::neg(y.b, x.b);
- }
- }
-
- static uint32_t get_xi_a() { return Fp::getOp().xi_a; }
- static void init()
- {
-// assert(Fp::maxSize <= 256);
- mcl::fp::Op& op = Fp::op_;
- assert(op.xi_a);
- mul_xi = 0;
-#ifdef MCL_XBYAK_DIRECT_CALL
- add = fp::func_ptr_cast<void (*)(Fp2T& z, const Fp2T& x, const Fp2T& y)>(op.fp2_addA_);
- if (add == 0) add = addC;
- sub = fp::func_ptr_cast<void (*)(Fp2T& z, const Fp2T& x, const Fp2T& y)>(op.fp2_subA_);
- if (sub == 0) sub = subC;
- neg = fp::func_ptr_cast<void (*)(Fp2T& y, const Fp2T& x)>(op.fp2_negA_);
- if (neg == 0) neg = negC;
- mul = fp::func_ptr_cast<void (*)(Fp2T& z, const Fp2T& x, const Fp2T& y)>(op.fp2_mulA_);
- if (mul == 0) mul = mulC;
- sqr = fp::func_ptr_cast<void (*)(Fp2T& y, const Fp2T& x)>(op.fp2_sqrA_);
- if (sqr == 0) sqr = sqrC;
- mul_xi = fp::func_ptr_cast<void (*)(Fp2T&, const Fp2T&)>(op.fp2_mul_xiA_);
-#endif
- op.fp2_inv = fp2_invW;
- if (mul_xi == 0) {
- if (op.xi_a == 1) {
- mul_xi = fp2_mul_xi_1_1iC;
- } else {
- mul_xi = fp2_mul_xiC;
- }
- }
- FpDblT<Fp>::init();
- Fp2DblT<Fp>::init();
- // call init before Fp2::pow because FpDbl is used in Fp2T
- const Fp2T xi(op.xi_a, 1);
- const mpz_class& p = Fp::getOp().mp;
- Fp2T::pow(g[0], xi, (p - 1) / 6); // g = xi^((p-1)/6)
- for (size_t i = 1; i < gN; i++) {
- g[i] = g[i - 1] * g[0];
- }
- /*
- permutate [0, 1, 2, 3, 4] => [1, 3, 0, 2, 4]
- g[0] = g^2
- g[1] = g^4
- g[2] = g^1
- g[3] = g^3
- g[4] = g^5
- */
- {
- Fp2T t = g[0];
- g[0] = g[1];
- g[1] = g[3];
- g[3] = g[2];
- g[2] = t;
- }
- for (size_t i = 0; i < gN; i++) {
- Fp2T t(g[i].a, g[i].b);
- if (Fp::getOp().pmod4 == 3) Fp::neg(t.b, t.b);
- Fp2T::mul(g2[i], t, g[i]);
- g3[i] = g[i] * g2[i];
- }
- }
-#ifndef CYBOZU_DONT_USE_EXCEPTION
- template<class InputStream>
- void load(InputStream& is, int ioMode = IoSerialize)
- {
- bool b;
- load(&b, is, ioMode);
- if (!b) throw cybozu::Exception("Fp2T:load");
- }
- template<class OutputStream>
- void save(OutputStream& os, int ioMode = IoSerialize) const
- {
- bool b;
- save(&b, os, ioMode);
- if (!b) throw cybozu::Exception("Fp2T:save");
- }
- template<class S>
- void setArray(const S *buf, size_t n)
- {
- bool b;
- setArray(&b, buf, n);
- if (!b) throw cybozu::Exception("Fp2T:setArray");
- }
-#endif
-#ifndef CYBOZU_DONT_USE_STRING
- Fp2T(const std::string& a, const std::string& b, int base = 0) : a(a, base), b(b, base) {}
- friend std::istream& operator>>(std::istream& is, Fp2T& self)
- {
- self.load(is, fp::detectIoMode(Fp::BaseFp::getIoMode(), is));
- return is;
- }
- friend std::ostream& operator<<(std::ostream& os, const Fp2T& self)
- {
- self.save(os, fp::detectIoMode(Fp::BaseFp::getIoMode(), os));
- return os;
- }
-#endif
-private:
- /*
- default Fp2T operator
- Fp2T = Fp[i]/(i^2 + 1)
- */
- static void addC(Fp2T& z, const Fp2T& x, const Fp2T& y)
- {
- Fp::add(z.a, x.a, y.a);
- Fp::add(z.b, x.b, y.b);
- }
- static void subC(Fp2T& z, const Fp2T& x, const Fp2T& y)
- {
- Fp::sub(z.a, x.a, y.a);
- Fp::sub(z.b, x.b, y.b);
- }
- static void negC(Fp2T& y, const Fp2T& x)
- {
- Fp::neg(y.a, x.a);
- Fp::neg(y.b, x.b);
- }
-#if 0
- /*
- x = a + bi, y = c + di, i^2 = -1
- z = xy = (a + bi)(c + di) = (ac - bd) + (ad + bc)i
- ad+bc = (a + b)(c + d) - ac - bd
- # of mod = 3
- */
- static void fp2_mulW(Unit *z, const Unit *x, const Unit *y)
- {
- const Fp *px = reinterpret_cast<const Fp*>(x);
- const Fp *py = reinterpret_cast<const Fp*>(y);
- const Fp& a = px[0];
- const Fp& b = px[1];
- const Fp& c = py[0];
- const Fp& d = py[1];
- Fp *pz = reinterpret_cast<Fp*>(z);
- Fp t1, t2, ac, bd;
- Fp::add(t1, a, b);
- Fp::add(t2, c, d);
- t1 *= t2; // (a + b)(c + d)
- Fp::mul(ac, a, c);
- Fp::mul(bd, b, d);
- Fp::sub(pz[0], ac, bd); // ac - bd
- Fp::sub(pz[1], t1, ac);
- pz[1] -= bd;
- }
- static void fp2_mulNFW(Fp2T& z, const Fp2T& x, const Fp2T& y)
- {
- const fp::Op& op = Fp::op_;
- op.fp2_mulNF((Unit*)&z, (const Unit*)&x, (const Unit*)&y, op.p);
- }
-#endif
- static void mulC(Fp2T& z, const Fp2T& x, const Fp2T& y)
- {
- Fp2Dbl d;
- Fp2Dbl::mulPre(d, x, y);
- FpDbl::mod(z.a, d.a);
- FpDbl::mod(z.b, d.b);
- }
- /*
- x = a + bi, i^2 = -1
- y = x^2 = (a + bi)^2 = (a + b)(a - b) + 2abi
- */
- static void sqrC(Fp2T& y, const Fp2T& x)
- {
- const Fp& a = x.a;
- const Fp& b = x.b;
-#if 1 // faster than using FpDbl
- Fp t1, t2, t3;
- Fp::add(t1, b, b); // 2b
- t1 *= a; // 2ab
- Fp::add(t2, a, b); // a + b
- Fp::sub(t3, a, b); // a - b
- Fp::mul(y.a, t2, t3); // (a + b)(a - b)
- y.b = t1;
-#else
- Fp t1, t2;
- FpDbl d1, d2;
- Fp::addPre(t1, b, b); // 2b
- FpDbl::mulPre(d2, t1, a); // 2ab
- Fp::addPre(t1, a, b); // a + b
- Fp::sub(t2, a, b); // a - b
- FpDbl::mulPre(d1, t1, t2); // (a + b)(a - b)
- FpDbl::mod(py[0], d1);
- FpDbl::mod(py[1], d2);
-#endif
- }
- /*
- xi = xi_a + i
- x = a + bi
- y = (a + bi)xi = (a + bi)(xi_a + i)
- =(a * x_ia - b) + (a + b xi_a)i
- */
- static void fp2_mul_xiC(Fp2T& y, const Fp2T& x)
- {
- const Fp& a = x.a;
- const Fp& b = x.b;
- Fp t;
- Fp::mulUnit(t, a, Fp::getOp().xi_a);
- t -= b;
- Fp::mulUnit(y.b, b, Fp::getOp().xi_a);
- y.b += a;
- y.a = t;
- }
- /*
- xi = 1 + i ; xi_a = 1
- y = (a + bi)xi = (a - b) + (a + b)i
- */
- static void fp2_mul_xi_1_1iC(Fp2T& y, const Fp2T& x)
- {
- const Fp& a = x.a;
- const Fp& b = x.b;
- Fp t;
- Fp::add(t, a, b);
- Fp::sub(y.a, a, b);
- y.b = t;
- }
- /*
- x = a + bi
- 1 / x = (a - bi) / (a^2 + b^2)
- */
- static void fp2_invW(Unit *y, const Unit *x)
- {
- const Fp *px = reinterpret_cast<const Fp*>(x);
- Fp *py = reinterpret_cast<Fp*>(y);
- const Fp& a = px[0];
- const Fp& b = px[1];
- Fp aa, bb;
- Fp::sqr(aa, a);
- Fp::sqr(bb, b);
- aa += bb;
- Fp::inv(aa, aa); // aa = 1 / (a^2 + b^2)
- Fp::mul(py[0], a, aa);
- Fp::mul(py[1], b, aa);
- Fp::neg(py[1], py[1]);
- }
-};
-
-#ifdef MCL_XBYAK_DIRECT_CALL
-template<class Fp_> void (*Fp2T<Fp_>::add)(Fp2T& z, const Fp2T& x, const Fp2T& y);
-template<class Fp_> void (*Fp2T<Fp_>::sub)(Fp2T& z, const Fp2T& x, const Fp2T& y);
-template<class Fp_> void (*Fp2T<Fp_>::neg)(Fp2T& y, const Fp2T& x);
-template<class Fp_> void (*Fp2T<Fp_>::mul)(Fp2T& z, const Fp2T& x, const Fp2T& y);
-template<class Fp_> void (*Fp2T<Fp_>::sqr)(Fp2T& y, const Fp2T& x);
-#endif
-template<class Fp_> void (*Fp2T<Fp_>::mul_xi)(Fp2T& y, const Fp2T& x);
-
-template<class Fp>
-struct Fp2DblT {
- typedef FpDblT<Fp> FpDbl;
- typedef Fp2T<Fp> Fp2;
- typedef fp::Unit Unit;
- FpDbl a, b;
- static void add(Fp2DblT& z, const Fp2DblT& x, const Fp2DblT& y)
- {
- FpDbl::add(z.a, x.a, y.a);
- FpDbl::add(z.b, x.b, y.b);
- }
- static void addPre(Fp2DblT& z, const Fp2DblT& x, const Fp2DblT& y)
- {
- FpDbl::addPre(z.a, x.a, y.a);
- FpDbl::addPre(z.b, x.b, y.b);
- }
- static void sub(Fp2DblT& z, const Fp2DblT& x, const Fp2DblT& y)
- {
- FpDbl::sub(z.a, x.a, y.a);
- FpDbl::sub(z.b, x.b, y.b);
- }
- static void subPre(Fp2DblT& z, const Fp2DblT& x, const Fp2DblT& y)
- {
- FpDbl::subPre(z.a, x.a, y.a);
- FpDbl::subPre(z.b, x.b, y.b);
- }
- static void neg(Fp2DblT& y, const Fp2DblT& x)
- {
- FpDbl::neg(y.a, x.a);
- FpDbl::neg(y.b, x.b);
- }
- static void mul_xi(Fp2DblT& y, const Fp2DblT& x)
- {
- const uint32_t xi_a = Fp2::get_xi_a();
- if (xi_a == 1) {
- FpDbl t;
- FpDbl::add(t, x.a, x.b);
- FpDbl::sub(y.a, x.a, x.b);
- y.b = t;
- } else {
- FpDbl t;
- FpDbl::mulUnit(t, x.a, xi_a);
- FpDbl::sub(t, t, x.b);
- FpDbl::mulUnit(y.b, x.b, xi_a);
- FpDbl::add(y.b, y.b, x.a);
- y.a = t;
- }
- }
- static void (*mulPre)(Fp2DblT&, const Fp2&, const Fp2&);
- static void (*sqrPre)(Fp2DblT&, const Fp2&);
- static void mod(Fp2& y, const Fp2DblT& x)
- {
- FpDbl::mod(y.a, x.a);
- FpDbl::mod(y.b, x.b);
- }
-#ifndef CYBOZU_DONT_USE_STRING
- friend std::ostream& operator<<(std::ostream& os, const Fp2DblT& x)
- {
- return os << x.a << ' ' << x.b;
- }
-#endif
- void operator+=(const Fp2DblT& x) { add(*this, *this, x); }
- void operator-=(const Fp2DblT& x) { sub(*this, *this, x); }
- static void init()
- {
- const mcl::fp::Op& op = Fp::getOp();
- if (op.fp2Dbl_mulPreA_) {
- mulPre = fp::func_ptr_cast<void (*)(Fp2DblT&, const Fp2&, const Fp2&)>(op.fp2Dbl_mulPreA_);
- } else {
- if (op.isFullBit) {
- mulPre = fp2Dbl_mulPreW<true>;
- } else {
- mulPre = fp2Dbl_mulPreW<false>;
- }
- }
- if (op.fp2Dbl_sqrPreA_) {
- sqrPre = fp::func_ptr_cast<void (*)(Fp2DblT&, const Fp2&)>(op.fp2Dbl_sqrPreA_);
- } else {
- if (op.isFullBit) {
- sqrPre = fp2Dbl_sqrPreW<true>;
- } else {
- sqrPre = fp2Dbl_sqrPreW<false>;
- }
- }
- }
- /*
- Fp2Dbl::mulPre by FpDblT
- @note mod of NIST_P192 is fast
- */
- template<bool isFullBit>
- static void fp2Dbl_mulPreW(Fp2DblT& z, const Fp2& x, const Fp2& y)
- {
- const Fp& a = x.a;
- const Fp& b = x.b;
- const Fp& c = y.a;
- const Fp& d = y.b;
- FpDbl& d0 = z.a;
- FpDbl& d1 = z.b;
- FpDbl d2;
- Fp s, t;
- if (isFullBit) {
- Fp::add(s, a, b);
- Fp::add(t, c, d);
- } else {
- Fp::addPre(s, a, b);
- Fp::addPre(t, c, d);
- }
- FpDbl::mulPre(d1, s, t); // (a + b)(c + d)
- FpDbl::mulPre(d0, a, c);
- FpDbl::mulPre(d2, b, d);
- if (isFullBit) {
- FpDbl::sub(d1, d1, d0); // (a + b)(c + d) - ac
- FpDbl::sub(d1, d1, d2); // (a + b)(c + d) - ac - bd
- } else {
- FpDbl::subPre(d1, d1, d0);
- FpDbl::subPre(d1, d1, d2);
- }
- FpDbl::sub(d0, d0, d2); // ac - bd
- }
- template<bool isFullBit>
- static void fp2Dbl_sqrPreW(Fp2DblT& y, const Fp2& x)
- {
- Fp t1, t2;
- if (isFullBit) {
- Fp::add(t1, x.b, x.b); // 2b
- Fp::add(t2, x.a, x.b); // a + b
- } else {
- Fp::addPre(t1, x.b, x.b); // 2b
- Fp::addPre(t2, x.a, x.b); // a + b
- }
- FpDbl::mulPre(y.b, t1, x.a); // 2ab
- Fp::sub(t1, x.a, x.b); // a - b
- FpDbl::mulPre(y.a, t1, t2); // (a + b)(a - b)
- }
-};
-
-template<class Fp> void (*Fp2DblT<Fp>::mulPre)(Fp2DblT&, const Fp2T<Fp>&, const Fp2T<Fp>&);
-template<class Fp> void (*Fp2DblT<Fp>::sqrPre)(Fp2DblT&, const Fp2T<Fp>&);
-
-template<class Fp> Fp2T<Fp> Fp2T<Fp>::g[Fp2T<Fp>::gN];
-template<class Fp> Fp2T<Fp> Fp2T<Fp>::g2[Fp2T<Fp>::gN];
-template<class Fp> Fp2T<Fp> Fp2T<Fp>::g3[Fp2T<Fp>::gN];
-
-template<class Fp>
-struct Fp6DblT;
-/*
- Fp6T = Fp2[v] / (v^3 - xi)
- x = a + b v + c v^2
-*/
-template<class _Fp>
-struct Fp6T : public fp::Serializable<Fp6T<_Fp>,
- fp::Operator<Fp6T<_Fp> > > {
- typedef _Fp Fp;
- typedef Fp2T<Fp> Fp2;
- typedef Fp2DblT<Fp> Fp2Dbl;
- typedef Fp6DblT<Fp> Fp6Dbl;
- typedef Fp BaseFp;
- Fp2 a, b, c;
- Fp6T() { }
- Fp6T(int64_t a) : a(a) , b(0) , c(0) { }
- Fp6T(const Fp2& a, const Fp2& b, const Fp2& c) : a(a) , b(b) , c(c) { }
- void clear()
- {
- a.clear();
- b.clear();
- c.clear();
- }
- Fp* getFp0() { return a.getFp0(); }
- const Fp* getFp0() const { return a.getFp0(); }
- Fp2* getFp2() { return &a; }
- const Fp2* getFp2() const { return &a; }
- void set(const Fp2 &a_, const Fp2 &b_, const Fp2 &c_)
- {
- a = a_;
- b = b_;
- c = c_;
- }
- bool isZero() const
- {
- return a.isZero() && b.isZero() && c.isZero();
- }
- bool isOne() const
- {
- return a.isOne() && b.isZero() && c.isZero();
- }
- bool operator==(const Fp6T& rhs) const
- {
- return a == rhs.a && b == rhs.b && c == rhs.c;
- }
- bool operator!=(const Fp6T& rhs) const { return !operator==(rhs); }
- template<class InputStream>
- void load(bool *pb, InputStream& is, int ioMode)
- {
- a.load(pb, is, ioMode); if (!*pb) return;
- b.load(pb, is, ioMode); if (!*pb) return;
- c.load(pb, is, ioMode); if (!*pb) return;
- }
- template<class OutputStream>
- void save(bool *pb, OutputStream& os, int ioMode) const
- {
- const char sep = *fp::getIoSeparator(ioMode);
- a.save(pb, os, ioMode); if (!*pb) return;
- if (sep) {
- cybozu::writeChar(pb, os, sep);
- if (!*pb) return;
- }
- b.save(pb, os, ioMode); if (!*pb) return;
- if (sep) {
- cybozu::writeChar(pb, os, sep);
- if (!*pb) return;
- }
- c.save(pb, os, ioMode);
- }
-#ifndef CYBOZU_DONT_USE_EXCEPTION
- template<class InputStream>
- void load(InputStream& is, int ioMode = IoSerialize)
- {
- bool b;
- load(&b, is, ioMode);
- if (!b) throw cybozu::Exception("Fp6T:load");
- }
- template<class OutputStream>
- void save(OutputStream& os, int ioMode = IoSerialize) const
- {
- bool b;
- save(&b, os, ioMode);
- if (!b) throw cybozu::Exception("Fp6T:save");
- }
-#endif
-#ifndef CYBOZU_DONT_USE_STRING
- friend std::istream& operator>>(std::istream& is, Fp6T& self)
- {
- self.load(is, fp::detectIoMode(Fp::BaseFp::getIoMode(), is));
- return is;
- }
- friend std::ostream& operator<<(std::ostream& os, const Fp6T& self)
- {
- self.save(os, fp::detectIoMode(Fp::BaseFp::getIoMode(), os));
- return os;
- }
-#endif
- static void add(Fp6T& z, const Fp6T& x, const Fp6T& y)
- {
- Fp2::add(z.a, x.a, y.a);
- Fp2::add(z.b, x.b, y.b);
- Fp2::add(z.c, x.c, y.c);
- }
- static void sub(Fp6T& z, const Fp6T& x, const Fp6T& y)
- {
- Fp2::sub(z.a, x.a, y.a);
- Fp2::sub(z.b, x.b, y.b);
- Fp2::sub(z.c, x.c, y.c);
- }
- static void neg(Fp6T& y, const Fp6T& x)
- {
- Fp2::neg(y.a, x.a);
- Fp2::neg(y.b, x.b);
- Fp2::neg(y.c, x.c);
- }
- /*
- x = a + bv + cv^2, v^3 = xi
- x^2 = (a^2 + 2bc xi) + (c^2 xi + 2ab)v + (b^2 + 2ac)v^2
-
- b^2 + 2ac = (a + b + c)^2 - a^2 - 2bc - c^2 - 2ab
- */
- static void sqr(Fp6T& y, const Fp6T& x)
- {
- Fp2 t1, t2, t3;
- Fp2::mul(t1, x.a, x.b);
- t1 += t1; // 2ab
- Fp2::mul(t2, x.b, x.c);
- t2 += t2; // 2bc
- Fp2::sqr(t3, x.c); // c^2
- Fp2::add(y.c, x.a, x.c); // a + c, destroy y.c
- y.c += x.b; // a + b + c
- Fp2::sqr(y.b, y.c); // (a + b + c)^2, destroy y.b
- y.b -= t2; // (a + b + c)^2 - 2bc
- Fp2::mul_xi(t2, t2); // 2bc xi
- Fp2::sqr(y.a, x.a); // a^2, destroy y.a
- y.b -= y.a; // (a + b + c)^2 - 2bc - a^2
- y.a += t2; // a^2 + 2bc xi
- Fp2::sub(y.c, y.b, t3); // (a + b + c)^2 - 2bc - a^2 - c^2
- Fp2::mul_xi(y.b, t3); // c^2 xi
- y.b += t1; // c^2 xi + 2ab
- y.c -= t1; // b^2 + 2ac
- }
- static inline void mul(Fp6T& z, const Fp6T& x, const Fp6T& y);
- /*
- x = a + bv + cv^2, v^3 = xi
- y = 1/x = p/q where
- p = (a^2 - bc xi) + (c^2 xi - ab)v + (b^2 - ac)v^2
- q = c^3 xi^2 + b(b^2 - 3ac)xi + a^3
- = (a^2 - bc xi)a + ((c^2 xi - ab)c + (b^2 - ac)b) xi
- */
- static void inv(Fp6T& y, const Fp6T& x)
- {
- const Fp2& a = x.a;
- const Fp2& b = x.b;
- const Fp2& c = x.c;
- Fp2 aa, bb, cc, ab, bc, ac;
- Fp2::sqr(aa, a);
- Fp2::sqr(bb, b);
- Fp2::sqr(cc, c);
- Fp2::mul(ab, a, b);
- Fp2::mul(bc, b, c);
- Fp2::mul(ac, c, a);
-
- Fp6T p;
- Fp2::mul_xi(p.a, bc);
- Fp2::sub(p.a, aa, p.a); // a^2 - bc xi
- Fp2::mul_xi(p.b, cc);
- p.b -= ab; // c^2 xi - ab
- Fp2::sub(p.c, bb, ac); // b^2 - ac
- Fp2 q, t;
- Fp2::mul(q, p.b, c);
- Fp2::mul(t, p.c, b);
- q += t;
- Fp2::mul_xi(q, q);
- Fp2::mul(t, p.a, a);
- q += t;
- Fp2::inv(q, q);
-
- Fp2::mul(y.a, p.a, q);
- Fp2::mul(y.b, p.b, q);
- Fp2::mul(y.c, p.c, q);
- }
-};
-
-template<class Fp>
-struct Fp6DblT {
- typedef Fp2T<Fp> Fp2;
- typedef Fp6T<Fp> Fp6;
- typedef Fp2DblT<Fp> Fp2Dbl;
- typedef Fp6DblT<Fp> Fp6Dbl;
- typedef fp::Unit Unit;
- Fp2Dbl a, b, c;
- static void add(Fp6Dbl& z, const Fp6Dbl& x, const Fp6Dbl& y)
- {
- Fp2Dbl::add(z.a, x.a, y.a);
- Fp2Dbl::add(z.b, x.b, y.b);
- Fp2Dbl::add(z.c, x.c, y.c);
- }
- static void sub(Fp6Dbl& z, const Fp6Dbl& x, const Fp6Dbl& y)
- {
- Fp2Dbl::sub(z.a, x.a, y.a);
- Fp2Dbl::sub(z.b, x.b, y.b);
- Fp2Dbl::sub(z.c, x.c, y.c);
- }
- /*
- x = a + bv + cv^2, y = d + ev + fv^2, v^3 = xi
- xy = (ad + (bf + ce)xi) + ((ae + bd) + cf xi)v + ((af + cd) + be)v^2
- bf + ce = (b + c)(e + f) - be - cf
- ae + bd = (a + b)(e + d) - ad - be
- af + cd = (a + c)(d + f) - ad - cf
- */
- static void mulPre(Fp6DblT& z, const Fp6& x, const Fp6& y)
- {
-//clk.begin();
- const Fp2& a = x.a;
- const Fp2& b = x.b;
- const Fp2& c = x.c;
- const Fp2& d = y.a;
- const Fp2& e = y.b;
- const Fp2& f = y.c;
- Fp2Dbl& za = z.a;
- Fp2Dbl& zb = z.b;
- Fp2Dbl& zc = z.c;
- Fp2Dbl BE;
- Fp2Dbl::mulPre(za, a, d);
- Fp2Dbl::mulPre(BE, b, e);
- Fp2Dbl::mulPre(zb, c, f);
-
- Fp2 t1, t2, t3, t4;
- Fp2::add(t1, b, c);
- Fp2::add(t2, e, f);
- Fp2Dbl T1;
- Fp2Dbl::mulPre(T1, t1, t2);
- Fp2Dbl::sub(T1, T1, BE);
- Fp2Dbl::sub(T1, T1, zb);
- Fp2Dbl::mul_xi(T1, T1);
-
- Fp2::add(t2, a, b);
- Fp2::add(t3, e, d);
- Fp2Dbl T2;
- Fp2Dbl::mulPre(T2, t2, t3);
- Fp2Dbl::sub(T2, T2, za);
- Fp2Dbl::sub(T2, T2, BE);
-
- Fp2::add(t3, a, c);
- Fp2::add(t4, d, f);
- Fp2Dbl::mulPre(zc, t3, t4);
- Fp2Dbl::sub(zc, zc, za);
- Fp2Dbl::sub(zc, zc, zb);
-
- Fp2Dbl::add(za, za, T1);
- Fp2Dbl::mul_xi(zb, zb);
- Fp2Dbl::add(zb, zb, T2);
- Fp2Dbl::add(zc, zc, BE);
-//clk.end();
- }
- static void mod(Fp6& y, const Fp6Dbl& x)
- {
- Fp2Dbl::mod(y.a, x.a);
- Fp2Dbl::mod(y.b, x.b);
- Fp2Dbl::mod(y.c, x.c);
- }
-};
-
-template<class Fp>
-inline void Fp6T<Fp>::mul(Fp6T<Fp>& z, const Fp6T<Fp>& x, const Fp6T<Fp>& y)
-{
- Fp6DblT<Fp> Z;
- Fp6DblT<Fp>::mulPre(Z, x, y);
- Fp6DblT<Fp>::mod(z, Z);
-}
-
-/*
- Fp12T = Fp6[w] / (w^2 - v)
- x = a + b w
-*/
-template<class Fp>
-struct Fp12T : public fp::Serializable<Fp12T<Fp>,
- fp::Operator<Fp12T<Fp> > > {
- typedef Fp2T<Fp> Fp2;
- typedef Fp6T<Fp> Fp6;
- typedef Fp2DblT<Fp> Fp2Dbl;
- typedef Fp6DblT<Fp> Fp6Dbl;
- typedef Fp BaseFp;
- Fp6 a, b;
- Fp12T() {}
- Fp12T(int64_t a) : a(a), b(0) {}
- Fp12T(const Fp6& a, const Fp6& b) : a(a), b(b) {}
- void clear()
- {
- a.clear();
- b.clear();
- }
- void setOne()
- {
- clear();
- a.a.a = 1;
- }
-
- Fp* getFp0() { return a.getFp0(); }
- const Fp* getFp0() const { return a.getFp0(); }
- Fp2* getFp2() { return a.getFp2(); }
- const Fp2* getFp2() const { return a.getFp2(); }
- void set(const Fp2& v0, const Fp2& v1, const Fp2& v2, const Fp2& v3, const Fp2& v4, const Fp2& v5)
- {
- a.set(v0, v1, v2);
- b.set(v3, v4, v5);
- }
-
- bool isZero() const
- {
- return a.isZero() && b.isZero();
- }
- bool isOne() const
- {
- return a.isOne() && b.isZero();
- }
- bool operator==(const Fp12T& rhs) const
- {
- return a == rhs.a && b == rhs.b;
- }
- bool operator!=(const Fp12T& rhs) const { return !operator==(rhs); }
- static void add(Fp12T& z, const Fp12T& x, const Fp12T& y)
- {
- Fp6::add(z.a, x.a, y.a);
- Fp6::add(z.b, x.b, y.b);
- }
- static void sub(Fp12T& z, const Fp12T& x, const Fp12T& y)
- {
- Fp6::sub(z.a, x.a, y.a);
- Fp6::sub(z.b, x.b, y.b);
- }
- static void neg(Fp12T& z, const Fp12T& x)
- {
- Fp6::neg(z.a, x.a);
- Fp6::neg(z.b, x.b);
- }
- /*
- z = x v + y
- in Fp6 : (a + bv + cv^2)v = cv^3 + av + bv^2 = cxi + av + bv^2
- */
- static void mulVadd(Fp6& z, const Fp6& x, const Fp6& y)
- {
- Fp2 t;
- Fp2::mul_xi(t, x.c);
- Fp2::add(z.c, x.b, y.c);
- Fp2::add(z.b, x.a, y.b);
- Fp2::add(z.a, t, y.a);
- }
- static void mulVadd(Fp6Dbl& z, const Fp6Dbl& x, const Fp6Dbl& y)
- {
- Fp2Dbl t;
- Fp2Dbl::mul_xi(t, x.c);
- Fp2Dbl::add(z.c, x.b, y.c);
- Fp2Dbl::add(z.b, x.a, y.b);
- Fp2Dbl::add(z.a, t, y.a);
- }
- /*
- x = a + bw, y = c + dw, w^2 = v
- z = xy = (a + bw)(c + dw) = (ac + bdv) + (ad + bc)w
- ad+bc = (a + b)(c + d) - ac - bd
-
- in Fp6 : (a + bv + cv^2)v = cv^3 + av + bv^2 = cxi + av + bv^2
- */
- static void mul(Fp12T& z, const Fp12T& x, const Fp12T& y)
- {
- // 4.7Kclk -> 4.55Kclk
- const Fp6& a = x.a;
- const Fp6& b = x.b;
- const Fp6& c = y.a;
- const Fp6& d = y.b;
- Fp6 t1, t2;
- Fp6::add(t1, a, b);
- Fp6::add(t2, c, d);
-#if 1
- Fp6Dbl T, AC, BD;
- Fp6Dbl::mulPre(AC, a, c);
- Fp6Dbl::mulPre(BD, b, d);
- mulVadd(T, BD, AC);
- Fp6Dbl::mod(z.a, T);
- Fp6Dbl::mulPre(T, t1, t2); // (a + b)(c + d)
- Fp6Dbl::sub(T, T, AC);
- Fp6Dbl::sub(T, T, BD);
- Fp6Dbl::mod(z.b, T);
-#else
- Fp6 ac, bd;
- t1 *= t2; // (a + b)(c + d)
- Fp6::mul(ac, a, c);
- Fp6::mul(bd, b, d);
- mulVadd(z.a, bd, ac);
- t1 -= ac;
- Fp6::sub(z.b, t1, bd);
-#endif
- }
- /*
- x = a + bw, w^2 = v
- y = x^2 = (a + bw)^2 = (a^2 + b^2v) + 2abw
- a^2 + b^2v = (a + b)(bv + a) - (abv + ab)
- */
- static void sqr(Fp12T& y, const Fp12T& x)
- {
- const Fp6& a = x.a;
- const Fp6& b = x.b;
- Fp6 t0, t1;
- Fp6::add(t0, a, b); // a + b
- mulVadd(t1, b, a); // bv + a
- t0 *= t1; // (a + b)(bv + a)
- Fp6::mul(t1, a, b); // ab
- Fp6::add(y.b, t1, t1); // 2ab
- mulVadd(y.a, t1, t1); // abv + ab
- Fp6::sub(y.a, t0, y.a);
- }
- /*
- x = a + bw, w^2 = v
- y = 1/x = (a - bw) / (a^2 - b^2v)
- */
- static void inv(Fp12T& y, const Fp12T& x)
- {
- const Fp6& a = x.a;
- const Fp6& b = x.b;
- Fp6 t0, t1;
- Fp6::sqr(t0, a);
- Fp6::sqr(t1, b);
- Fp2::mul_xi(t1.c, t1.c);
- t0.a -= t1.c;
- t0.b -= t1.a;
- t0.c -= t1.b; // t0 = a^2 - b^2v
- Fp6::inv(t0, t0);
- Fp6::mul(y.a, x.a, t0);
- Fp6::mul(y.b, x.b, t0);
- Fp6::neg(y.b, y.b);
- }
- /*
- y = 1 / x = conjugate of x if |x| = 1
- */
- static void unitaryInv(Fp12T& y, const Fp12T& x)
- {
- if (&y != &x) y.a = x.a;
- Fp6::neg(y.b, x.b);
- }
- /*
- Frobenius
- i^2 = -1
- (a + bi)^p = a + bi^p in Fp
- = a + bi if p = 1 mod 4
- = a - bi if p = 3 mod 4
-
- g = xi^(p - 1) / 6
- v^3 = xi in Fp2
- v^p = ((v^6) ^ (p-1)/6) v = g^2 v
- v^2p = g^4 v^2
- (a + bv + cv^2)^p in Fp6
- = F(a) + F(b)g^2 v + F(c) g^4 v^2
-
- w^p = ((w^6) ^ (p-1)/6) w = g w
- ((a + bv + cv^2)w)^p in Fp12T
- = (F(a) g + F(b) g^3 v + F(c) g^5 v^2)w
- */
- static void Frobenius(Fp12T& y, const Fp12T& x)
- {
- for (int i = 0; i < 6; i++) {
- Fp2::Frobenius(y.getFp2()[i], x.getFp2()[i]);
- }
- for (int i = 1; i < 6; i++) {
- y.getFp2()[i] *= Fp2::get_gTbl()[i - 1];
- }
- }
- static void Frobenius2(Fp12T& y, const Fp12T& x)
- {
-#if 0
- Frobenius(y, x);
- Frobenius(y, y);
-#else
- y.getFp2()[0] = x.getFp2()[0];
- if (Fp::getOp().pmod4 == 1) {
- for (int i = 1; i < 6; i++) {
- Fp2::mul(y.getFp2()[i], x.getFp2()[i], Fp2::get_g2Tbl()[i]);
- }
- } else {
- for (int i = 1; i < 6; i++) {
- Fp2::mulFp(y.getFp2()[i], x.getFp2()[i], Fp2::get_g2Tbl()[i - 1].a);
- }
- }
-#endif
- }
- static void Frobenius3(Fp12T& y, const Fp12T& x)
- {
-#if 0
- Frobenius(y, x);
- Frobenius(y, y);
- Frobenius(y, y);
-#else
- Fp2::Frobenius(y.getFp2()[0], x.getFp2()[0]);
- for (int i = 1; i < 6; i++) {
- Fp2::Frobenius(y.getFp2()[i], x.getFp2()[i]);
- y.getFp2()[i] *= Fp2::get_g3Tbl()[i - 1];
- }
-#endif
- }
- template<class InputStream>
- void load(bool *pb, InputStream& is, int ioMode)
- {
- a.load(pb, is, ioMode); if (!*pb) return;
- b.load(pb, is, ioMode);
- }
- template<class OutputStream>
- void save(bool *pb, OutputStream& os, int ioMode) const
- {
- const char sep = *fp::getIoSeparator(ioMode);
- a.save(pb, os, ioMode); if (!*pb) return;
- if (sep) {
- cybozu::writeChar(pb, os, sep);
- if (!*pb) return;
- }
- b.save(pb, os, ioMode);
- }
-#ifndef CYBOZU_DONT_USE_EXCEPTION
- template<class InputStream>
- void load(InputStream& is, int ioMode = IoSerialize)
- {
- bool b;
- load(&b, is, ioMode);
- if (!b) throw cybozu::Exception("Fp12T:load");
- }
- template<class OutputStream>
- void save(OutputStream& os, int ioMode = IoSerialize) const
- {
- bool b;
- save(&b, os, ioMode);
- if (!b) throw cybozu::Exception("Fp12T:save");
- }
-#endif
-#ifndef CYBOZU_DONT_USE_STRING
- friend std::istream& operator>>(std::istream& is, Fp12T& self)
- {
- self.load(is, fp::detectIoMode(Fp::BaseFp::getIoMode(), is));
- return is;
- }
- friend std::ostream& operator<<(std::ostream& os, const Fp12T& self)
- {
- self.save(os, fp::detectIoMode(Fp::BaseFp::getIoMode(), os));
- return os;
- }
-#endif
-};
-
-/*
- convert multiplicative group to additive group
-*/
-template<class T>
-struct GroupMtoA : public T {
- static T& castT(GroupMtoA& x) { return static_cast<T&>(x); }
- static const T& castT(const GroupMtoA& x) { return static_cast<const T&>(x); }
- void clear()
- {
- castT(*this) = 1;
- }
- bool isZero() const { return castT(*this).isOne(); }
- static void add(GroupMtoA& z, const GroupMtoA& x, const GroupMtoA& y)
- {
- T::mul(castT(z), castT(x), castT(y));
- }
- static void dbl(GroupMtoA& y, const GroupMtoA& x)
- {
- T::sqr(castT(y), castT(x));
- }
- static void neg(GroupMtoA& y, const GroupMtoA& x)
- {
- // assume Fp12
- T::unitaryInv(castT(y), castT(x));
- }
- static void Frobenus(GroupMtoA& y, const GroupMtoA& x)
- {
- T::Frobenius(castT(y), castT(x));
- }
- template<class INT>
- static void mul(GroupMtoA& z, const GroupMtoA& x, const INT& y)
- {
- T::pow(castT(z), castT(x), y);
- }
- template<class INT>
- static void mulGeneric(GroupMtoA& z, const GroupMtoA& x, const INT& y)
- {
- T::powGeneric(castT(z), castT(x), y);
- }
- void operator+=(const GroupMtoA& rhs)
- {
- add(*this, *this, rhs);
- }
- void normalize() {}
-private:
- bool isOne() const;
-};
-
-} // mcl
-