diff options
author | MITSUNARI Shigeo <herumi@nifty.com> | 2019-03-14 14:25:05 +0800 |
---|---|---|
committer | MITSUNARI Shigeo <herumi@nifty.com> | 2019-03-14 15:47:00 +0800 |
commit | ed6ad685c2096769d5e7672dddad09b04d7eecde (patch) | |
tree | 0e663e585ca16fecf1db68ec7e9b5a36387c4e22 | |
parent | 54f2e8cc85d017945a47629d1986c29c291cf6eb (diff) | |
download | dexon-mcl-ed6ad685c2096769d5e7672dddad09b04d7eecde.tar.gz dexon-mcl-ed6ad685c2096769d5e7672dddad09b04d7eecde.tar.zst dexon-mcl-ed6ad685c2096769d5e7672dddad09b04d7eecde.zip |
Modp supports mcl-wasm
-rw-r--r-- | include/mcl/gmp_util.hpp | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/include/mcl/gmp_util.hpp b/include/mcl/gmp_util.hpp index c2f1859..bcbd91a 100644 --- a/include/mcl/gmp_util.hpp +++ b/include/mcl/gmp_util.hpp @@ -871,6 +871,13 @@ struct Modp { mpz_class a_; size_t pBitSize_; size_t N_; + bool initU_; // Is u_ initialized? + Modp() + : pBitSize_(0) + , N_(0) + , initU_(false) + { + } // x &= 1 << (unitBitSize * unitSize) void shrinkSize(mpz_class &x, size_t unitSize) const { @@ -878,24 +885,49 @@ struct Modp { if (u < unitSize) return; bool b; gmp::setArray(&b, x, gmp::getUnit(x), unitSize); + (void)b; assert(b); } + // p_ is set by p and compute (u_, a_) if possible void init(const mpz_class& p) { p_ = p; pBitSize_ = gmp::getBitSize(p); N_ = (pBitSize_ + unitBitSize - 1) / unitBitSize; + initU_ = false; +#if 0 u_ = (mpz_class(1) << (unitBitSize * 2 * N_)) / p_; +#else + /* + 1 << (unitBitSize * 2 * N_) may be overflow, + so use (1 << (unitBitSize * 2 * N_)) - 1 because u_ is same. + */ + uint8_t buf[48 * 2]; + const size_t byteSize = unitBitSize / 8 * 2 * N_; + if (byteSize > sizeof(buf)) return; + memset(buf, 0xff, byteSize); + bool b; + gmp::setArray(&b, u_, buf, byteSize); + if (!b) return; +#endif + u_ /= p_; a_ = mpz_class(1) << (unitBitSize * (N_ + 1)); + initU_ = true; } void modp(mpz_class& r, const mpz_class& t) const { + assert(p_ > 0); const size_t tBitSize = gmp::getBitSize(t); - assert(tBitSize <= unitBitSize * 2 * N_); + // use gmp::mod if init() fails or t is too large + if (tBitSize > unitBitSize * 2 * N_ || !initU_) { + gmp::mod(r, t, p_); + return; + } if (tBitSize < pBitSize_) { r = t; return; } + // mod is faster than modp if t is small if (tBitSize <= unitBitSize * N_) { gmp::mod(r, t, p_); return; |