reducing string/throw

dev
MITSUNARI Shigeo 7 years ago
parent 83b4ea2e22
commit c5e574bbfc
  1. 2
      Makefile
  2. 13
      include/mcl/bn.hpp
  3. 2
      include/mcl/conversion.hpp
  4. 173
      include/mcl/fp.hpp
  5. 162
      include/mcl/gmp_util.hpp
  6. 2
      include/mcl/operator.hpp
  7. 237
      include/mcl/vint.hpp
  8. 55
      src/fp.cpp
  9. 1
      test/fp_test.cpp
  10. 39
      test/gmp_test.cpp

@ -261,7 +261,7 @@ endif
emcc -o $@ src/fp.cpp src/she_c384.cpp $(EMCC_OPT) -DMCL_MAX_BIT_SIZE=384 -s TOTAL_MEMORY=67108864 -s DISABLE_EXCEPTION_CATCHING=0 emcc -o $@ src/fp.cpp src/she_c384.cpp $(EMCC_OPT) -DMCL_MAX_BIT_SIZE=384 -s TOTAL_MEMORY=67108864 -s DISABLE_EXCEPTION_CATCHING=0
../mcl-wasm/mcl_c.js: src/bn_c256.cpp $(MCL_C_DEP) ../mcl-wasm/mcl_c.js: src/bn_c256.cpp $(MCL_C_DEP)
emcc -o $@ src/fp.cpp src/bn_c256.cpp $(EMCC_OPT) -DMCL_MAX_BIT_SIZE=256 -DMCL_USE_WEB_CRYPTO_API -s DISABLE_EXCEPTION_CATCHING=1 emcc -o $@ src/fp.cpp src/bn_c256.cpp $(EMCC_OPT) -DMCL_MAX_BIT_SIZE=256 -DMCL_USE_WEB_CRYPTO_API -s DISABLE_EXCEPTION_CATCHING=1 #-DCYBOZU_DONT_USE_EXCEPTION -DCYBOZU_DONT_USE_STRING
../mcl-wasm/mcl_c512.js: src/bn_c512.cpp $(MCL_C_DEP) ../mcl-wasm/mcl_c512.js: src/bn_c512.cpp $(MCL_C_DEP)
emcc -o $@ src/fp.cpp src/bn_c512.cpp $(EMCC_OPT) -DMCL_MAX_BIT_SIZE=512 -DMCL_USE_WEB_CRYPTO_API -s DISABLE_EXCEPTION_CATCHING=1 emcc -o $@ src/fp.cpp src/bn_c512.cpp $(EMCC_OPT) -DMCL_MAX_BIT_SIZE=512 -DMCL_USE_WEB_CRYPTO_API -s DISABLE_EXCEPTION_CATCHING=1

@ -890,7 +890,8 @@ struct Param {
{ {
this->cp = cp; this->cp = cp;
isBLS12 = cp.curveType == MCL_BLS12_381; isBLS12 = cp.curveType == MCL_BLS12_381;
z = mpz_class(cp.z); gmp::setStr(pb, z, cp.z);
if (!*pb) return;
isNegative = z < 0; isNegative = z < 0;
if (isNegative) { if (isNegative) {
abs_z = -z; abs_z = -z;
@ -970,12 +971,14 @@ struct Param {
glv2.init(r, z, isBLS12); glv2.init(r, z, isBLS12);
*pb = true; *pb = true;
} }
#ifndef CYBOZU_DONT_EXCEPTION
void init(const mcl::CurveParam& cp, fp::Mode mode) void init(const mcl::CurveParam& cp, fp::Mode mode)
{ {
bool b; bool b;
init(&b, cp, mode); init(&b, cp, mode);
if (!b) throw cybozu::Exception("Param:init"); if (!b) throw cybozu::Exception("Param:init");
} }
#endif
}; };
template<size_t dummyImpl = 0> template<size_t dummyImpl = 0>
@ -1828,6 +1831,7 @@ inline void precomputedMillerLoop2(Fp12& f, const G1& P1, const mcl::Array<Fp6>&
} }
inline void mapToG1(bool *pb, G1& P, const Fp& x) { *pb = BN::param.mapTo.calcG1(P, x); } inline void mapToG1(bool *pb, G1& P, const Fp& x) { *pb = BN::param.mapTo.calcG1(P, x); }
inline void mapToG2(bool *pb, G2& P, const Fp2& x) { *pb = BN::param.mapTo.calcG2(P, x); } inline void mapToG2(bool *pb, G2& P, const Fp2& x) { *pb = BN::param.mapTo.calcG2(P, x); }
#ifndef CYBOZU_DONT_EXCEPTION
inline void mapToG1(G1& P, const Fp& x) inline void mapToG1(G1& P, const Fp& x)
{ {
bool b; bool b;
@ -1840,6 +1844,7 @@ inline void mapToG2(G2& P, const Fp2& x)
mapToG2(&b, P, x); mapToG2(&b, P, x);
if (!b) throw cybozu::Exception("mapToG2:bad value") << x; if (!b) throw cybozu::Exception("mapToG2:bad value") << x;
} }
#endif
inline void hashAndMapToG1(G1& P, const void *buf, size_t bufSize) inline void hashAndMapToG1(G1& P, const void *buf, size_t bufSize)
{ {
Fp t; Fp t;
@ -1861,6 +1866,7 @@ inline void hashAndMapToG2(G2& P, const void *buf, size_t bufSize)
assert(b); assert(b);
(void)b; (void)b;
} }
#ifndef CYBOZU_DONT_USE_STRING
inline void hashAndMapToG1(G1& P, const std::string& str) inline void hashAndMapToG1(G1& P, const std::string& str)
{ {
hashAndMapToG1(P, str.c_str(), str.size()); hashAndMapToG1(P, str.c_str(), str.size());
@ -1869,6 +1875,7 @@ inline void hashAndMapToG2(G2& P, const std::string& str)
{ {
hashAndMapToG2(P, str.c_str(), str.size()); hashAndMapToG2(P, str.c_str(), str.size());
} }
#endif
inline void verifyOrderG1(bool doVerify) inline void verifyOrderG1(bool doVerify)
{ {
if (BN::param.isBLS12) { if (BN::param.isBLS12) {
@ -1936,12 +1943,14 @@ inline void init(bool *pb, const mcl::CurveParam& cp = mcl::BN254, fp::Mode mode
*pb = true; *pb = true;
} }
#ifndef CYBOZU_DONT_EXCEPTION
inline void init(const mcl::CurveParam& cp = mcl::BN254, fp::Mode mode = fp::FP_AUTO) inline void init(const mcl::CurveParam& cp = mcl::BN254, fp::Mode mode = fp::FP_AUTO)
{ {
bool b; bool b;
init(&b, cp, mode); init(&b, cp, mode);
if (!b) throw cybozu::Exception("BN:init"); if (!b) throw cybozu::Exception("BN:init");
} }
#endif
} // mcl::bn::BN } // mcl::bn::BN
@ -1950,12 +1959,14 @@ inline void initPairing(bool *pb, const mcl::CurveParam& cp = mcl::BN254, fp::Mo
BN::init(pb, cp, mode); BN::init(pb, cp, mode);
} }
#ifndef CYBOZU_DONT_EXCEPTION
inline void initPairing(const mcl::CurveParam& cp = mcl::BN254, fp::Mode mode = fp::FP_AUTO) inline void initPairing(const mcl::CurveParam& cp = mcl::BN254, fp::Mode mode = fp::FP_AUTO)
{ {
bool b; bool b;
BN::init(&b, cp, mode); BN::init(&b, cp, mode);
if (!b) throw cybozu::Exception("bn:initPairing"); if (!b) throw cybozu::Exception("bn:initPairing");
} }
#endif
} } // mcl::bn } } // mcl::bn

@ -26,6 +26,7 @@ bool skipSpace(char *c, InputStream& is)
} }
} }
#ifndef CYBOZU_DONT_USE_STRING
template<class InputStream> template<class InputStream>
void loadWord(std::string& s, InputStream& is) void loadWord(std::string& s, InputStream& is)
{ {
@ -39,6 +40,7 @@ void loadWord(std::string& s, InputStream& is)
s += c; s += c;
} }
} }
#endif
template<class InputStream> template<class InputStream>
size_t loadWord(char *buf, size_t bufSize, InputStream& is) size_t loadWord(char *buf, size_t bufSize, InputStream& is)

@ -48,7 +48,14 @@ int64_t getInt64(bool *pb, fp::Block& b, const fp::Op& op);
const char *ModeToStr(Mode mode); const char *ModeToStr(Mode mode);
Mode StrToMode(const std::string& s); Mode StrToMode(const char *s);
#ifndef CYBOZU_DONT_USE_STRING
inline Mode StrToMode(const std::string& s)
{
return StrToMode(s.c_str());
}
#endif
inline void dumpUnit(Unit x) inline void dumpUnit(Unit x)
{ {
@ -124,36 +131,14 @@ public:
static inline void init(bool *pb, const char *mstr, fp::Mode mode = fp::FP_AUTO) static inline void init(bool *pb, const char *mstr, fp::Mode mode = fp::FP_AUTO)
{ {
mpz_class p; mpz_class p;
gmp::setStr(pb, p, mstr, strlen(mstr)); gmp::setStr(pb, p, mstr);
if (!*pb) return; if (!*pb) return;
init(pb, p, mode); init(pb, p, mode);
} }
static inline void init(const mpz_class& _p, fp::Mode mode = fp::FP_AUTO)
{
bool b;
init(&b, _p, mode);
if (!b) throw cybozu::Exception("Fp:init");
}
static inline void init(const std::string& mstr, fp::Mode mode = fp::FP_AUTO)
{
bool b;
init(&b, mstr.c_str(), mode);
if (!b) throw cybozu::Exception("Fp:init");
}
static inline size_t getModulo(char *buf, size_t bufSize) static inline size_t getModulo(char *buf, size_t bufSize)
{ {
return gmp::getStr(buf, bufSize, op_.mp); return gmp::getStr(buf, bufSize, op_.mp);
} }
static inline void getModulo(std::string& pstr)
{
gmp::getStr(pstr, op_.mp);
}
static std::string getModulo()
{
std::string s;
getModulo(s);
return s;
}
static inline bool isFullBit() { return op_.isFullBit; } static inline bool isFullBit() { return op_.isFullBit; }
/* /*
binary patter of p binary patter of p
@ -176,8 +161,8 @@ public:
x.getMpz(mx); x.getMpz(mx);
bool b = op_.sq.get(my, mx); bool b = op_.sq.get(my, mx);
if (!b) return false; if (!b) return false;
y.setMpz(my); y.setMpz(&b, my);
return true; return b;
} }
FpT() {} FpT() {}
FpT(const FpT& x) FpT(const FpT& x)
@ -194,10 +179,6 @@ public:
op_.fp_clear(v_); op_.fp_clear(v_);
} }
FpT(int64_t x) { operator=(x); } FpT(int64_t x) { operator=(x); }
explicit FpT(const std::string& str, int base = 0)
{
Serializer::setStr(str, base);
}
FpT& operator=(int64_t x) FpT& operator=(int64_t x)
{ {
if (x == 1) { if (x == 1) {
@ -290,36 +271,12 @@ public:
} }
cybozu::write(pb, os, buf + sizeof(buf) - len, len); cybozu::write(pb, os, buf + sizeof(buf) - len, len);
} }
template<class OutputStream>
void save(OutputStream& os, int ioMode = IoSerialize) const
{
bool b;
save(&b, os, ioMode);
if (!b) throw cybozu::Exception("fp:save") << ioMode;
}
template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize)
{
bool b;
load(&b, is, ioMode);
if (!b) throw cybozu::Exception("fp:load") << ioMode;
}
template<class S> template<class S>
void setArray(bool *pb, const S *x, size_t n) void setArray(bool *pb, const S *x, size_t n)
{ {
*pb = fp::copyAndMask(v_, x, sizeof(S) * n, op_, fp::NoMask); *pb = fp::copyAndMask(v_, x, sizeof(S) * n, op_, fp::NoMask);
toMont(); toMont();
} }
/*
throw exception if x >= p
*/
template<class S>
void setArray(const S *x, size_t n)
{
bool b;
setArray(&b, x, n);
if (!b) throw cybozu::Exception("Fp:setArray");
}
/* /*
mask x with (1 << bitLen) and subtract p if x >= p mask x with (1 << bitLen) and subtract p if x >= p
*/ */
@ -368,10 +325,6 @@ public:
uint32_t size = op_.hash(buf, static_cast<uint32_t>(sizeof(buf)), msg, static_cast<uint32_t>(msgSize)); uint32_t size = op_.hash(buf, static_cast<uint32_t>(sizeof(buf)), msg, static_cast<uint32_t>(msgSize));
setArrayMask(buf, size); setArrayMask(buf, size);
} }
void setHashOf(const std::string& msg)
{
setHashOf(msg.data(), msg.size());
}
void getMpz(mpz_class& x) const void getMpz(mpz_class& x) const
{ {
fp::Block b; fp::Block b;
@ -392,12 +345,6 @@ public:
} }
setArray(pb, gmp::getUnit(x), gmp::getUnitSize(x)); setArray(pb, gmp::getUnit(x), gmp::getUnitSize(x));
} }
void setMpz(const mpz_class& x)
{
bool b;
setMpz(&b, x);
if (!b) throw cybozu::Exception("Fp:setMpz:neg");
}
static inline void add(FpT& z, const FpT& x, const FpT& y) { op_.fp_add(z.v_, x.v_, y.v_, op_.p); } static inline void add(FpT& z, const FpT& x, const FpT& y) { op_.fp_add(z.v_, x.v_, y.v_, op_.p); }
static inline void sub(FpT& z, const FpT& x, const FpT& y) { op_.fp_sub(z.v_, x.v_, y.v_, op_.p); } static inline void sub(FpT& z, const FpT& x, const FpT& y) { op_.fp_sub(z.v_, x.v_, y.v_, op_.p); }
static inline void addPre(FpT& z, const FpT& x, const FpT& y) { op_.fp_addPre(z.v_, x.v_, y.v_); } static inline void addPre(FpT& z, const FpT& x, const FpT& y) { op_.fp_addPre(z.v_, x.v_, y.v_); }
@ -458,20 +405,6 @@ public:
getBlock(b); getBlock(b);
return fp::getInt64(pb, b, op_); return fp::getInt64(pb, b, op_);
} }
uint64_t getUint64() const
{
bool b;
uint64_t v = getUint64(&b);
if (!b) throw cybozu::Exception("Fp:getUint64:large value");
return v;
}
int64_t getInt64() const
{
bool b;
int64_t v = getInt64(&b);
if (!b) throw cybozu::Exception("Fp:getInt64:large value");
return v;
}
bool operator==(const FpT& rhs) const { return fp::isEqualArray(v_, rhs.v_, op_.N); } bool operator==(const FpT& rhs) const { return fp::isEqualArray(v_, rhs.v_, op_.N); }
bool operator!=(const FpT& rhs) const { return !operator==(rhs); } bool operator!=(const FpT& rhs) const { return !operator==(rhs); }
friend inline std::ostream& operator<<(std::ostream& os, const FpT& self) friend inline std::ostream& operator<<(std::ostream& os, const FpT& self)
@ -526,16 +459,94 @@ public:
ioMode_ = ioMode; ioMode_ = ioMode;
} }
static inline int getIoMode() { return ioMode_; } static inline int getIoMode() { return ioMode_; }
static inline size_t getModBitLen() { return getBitSize(); }
static inline void setHashFunc(uint32_t hash(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize))
{
op_.hash = hash;
}
#ifndef CYBOZU_DONT_USE_STRING
explicit FpT(const std::string& str, int base = 0)
{
Serializer::setStr(str, base);
}
static inline void getModulo(std::string& pstr)
{
gmp::getStr(pstr, op_.mp);
}
static std::string getModulo()
{
std::string s;
getModulo(s);
return s;
}
void setHashOf(const std::string& msg)
{
setHashOf(msg.data(), msg.size());
}
// backward compatibility // backward compatibility
static inline void setModulo(const std::string& mstr, fp::Mode mode = fp::FP_AUTO) static inline void setModulo(const std::string& mstr, fp::Mode mode = fp::FP_AUTO)
{ {
init(mstr, mode); init(mstr, mode);
} }
static inline size_t getModBitLen() { return getBitSize(); } #endif
static inline void setHashFunc(uint32_t hash(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize)) #ifndef CYBOZU_DONT_USE_EXCEPTION
static inline void init(const mpz_class& _p, fp::Mode mode = fp::FP_AUTO)
{ {
op_.hash = hash; bool b;
init(&b, _p, mode);
if (!b) throw cybozu::Exception("Fp:init");
}
static inline void init(const std::string& mstr, fp::Mode mode = fp::FP_AUTO)
{
bool b;
init(&b, mstr.c_str(), mode);
if (!b) throw cybozu::Exception("Fp:init");
}
template<class OutputStream>
void save(OutputStream& os, int ioMode = IoSerialize) const
{
bool b;
save(&b, os, ioMode);
if (!b) throw cybozu::Exception("fp:save") << ioMode;
}
template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize)
{
bool b;
load(&b, is, ioMode);
if (!b) throw cybozu::Exception("fp:load") << ioMode;
}
/*
throw exception if x >= p
*/
template<class S>
void setArray(const S *x, size_t n)
{
bool b;
setArray(&b, x, n);
if (!b) throw cybozu::Exception("Fp:setArray");
}
void setMpz(const mpz_class& x)
{
bool b;
setMpz(&b, x);
if (!b) throw cybozu::Exception("Fp:setMpz:neg");
}
uint64_t getUint64() const
{
bool b;
uint64_t v = getUint64(&b);
if (!b) throw cybozu::Exception("Fp:getUint64:large value");
return v;
}
int64_t getInt64() const
{
bool b;
int64_t v = getInt64(&b);
if (!b) throw cybozu::Exception("Fp:getInt64:large value");
return v;
} }
#endif
}; };
template<class tag, size_t maxBitSize> fp::Op FpT<tag, maxBitSize>::op_; template<class tag, size_t maxBitSize> fp::Op FpT<tag, maxBitSize>::op_;

@ -64,12 +64,13 @@ typedef mpz_class ImplType;
// z = [buf[n-1]:..:buf[1]:buf[0]] // z = [buf[n-1]:..:buf[1]:buf[0]]
// eg. buf[] = {0x12345678, 0xaabbccdd}; => z = 0xaabbccdd12345678; // eg. buf[] = {0x12345678, 0xaabbccdd}; => z = 0xaabbccdd12345678;
template<class T> template<class T>
void setArray(mpz_class& z, const T *buf, size_t n) void setArray(bool *pb, mpz_class& z, const T *buf, size_t n)
{ {
#ifdef MCL_USE_VINT #ifdef MCL_USE_VINT
z.setArray(buf, n); z.setArray(pb, buf, n);
#else #else
mpz_import(z.get_mpz_t(), n, -1, sizeof(*buf), 0, 0, buf); mpz_import(z.get_mpz_t(), n, -1, sizeof(*buf), 0, 0, buf);
*pb = true;
#endif #endif
} }
/* /*
@ -78,44 +79,43 @@ void setArray(mpz_class& z, const T *buf, size_t n)
*/ */
#ifndef MCL_USE_VINT #ifndef MCL_USE_VINT
template<class T> template<class T>
void getArray(T *buf, size_t maxSize, const mpz_srcptr x) bool getArray_(T *buf, size_t maxSize, const mpz_srcptr x)
{ {
const size_t bufByteSize = sizeof(T) * maxSize; const size_t bufByteSize = sizeof(T) * maxSize;
const int xn = x->_mp_size; const int xn = x->_mp_size;
if (xn < 0) throw cybozu::Exception("gmp:getArray:x is negative"); if (xn < 0) return false;
size_t xByteSize = sizeof(*x->_mp_d) * xn; size_t xByteSize = sizeof(*x->_mp_d) * xn;
if (xByteSize > bufByteSize) throw cybozu::Exception("gmp:getArray:too small") << xn << maxSize; if (xByteSize > bufByteSize) return false;
memcpy(buf, x->_mp_d, xByteSize); memcpy(buf, x->_mp_d, xByteSize);
memset((char*)buf + xByteSize, 0, bufByteSize - xByteSize); memset((char*)buf + xByteSize, 0, bufByteSize - xByteSize);
return true;
} }
#endif #endif
template<class T> template<class T>
void getArray(T *buf, size_t maxSize, const mpz_class& x) void getArray(bool *pb, T *buf, size_t maxSize, const mpz_class& x)
{ {
#ifdef MCL_USE_VINT #ifdef MCL_USE_VINT
x.getArray(buf, maxSize); x.getArray(pb, buf, maxSize);
#else #else
getArray(buf, maxSize, x.get_mpz_t()); *pb = getArray_(buf, maxSize, x.get_mpz_t());
#endif #endif
} }
inline void set(mpz_class& z, uint64_t x) inline void set(mpz_class& z, uint64_t x)
{ {
setArray(z, &x, 1); bool b;
setArray(&b, z, &x, 1);
assert(b);
(void)b;
} }
inline void setStr(bool *pb, mpz_class& z, const char *str, size_t strSize, int base = 0) inline void setStr(bool *pb, mpz_class& z, const char *str, int base = 0)
{ {
#ifdef MCL_USE_VINT #ifdef MCL_USE_VINT
z.setStr(pb, str, strSize, base); z.setStr(pb, str, base);
#else #else
*pb = z.set_str(std::string(str, strSize), base) == 0; *pb = z.set_str(str, base) == 0;
#endif #endif
} }
inline void setStr(mpz_class& z, const std::string& str, int base = 0)
{
bool b;
setStr(&b, z, str.c_str(), str.size(), base);
if (!b) throw cybozu::Exception("gmp:setStr");
}
/* /*
set buf with string terminated by '\0' set buf with string terminated by '\0'
return strlen(buf) if success else 0 return strlen(buf) if success else 0
@ -125,18 +125,19 @@ inline size_t getStr(char *buf, size_t bufSize, const mpz_class& z, int base = 1
#ifdef MCL_USE_VINT #ifdef MCL_USE_VINT
return z.getStr(buf, bufSize, base); return z.getStr(buf, bufSize, base);
#else #else
std::string str = z.get_str(base); __gmp_alloc_cstring tmp(mpz_get_str(0, base, z.get_mpz_t()));
if (str.size() < bufSize) { size_t n = strlen(tmp.str);
memcpy(buf, str.c_str(), str.size() + 1); if (n + 1 > bufSize) return 0;
return str.size(); memcpy(buf, tmp.str, n + 1);
} return n;
return 0;
#endif #endif
} }
#ifndef CYBOZU_DONT_USE_STRING
inline void getStr(std::string& str, const mpz_class& z, int base = 10) inline void getStr(std::string& str, const mpz_class& z, int base = 10)
{ {
#ifdef MCL_USE_VINT #ifdef MCL_USE_VINT
str = z.getStr(base); z.getStr(str, base);
#else #else
str = z.get_str(base); str = z.get_str(base);
#endif #endif
@ -144,9 +145,11 @@ inline void getStr(std::string& str, const mpz_class& z, int base = 10)
inline std::string getStr(const mpz_class& z, int base = 10) inline std::string getStr(const mpz_class& z, int base = 10)
{ {
std::string s; std::string s;
getStr(s, z, base); gmp::getStr(s, z, base);
return s; return s;
} }
#endif
inline void add(mpz_class& z, const mpz_class& x, const mpz_class& y) inline void add(mpz_class& z, const mpz_class& x, const mpz_class& y)
{ {
#ifdef MCL_USE_VINT #ifdef MCL_USE_VINT
@ -365,11 +368,12 @@ inline int legendre(const mpz_class& a, const mpz_class& p)
return mpz_legendre(a.get_mpz_t(), p.get_mpz_t()); return mpz_legendre(a.get_mpz_t(), p.get_mpz_t());
#endif #endif
} }
inline bool isPrime(const mpz_class& x) inline bool isPrime(bool *pb, const mpz_class& x)
{ {
#ifdef MCL_USE_VINT #ifdef MCL_USE_VINT
return x.isPrime(32); return x.isPrime(pb, 32);
#else #else
*pb = true;
return mpz_probab_prime_p(x.get_mpz_t(), 32) != 0; return mpz_probab_prime_p(x.get_mpz_t(), 32) != 0;
#endif #endif
} }
@ -438,7 +442,7 @@ inline mpz_class abs(const mpz_class& x)
#endif #endif
} }
inline void getRand(mpz_class& z, size_t bitSize, fp::RandGen rg = fp::RandGen()) inline void getRand(bool *pb, mpz_class& z, size_t bitSize, fp::RandGen rg = fp::RandGen())
{ {
if (rg.isZero()) rg = fp::RandGen::get(); if (rg.isZero()) rg = fp::RandGen::get();
assert(bitSize > 1); assert(bitSize > 1);
@ -447,7 +451,7 @@ inline void getRand(mpz_class& z, size_t bitSize, fp::RandGen rg = fp::RandGen()
uint32_t buf[128]; uint32_t buf[128];
assert(n <= CYBOZU_NUM_OF_ARRAY(buf)); assert(n <= CYBOZU_NUM_OF_ARRAY(buf));
if (n > CYBOZU_NUM_OF_ARRAY(buf)) { if (n > CYBOZU_NUM_OF_ARRAY(buf)) {
z = 0; *pb = false;
return; return;
} }
rg.read(buf, n * sizeof(buf[0])); rg.read(buf, n * sizeof(buf[0]));
@ -459,22 +463,26 @@ inline void getRand(mpz_class& z, size_t bitSize, fp::RandGen rg = fp::RandGen()
v |= 1U << (rem - 1); v |= 1U << (rem - 1);
} }
buf[n - 1] = v; buf[n - 1] = v;
setArray(z, buf, n); setArray(pb, z, buf, n);
} }
inline void getRandPrime(mpz_class& z, size_t bitSize, fp::RandGen rg = fp::RandGen(), bool setSecondBit = false, bool mustBe3mod4 = false) inline void getRandPrime(bool *pb, mpz_class& z, size_t bitSize, fp::RandGen rg = fp::RandGen(), bool setSecondBit = false, bool mustBe3mod4 = false)
{ {
if (rg.isZero()) rg = fp::RandGen::get(); if (rg.isZero()) rg = fp::RandGen::get();
assert(bitSize > 2); assert(bitSize > 2);
do { for (;;) {
getRand(z, bitSize, rg); getRand(pb, z, bitSize, rg);
if (!*pb) return;
if (setSecondBit) { if (setSecondBit) {
z |= mpz_class(1) << (bitSize - 2); z |= mpz_class(1) << (bitSize - 2);
} }
if (mustBe3mod4) { if (mustBe3mod4) {
z |= 3; z |= 3;
} }
} while (!(isPrime(z))); bool ret = isPrime(pb, z);
if (!*pb) return;
if (ret) return;
}
} }
inline mpz_class getQuadraticNonResidue(const mpz_class& p) inline mpz_class getQuadraticNonResidue(const mpz_class& p)
{ {
@ -566,6 +574,49 @@ bool getNAF(Vec& v, const mpz_class& x)
} }
} }
#ifndef CYBOZU_DONT_USE_EXCEPTION
inline void setStr(mpz_class& z, const std::string& str, int base = 0)
{
bool b;
setStr(&b, z, str.c_str(), base);
if (!b) throw cybozu::Exception("gmp:setStr");
}
template<class T>
void setArray(mpz_class& z, const T *buf, size_t n)
{
bool b;
setArray(&b, z, buf, n);
if (!b) throw cybozu::Exception("gmp:setArray");
}
template<class T>
void getArray(T *buf, size_t maxSize, const mpz_class& x)
{
bool b;
getArray(&b, buf, maxSize, x);
if (!b) throw cybozu::Exception("gmp:getArray");
}
inline bool isPrime(const mpz_class& x)
{
bool b;
bool ret = isPrime(&b, x);
if (!b) throw cybozu::Exception("gmp:isPrime");
return ret;
}
inline void getRand(mpz_class& z, size_t bitSize, fp::RandGen rg = fp::RandGen())
{
bool b;
getRand(&b, z, bitSize, rg);
if (!b) throw cybozu::Exception("gmp:getRand");
}
inline void getRandPrime(mpz_class& z, size_t bitSize, fp::RandGen rg = fp::RandGen(), bool setSecondBit = false, bool mustBe3mod4 = false)
{
bool b;
getRandPrime(&b, z, bitSize, rg, setSecondBit, mustBe3mod4);
if (!b) throw cybozu::Exception("gmp:getRandPrime");
}
#endif
} // mcl::gmp } // mcl::gmp
/* /*
@ -591,12 +642,19 @@ public:
s = 0; s = 0;
q_add_1_div_2 = 0; q_add_1_div_2 = 0;
} }
void set(const mpz_class& _p) void set(bool *pb, const mpz_class& _p)
{ {
p = _p; p = _p;
if (p <= 2) throw cybozu::Exception("SquareRoot:bad p") << p; if (p <= 2) {
isPrime = gmp::isPrime(p); *pb = false;
if (!isPrime) return; // don't throw until get() is called return;
}
isPrime = gmp::isPrime(pb, p);
if (!*pb) return;
if (!isPrime) {
*pb = false;
return;
}
g = gmp::getQuadraticNonResidue(p); g = gmp::getQuadraticNonResidue(p);
// p - 1 = 2^r q, q is odd // p - 1 = 2^r q, q is odd
r = 0; r = 0;
@ -607,13 +665,18 @@ public:
} }
gmp::powMod(s, g, q, p); gmp::powMod(s, g, q, p);
q_add_1_div_2 = (q + 1) / 2; q_add_1_div_2 = (q + 1) / 2;
*pb = true;
} }
/* /*
solve x^2 = a mod p solve x^2 = a mod p
*/ */
bool get(mpz_class& x, const mpz_class& a) const bool get(bool *pb, mpz_class& x, const mpz_class& a) const
{ {
if (!isPrime) throw cybozu::Exception("SquareRoot:get:not prime") << p; if (!isPrime) {
*pb = false;
return false;
}
*pb = true;
if (a == 0) { if (a == 0) {
x = 0; x = 0;
return true; return true;
@ -653,7 +716,7 @@ public:
template<class Fp> template<class Fp>
bool get(Fp& x, const Fp& a) const bool get(Fp& x, const Fp& a) const
{ {
if (Fp::getOp().mp != p) throw cybozu::Exception("bad Fp") << Fp::getOp().mp << p; assert(Fp::getOp().mp == p);
if (a == 0) { if (a == 0) {
x = 0; x = 0;
return true; return true;
@ -691,6 +754,21 @@ public:
} }
return true; return true;
} }
#ifndef CYBOZU_DONT_USE_EXCEPTION
void set(const mpz_class& _p)
{
bool b;
set(&b, _p);
if (!b) throw cybozu::Exception("gmp:SquareRoot:set");
}
bool get(mpz_class& x, const mpz_class& a) const
{
bool b;
bool ret = get(&b, x, a);
if (!b) throw cybozu::Exception("gmp:SquareRoot:get:not prime");
return ret;
}
#endif
}; };
} // mcl } // mcl

@ -136,6 +136,7 @@ struct Serializable : public E {
buf[n] = '\0'; buf[n] = '\0';
return n; return n;
} }
#ifndef CYBOZU_DONT_USE_STRING
void setStr(const std::string& str, int ioMode = 0) void setStr(const std::string& str, int ioMode = 0)
{ {
cybozu::StringInputStream is(str); cybozu::StringInputStream is(str);
@ -153,6 +154,7 @@ struct Serializable : public E {
getStr(str, ioMode); getStr(str, ioMode);
return str; return str;
} }
#endif
// return written bytes // return written bytes
size_t serialize(void *buf, size_t maxBufSize, int ioMode = IoSerialize) const size_t serialize(void *buf, size_t maxBufSize, int ioMode = IoSerialize) const
{ {

@ -618,6 +618,7 @@ void divNM(T *q, size_t qn, T *r, const T *x, size_t xn, const T *y, size_t yn)
} }
} }
#ifndef MCL_VINT_FIXED_BUFFER
template<class T> template<class T>
class Buffer { class Buffer {
size_t allocSize_; size_t allocSize_;
@ -651,21 +652,6 @@ public:
std::swap(allocSize_, rhs.allocSize_); std::swap(allocSize_, rhs.allocSize_);
std::swap(ptr_, rhs.ptr_); std::swap(ptr_, rhs.ptr_);
} }
#if 0
#if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
Buffer(Buffer&& rhs) noexcept
: allocSize_(0)
, ptr_(0)
{
swap(rhs);
}
Buffer& operator=(Buffer&& rhs) noexcept
{
swap(rhs);
return *this;
}
#endif
#endif
void clear() void clear()
{ {
allocSize_ = 0; allocSize_ = 0;
@ -676,17 +662,29 @@ public:
/* /*
@note extended buffer may be not cleared @note extended buffer may be not cleared
*/ */
void alloc(size_t n) void alloc(bool *pb, size_t n)
{ {
if (n > allocSize_) { if (n > allocSize_) {
T *p = (T*)malloc(n * sizeof(T)); T *p = (T*)malloc(n * sizeof(T));
if (p == 0) throw cybozu::Exception("Buffer:alloc:malloc:") << n; if (p == 0) {
*pb = false;
return;
}
copyN(p, ptr_, allocSize_); copyN(p, ptr_, allocSize_);
free(ptr_); free(ptr_);
ptr_ = p; ptr_ = p;
allocSize_ = n; allocSize_ = n;
} }
*pb = true;
} }
#ifndef CYBOZU_DONT_USE_EXCEPTION
void alloc(size_t n)
{
bool b;
alloc(&b, n);
if (!b) throw cybozu::Exception("Buffer:alloc");
}
#endif
/* /*
*this = rhs *this = rhs
rhs may be destroyed rhs may be destroyed
@ -694,6 +692,7 @@ public:
const T& operator[](size_t n) const { return ptr_[n]; } const T& operator[](size_t n) const { return ptr_[n]; }
T& operator[](size_t n) { return ptr_[n]; } T& operator[](size_t n) { return ptr_[n]; }
}; };
#endif
template<class T, size_t BitLen> template<class T, size_t BitLen>
class FixedBuffer { class FixedBuffer {
@ -721,11 +720,23 @@ public:
return *this; return *this;
} }
void clear() { size_ = 0; } void clear() { size_ = 0; }
void alloc(size_t n) void alloc(bool *pb, size_t n)
{ {
verify(n); if (n > N) {
*pb = false;
return;
}
size_ = n; size_ = n;
*pb = true;
} }
#ifndef CYBOZU_DONT_USE_EXCEPTION
void alloc(size_t n)
{
bool b;
alloc(&b, n);
if (!b) throw cybozu::Exception("FixedBuffer:alloc");
}
#endif
void swap(FixedBuffer& rhs) void swap(FixedBuffer& rhs)
{ {
FixedBuffer *p1 = this; FixedBuffer *p1 = this;
@ -745,9 +756,8 @@ public:
// to avoid warning of gcc // to avoid warning of gcc
void verify(size_t n) const void verify(size_t n) const
{ {
if (n > N) { assert(n <= N);
throw cybozu::Exception("verify:too large size") << n << (int)N; (void)n;
}
} }
const T& operator[](size_t n) const { verify(n); return v_[n]; } const T& operator[](size_t n) const { verify(n); return v_[n]; }
T& operator[](size_t n) { verify(n); return v_[n]; } T& operator[](size_t n) { verify(n); return v_[n]; }
@ -946,6 +956,19 @@ private:
} }
r.trim(yn); r.trim(yn);
} }
/*
@param x [inout] x <- d
@retval s for x = 2^s d where d is odd
*/
static uint32_t countTrailingZero(VintT& x)
{
uint32_t s = 0;
while (x.isEven()) {
x >>= 1;
s++;
}
return s;
}
struct MulMod { struct MulMod {
const VintT *pm; const VintT *pm;
void operator()(VintT& z, const VintT& x, const VintT& y) const void operator()(VintT& z, const VintT& x, const VintT& y) const
@ -973,11 +996,6 @@ public:
{ {
*this = x; *this = x;
} }
explicit VintT(const std::string& str)
: size_(0)
{
setStr(str);
}
VintT(const VintT& rhs) VintT(const VintT& rhs)
: buf_(rhs.buf_) : buf_(rhs.buf_)
, size_(rhs.size_) , size_(rhs.size_)
@ -1057,12 +1075,13 @@ public:
/* /*
set [0, max) randomly set [0, max) randomly
*/ */
void setRand(const VintT& max) void setRand(bool *pb, const VintT& max)
{ {
assert(max > 0);
fp::RandGen& rg = fp::RandGen::get(); fp::RandGen& rg = fp::RandGen::get();
if (max <= 0) throw cybozu::Exception("Vint:setRand:bad value") << max;
size_t n = max.size(); size_t n = max.size();
buf_.alloc(n); buf_.alloc(pb, n);
if (!*pb) return;
rg.read(&buf_[0], n * sizeof(buf_[0])); rg.read(&buf_[0], n * sizeof(buf_[0]));
trim(n); trim(n);
*this %= max; *this %= max;
@ -1073,12 +1092,16 @@ public:
buf_[size, maxSize) with zero buf_[size, maxSize) with zero
@note assume little endian system @note assume little endian system
*/ */
void getArray(Unit *x, size_t maxSize) const void getArray(bool *pb, Unit *x, size_t maxSize) const
{ {
size_t n = size(); size_t n = size();
if (n > maxSize) throw cybozu::Exception("Vint:getArray:small maxSize") << maxSize << n; if (n > maxSize) {
*pb = false;
return;
}
vint::copyN(x, &buf_[0], n); vint::copyN(x, &buf_[0], n);
vint::clearN(x + n, maxSize - n); vint::clearN(x + n, maxSize - n);
*pb = true;
} }
void clear() { *this = 0; } void clear() { *this = 0; }
template<class OutputStream> template<class OutputStream>
@ -1093,13 +1116,6 @@ public:
} }
cybozu::write(pb, os, buf + sizeof(buf) - n, n); cybozu::write(pb, os, buf + sizeof(buf) - n, n);
} }
template<class OutputStream>
void save(OutputStream& os, int base = 10) const
{
bool b;
save(&b, os, base);
if (!b) throw cybozu::Exception("Vint:save");
}
/* /*
set buf with string terminated by '\0' set buf with string terminated by '\0'
return strlen(buf) if success else 0 return strlen(buf) if success else 0
@ -1114,13 +1130,6 @@ public:
buf[n] = '\0'; buf[n] = '\0';
return n; return n;
} }
std::string getStr(int base = 10) const
{
std::string s;
cybozu::StringOutputStream os(s);
save(os, base);
return s;
}
/* /*
return bitSize(abs(*this)) return bitSize(abs(*this))
@note return 1 if zero @note return 1 if zero
@ -1138,7 +1147,7 @@ public:
{ {
size_t q = i / unitBitSize; size_t q = i / unitBitSize;
size_t r = i % unitBitSize; size_t r = i % unitBitSize;
if (q > size()) throw cybozu::Exception("Vint:testBit:large i") << q << size(); assert(q <= size());
Unit mask = Unit(1) << r; Unit mask = Unit(1) << r;
return (buf_[q] & mask) != 0; return (buf_[q] & mask) != 0;
} }
@ -1146,7 +1155,7 @@ public:
{ {
size_t q = i / unitBitSize; size_t q = i / unitBitSize;
size_t r = i % unitBitSize; size_t r = i % unitBitSize;
if (q > size()) throw cybozu::Exception("Vint:setBit:large i") << q << size(); assert(q <= size());
buf_.alloc(q + 1); buf_.alloc(q + 1);
Unit mask = Unit(1) << r; Unit mask = Unit(1) << r;
if (v) { if (v) {
@ -1162,23 +1171,19 @@ public:
"0b..." => base = 2 "0b..." => base = 2
otherwise => base = 10 otherwise => base = 10
*/ */
void setStr(bool *pb, const char *str, size_t strSize, int base = 0) void setStr(bool *pb, const char *str, int base = 0)
{ {
const size_t maxN = MCL_MAX_BIT_SIZE / (sizeof(MCL_SIZEOF_UNIT) * 8); const size_t maxN = MCL_MAX_BIT_SIZE / (sizeof(MCL_SIZEOF_UNIT) * 8);
buf_.alloc(maxN); buf_.alloc(pb, maxN);
if (!*pb) return;
*pb = false; *pb = false;
isNeg_ = false; isNeg_ = false;
size_t n = fp::strToArray(&isNeg_, &buf_[0], maxN, str, strSize, base); size_t len = strlen(str);
size_t n = fp::strToArray(&isNeg_, &buf_[0], maxN, str, len, base);
if (n == 0) return; if (n == 0) return;
trim(n); trim(n);
*pb = true; *pb = true;
} }
void setStr(std::string str, int base = 0)
{
bool b;
setStr(&b, str.c_str(), str.size(), base);
if (!b) throw cybozu::Exception("Vint:setStr") << str;
}
static int compare(const VintT& x, const VintT& y) static int compare(const VintT& x, const VintT& y)
{ {
if (x.isNeg_ ^ y.isNeg_) { if (x.isNeg_ ^ y.isNeg_) {
@ -1372,10 +1377,6 @@ public:
usub(r, yy.buf_, yy.size(), r.buf_, r.size()); usub(r, yy.buf_, yy.size(), r.buf_, r.size());
} }
} }
inline friend std::ostream& operator<<(std::ostream& os, const VintT& x)
{
return os << x.getStr(os.flags() & std::ios_base::hex ? 16 : 10);
}
template<class InputStream> template<class InputStream>
void load(bool *pb, InputStream& is, int ioMode) void load(bool *pb, InputStream& is, int ioMode)
{ {
@ -1391,18 +1392,6 @@ public:
trim(n); trim(n);
*pb = true; *pb = true;
} }
template<class InputStream>
void load(InputStream& is, int ioMode = 0)
{
bool b;
load(&b, is, ioMode);
if (!b) throw cybozu::Exception("Vint:load");
}
inline friend std::istream& operator>>(std::istream& is, VintT& x)
{
x.load(is);
return is;
}
// logical left shift (copy sign) // logical left shift (copy sign)
static void shl(VintT& y, const VintT& x, size_t shiftBit) static void shl(VintT& y, const VintT& x, size_t shiftBit)
{ {
@ -1575,26 +1564,12 @@ public:
b -= a * q; b -= a * q;
} }
} }
private:
/*
@param x [inout] x <- d
@retval s for x = 2^s d where d is odd
*/
static uint32_t countTrailingZero(VintT& x)
{
uint32_t s = 0;
while (x.isEven()) {
x >>= 1;
s++;
}
return s;
}
public:
/* /*
Miller-Rabin Miller-Rabin
*/ */
static bool isPrime(const VintT& n, int tryNum = 32) static bool isPrime(bool *pb, const VintT& n, int tryNum = 32)
{ {
*pb = true;
if (n <= 1) return false; if (n <= 1) return false;
if (n == 2 || n == 3) return true; if (n == 2 || n == 3) return true;
if (n.isEven()) return false; if (n.isEven()) return false;
@ -1604,7 +1579,8 @@ public:
// n - 1 = 2^r d // n - 1 = 2^r d
VintT a, x; VintT a, x;
for (int i = 0; i < tryNum; i++) { for (int i = 0; i < tryNum; i++) {
a.setRand(n - 3); a.setRand(pb, n - 3);
if (!*pb) return false;
a += 2; // a in [2, n - 2] a += 2; // a in [2, n - 2]
powMod(x, a, d, n); powMod(x, a, d, n);
if (x == 1 || x == nm1) { if (x == 1 || x == nm1) {
@ -1621,9 +1597,9 @@ public:
} }
return true; return true;
} }
bool isPrime(int tryNum = 32) const bool isPrime(bool *pb, int tryNum = 32) const
{ {
return isPrime(*this, tryNum); return isPrime(pb, *this, tryNum);
} }
static void gcd(VintT& z, VintT x, VintT y) static void gcd(VintT& z, VintT x, VintT y)
{ {
@ -1665,7 +1641,7 @@ public:
*/ */
static int jacobi(VintT m, VintT n) static int jacobi(VintT m, VintT n)
{ {
if (n.isEven()) throw cybozu::Exception(); assert(n.isOdd());
if (n == 1) return 1; if (n == 1) return 1;
if (m < 0 || m > n) { if (m < 0 || m > n) {
quotRem(0, m, m, n); // m = m mod n quotRem(0, m, m, n); // m = m mod n
@ -1693,6 +1669,81 @@ public:
} }
return j; return j;
} }
#ifndef CYBOZU_DONT_USE_STRING
explicit VintT(const std::string& str)
: size_(0)
{
setStr(str);
}
void getStr(std::string& s, int base = 10) const
{
cybozu::StringOutputStream os(s);
save(os, base);
}
std::string getStr(int base = 10) const
{
std::string s;
getStr(s, base);
return s;
}
inline friend std::ostream& operator<<(std::ostream& os, const VintT& x)
{
return os << x.getStr(os.flags() & std::ios_base::hex ? 16 : 10);
}
inline friend std::istream& operator>>(std::istream& is, VintT& x)
{
x.load(is);
return is;
}
#endif
#ifndef CYBOZU_DONT_USE_EXCEPTION
void setStr(const std::string& str, int base = 0)
{
bool b;
setStr(&b, str.c_str(), base);
if (!b) throw cybozu::Exception("Vint:setStr") << str;
}
void setRand(const VintT& max)
{
bool b;
setRand(&b, max);
if (!b) throw cybozu::Exception("Vint:setRand");
}
void getArray(Unit *x, size_t maxSize) const
{
bool b;
getArray(&b, x, maxSize);
if (!b) throw cybozu::Exception("Vint:getArray");
}
template<class InputStream>
void load(InputStream& is, int ioMode = 0)
{
bool b;
load(&b, is, ioMode);
if (!b) throw cybozu::Exception("Vint:load");
}
template<class OutputStream>
void save(OutputStream& os, int base = 10) const
{
bool b;
save(&b, os, base);
if (!b) throw cybozu::Exception("Vint:save");
}
static bool isPrime(const VintT& n, int tryNum = 32)
{
bool b;
bool ret = isPrime(&b, n, tryNum);
if (!b) throw cybozu::Exception("Vint:isPrime");
return ret;
}
bool isPrime(int tryNum = 32) const
{
bool b;
bool ret = isPrime(&b, *this, tryNum);
if (!b) throw cybozu::Exception("Vint:isPrime");
return ret;
}
#endif
VintT& operator++() { adds1(*this, *this, 1); return *this; } VintT& operator++() { adds1(*this, *this, 1); return *this; }
VintT& operator--() { subs1(*this, *this, 1); return *this; } VintT& operator--() { subs1(*this, *this, 1); return *this; }
VintT operator++(int) { VintT c = *this; adds1(*this, *this, 1); return c; } VintT operator++(int) { VintT c = *this; adds1(*this, *this, 1); return c; }

@ -77,7 +77,7 @@ const char *ModeToStr(Mode mode)
} }
} }
Mode StrToMode(const std::string& s) Mode StrToMode(const char *s)
{ {
static const struct { static const struct {
const char *s; const char *s;
@ -91,7 +91,7 @@ Mode StrToMode(const std::string& s)
{ "xbyak", FP_XBYAK }, { "xbyak", FP_XBYAK },
}; };
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
if (s == tbl[i].s) return tbl[i].mode; if (strcmp(s, tbl[i].s) == 0) return tbl[i].mode;
} }
return FP_AUTO; return FP_AUTO;
} }
@ -176,19 +176,24 @@ static inline void set_mpz_t(mpz_t& z, const Unit* p, int n)
static inline void fp_invOpC(Unit *y, const Unit *x, const Op& op) static inline void fp_invOpC(Unit *y, const Unit *x, const Op& op)
{ {
const int N = (int)op.N; const int N = (int)op.N;
bool b;
#ifdef MCL_USE_VINT #ifdef MCL_USE_VINT
Vint vx, vy, vp; Vint vx, vy, vp;
vx.setArray(x, N); vx.setArray(&b, x, N);
vp.setArray(op.p, N); assert(b);
vp.setArray(&b, op.p, N);
assert(b);
Vint::invMod(vy, vx, vp); Vint::invMod(vy, vx, vp);
vy.getArray(y, N); vy.getArray(&b, y, N);
assert(b);
#else #else
mpz_class my; mpz_class my;
mpz_t mx, mp; mpz_t mx, mp;
set_mpz_t(mx, x, N); set_mpz_t(mx, x, N);
set_mpz_t(mp, op.p, N); set_mpz_t(mp, op.p, N);
mpz_invert(my.get_mpz_t(), mx, mp); mpz_invert(my.get_mpz_t(), mx, mp);
gmp::getArray(y, N, my); gmp::getArray(&b, y, N, my);
assert(b);
#endif #endif
} }
@ -323,20 +328,24 @@ static void initInvTbl(Op& op)
} }
#endif #endif
static void initForMont(Op& op, const Unit *p, Mode mode) static bool initForMont(Op& op, const Unit *p, Mode mode)
{ {
const size_t N = op.N; const size_t N = op.N;
bool b;
{ {
mpz_class t = 1, R; mpz_class t = 1, R;
gmp::getArray(op.one, N, t); gmp::getArray(&b, op.one, N, t);
if (!b) return false;
R = (t << (N * UnitBitSize)) % op.mp; R = (t << (N * UnitBitSize)) % op.mp;
t = (R * R) % op.mp; t = (R * R) % op.mp;
gmp::getArray(op.R2, N, t); gmp::getArray(&b, op.R2, N, t);
if (!b) return false;
t = (t * R) % op.mp; t = (t * R) % op.mp;
gmp::getArray(op.R3, N, t); gmp::getArray(&b, op.R3, N, t);
if (!b) return false;
} }
op.rp = getMontgomeryCoeff(p[0]); op.rp = getMontgomeryCoeff(p[0]);
if (mode != FP_XBYAK) return; if (mode != FP_XBYAK) return true;
#ifdef MCL_USE_XBYAK #ifdef MCL_USE_XBYAK
if (op.fg == 0) op.fg = Op::createFpGenerator(); if (op.fg == 0) op.fg = Op::createFpGenerator();
op.fg->init(op); op.fg->init(op);
@ -346,6 +355,7 @@ static void initForMont(Op& op, const Unit *p, Mode mode)
initInvTbl(op); initInvTbl(op);
} }
#endif #endif
return true;
} }
bool Op::init(const mpz_class& _p, size_t maxBitSize, Mode mode, size_t mclMaxBitSize) bool Op::init(const mpz_class& _p, size_t maxBitSize, Mode mode, size_t mclMaxBitSize)
@ -359,11 +369,13 @@ bool Op::init(const mpz_class& _p, size_t maxBitSize, Mode mode, size_t mclMaxBi
if (maxBitSize > MCL_MAX_BIT_SIZE) return false; if (maxBitSize > MCL_MAX_BIT_SIZE) return false;
if (_p <= 0) return false; if (_p <= 0) return false;
clear(); clear();
bool b;
{ {
const size_t maxN = (maxBitSize + fp::UnitBitSize - 1) / fp::UnitBitSize; const size_t maxN = (maxBitSize + fp::UnitBitSize - 1) / fp::UnitBitSize;
N = gmp::getUnitSize(_p); N = gmp::getUnitSize(_p);
if (N > maxN) return false; if (N > maxN) return false;
gmp::getArray(p, N, _p); gmp::getArray(&b, p, N, _p);
if (!b) return false;
mp = _p; mp = _p;
} }
bitSize = gmp::getBitSize(mp); bitSize = gmp::getBitSize(mp);
@ -417,10 +429,16 @@ bool Op::init(const mpz_class& _p, size_t maxBitSize, Mode mode, size_t mclMaxBi
} }
#endif #endif
#if defined(MCL_USE_VINT) && MCL_SIZEOF_UNIT == 8 #if defined(MCL_USE_VINT) && MCL_SIZEOF_UNIT == 8
if (mp == mpz_class("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f")) { {
primeMode = PM_SECP256K1; const char *secp256k1Str = "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f";
isMont = false; bool b;
isFastMod = true; mpz_class secp256k1;
gmp::setStr(&b, secp256k1, secp256k1Str);
if (b && mp == secp256k1) {
primeMode = PM_SECP256K1;
isMont = false;
isFastMod = true;
}
} }
#endif #endif
switch (N) { switch (N) {
@ -477,8 +495,9 @@ bool Op::init(const mpz_class& _p, size_t maxBitSize, Mode mode, size_t mclMaxBi
fpDbl_mod = &mcl::vint::mcl_fpDbl_mod_SECP256K1; fpDbl_mod = &mcl::vint::mcl_fpDbl_mod_SECP256K1;
} }
#endif #endif
fp::initForMont(*this, p, mode); if (!fp::initForMont(*this, p, mode)) return false;
sq.set(mp); sq.set(&b, mp);
if (!b) return false;
if (N * UnitBitSize <= 256) { if (N * UnitBitSize <= 256) {
hash = sha256; hash = sha256;
} else { } else {

@ -351,6 +351,7 @@ void compareTest()
void moduloTest(const char *pStr) void moduloTest(const char *pStr)
{ {
std::cout << std::hex;
std::string str; std::string str;
Fp::getModulo(str); Fp::getModulo(str);
CYBOZU_TEST_EQUAL(str, mcl::gmp::getStr(mpz_class(pStr))); CYBOZU_TEST_EQUAL(str, mcl::gmp::getStr(mpz_class(pStr)));

@ -21,6 +21,45 @@ CYBOZU_TEST_AUTO(testBit)
} }
} }
CYBOZU_TEST_AUTO(getStr)
{
const struct {
int x;
const char *dec;
const char *hex;
} tbl[] = {
{ 0, "0", "0" },
{ 1, "1", "1" },
{ 10, "10", "a" },
{ 16, "16", "10" },
{ 123456789, "123456789", "75bcd15" },
{ -1, "-1", "-1" },
{ -10, "-10", "-a" },
{ -16, "-16", "-10" },
{ -100000000, "-100000000", "-5f5e100" },
{ -987654321, "-987654321", "-3ade68b1" },
{ -2147483647, "-2147483647", "-7fffffff" },
};
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
mpz_class x = tbl[i].x;
char buf[32];
size_t n, len;
len = strlen(tbl[i].dec);
n = mcl::gmp::getStr(buf, len, x, 10);
CYBOZU_TEST_EQUAL(n, 0);
n = mcl::gmp::getStr(buf, len + 1, x, 10);
CYBOZU_TEST_EQUAL(n, len);
CYBOZU_TEST_EQUAL_ARRAY(buf, tbl[i].dec, n);
len = strlen(tbl[i].hex);
n = mcl::gmp::getStr(buf, len, x, 16);
CYBOZU_TEST_EQUAL(n, 0);
n = mcl::gmp::getStr(buf, len + 1, x, 16);
CYBOZU_TEST_EQUAL(n, len);
CYBOZU_TEST_EQUAL_ARRAY(buf, tbl[i].hex, n);
}
}
CYBOZU_TEST_AUTO(getRandPrime) CYBOZU_TEST_AUTO(getRandPrime)
{ {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {

Loading…
Cancel
Save