#define PUT(x) std::cout << #x "=" << (x) << std::endl #include #include #include #include struct ZnTag; typedef mcl::FpT Zn; typedef mcl::FpT<> Fp; struct Montgomery { typedef mcl::gmp::Unit Unit; mpz_class p_; mpz_class R_; // (1 << (pn_ * 64)) % p mpz_class RR_; // (R * R) % p Unit rp_; // rp * p = -1 mod M = 1 << 64 size_t pn_; Montgomery() {} explicit Montgomery(const mpz_class& p) { p_ = p; rp_ = mcl::fp::getMontgomeryCoeff(mcl::gmp::getUnit(p, 0)); pn_ = mcl::gmp::getUnitSize(p); R_ = 1; R_ = (R_ << (pn_ * 64)) % p_; RR_ = (R_ * R_) % p_; } void toMont(mpz_class& x) const { mul(x, x, RR_); } void fromMont(mpz_class& x) const { mul(x, x, 1); } void mul(mpz_class& z, const mpz_class& x, const mpz_class& y) const { #if 0 const size_t ySize = mcl::gmp::getUnitSize(y); mpz_class c = x * mcl::gmp::getUnit(y, 0); Unit q = mcl::gmp::getUnit(c, 0) * rp_; c += p_ * q; c >>= sizeof(Unit) * 8; for (size_t i = 1; i < pn_; i++) { if (i < ySize) { c += x * mcl::gmp::getUnit(y, i); } Unit q = mcl::gmp::getUnit(c, 0) * rp_; c += p_ * q; c >>= sizeof(Unit) * 8; } if (c >= p_) { c -= p_; } z = c; #else z = x * y; for (size_t i = 0; i < pn_; i++) { Unit q = mcl::gmp::getUnit(z, 0) * rp_; z += p_ * (mp_limb_t)q; z >>= sizeof(Unit) * 8; } if (z >= p_) { z -= p_; } #endif } }; template mpz_class getMpz(const T& x) { std::string str = x.getStr(); mpz_class t; mcl::gmp::setStr(t, str); return t; } template std::string getStr(const T& x) { std::ostringstream os; os << x; return os.str(); } template T castTo(const U& x) { T t; t.setStr(getStr(x)); return t; } template void putRaw(const T& x) { const uint64_t *p = x.getInnerValue(); for (size_t i = 0, n = T::BlockSize; i < n; i++) { printf("%016llx", p[n - 1 - i]); } printf("\n"); } template void put(const uint64_t (&x)[N]) { for (size_t i = 0; i < N; i++) { printf("%016llx", x[N - 1 - i]); } printf("\n"); } struct Test { typedef mcl::FpT<> Fp; void run(const char *p) { Fp::init(p); Fp x("-123456789"); Fp y("-0x7ffffffff"); CYBOZU_BENCH("add", operator+, x, x); CYBOZU_BENCH("sub", operator-, x, y); CYBOZU_BENCH("mul", operator*, x, x); CYBOZU_BENCH("sqr", Fp::sqr, x, x); CYBOZU_BENCH("div", y += x; operator/, x, y); } }; void customTest(const char *pStr, const char *xStr, const char *yStr) { #if 0 { pStr = "0xfffffffffffffffffffffffffffffffffffffffeffffee37", Fp::init(pStr); static uint64_t x[3] = { 1, 0, 0 }; uint64_t z[3]; std::cout<