unify toArray and Gmp::getArray

dev
MITSUNARI Shigeo 10 years ago
parent a89ed738a7
commit 02f726aad2
  1. 10
      include/mcl/fp.hpp
  2. 27
      include/mcl/gmp_util.hpp
  3. 35
      include/mcl/util.hpp
  4. 34
      src/fp.cpp
  5. 33
      test/fp_test.cpp
  6. 16
      test/fp_util_test.cpp
  7. 41
      test/mont_fp_test.cpp

@ -35,7 +35,7 @@ void arrayToStr(std::string& str, const Unit *x, size_t n, int base, bool withPr
*/
bool strToMpzArray(size_t *pBitSize, Unit *y, size_t maxBitSize, mpz_class& x, const std::string& str, int base);
bool copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, bool doMask);
void copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, bool doMask);
} // mcl::fp
@ -143,14 +143,12 @@ public:
toMont(*this, *this);
}
/*
throw exception if inBuf >= p
throw exception if x >= p
*/
template<class S>
void setArray(const S *inBuf, size_t n)
void setArray(const S *x, size_t n)
{
if (!fp::copyAndMask(v_, inBuf, sizeof(S) * n, op_, false)) {
throw cybozu::Exception("FpT:setArray:large value") << n;
}
fp::copyAndMask(v_, x, sizeof(S) * n, op_, false);
toMont(*this, *this);
}
/*

@ -70,19 +70,24 @@ struct Gmp {
mpz_import(z.get_mpz_t(), n, -1, sizeof(*buf), 0, 0, buf);
}
/*
return positive written size
return 0 if failure
buf[0, size) = x
buf[size, maxSize) with zero
*/
template<class T>
static size_t getArray(T *buf, size_t maxSize, const mpz_class& x)
{
const size_t totalSize = sizeof(T) * maxSize;
if (getBitSize(x) > totalSize * 8) return 0;
memset(buf, 0, sizeof(*buf) * maxSize);
size_t size;
mpz_export(buf, &size, -1, sizeof(T), 0, 0, x.get_mpz_t());
// if x == 0, then size = 0 for gmp, size = 1 for mpir
return size == 0 ? 1 : size;
static void getArray(T *buf, size_t maxSize, const mpz_srcptr x)
{
const size_t bufByteSize = sizeof(T) * maxSize;
const int xn = x->_mp_size;
if (xn < 0) throw cybozu::Exception("Gmp:getArray:x is negative");
size_t xByteSize = sizeof(*x->_mp_d) * xn;
if (xByteSize > bufByteSize) throw cybozu::Exception("Gmp:getArray:too small") << maxSize;
memcpy(buf, x->_mp_d, xByteSize);
memset((char*)buf + xByteSize, 0, bufByteSize - xByteSize);
}
template<class T>
static void getArray(T *buf, size_t maxSize, const mpz_class& x)
{
getArray(buf, maxSize, x.get_mpz_t());
}
static inline void set(mpz_class& z, uint64_t x)
{

@ -73,23 +73,38 @@ void copyArray(T *y, const T *x, size_t n)
for (size_t i = 0; i < n; i++) y[i] = x[i];
}
/*
x &= (1 << bitSize) - 1
*/
template<class T>
void toArray(T *y, size_t yn, const mpz_srcptr x)
void maskArray(T *x, size_t n, size_t bitSize)
{
const int xn = x->_mp_size;
assert(xn >= 0);
const T* xp = (const T*)x->_mp_d;
assert(xn <= (int)yn);
copyArray(y, xp, xn);
clearArray(y, xn, yn);
const size_t TbitSize = sizeof(T) * 8;
assert(bitSize <= TbitSize * n);
const size_t q = bitSize / TbitSize;
const size_t r = bitSize % TbitSize;
if (r) {
x[q] &= (T(1) << r) - 1;
clearArray(x, q + 1, n);
} else {
clearArray(x, q, n);
}
}
/*
return non zero size of x[]
return 1 if x[] == 0
*/
template<class T>
void toArray(T *y, size_t yn, const mpz_class& x)
size_t getNonZeroArraySize(const T *x, size_t n)
{
toArray(y, yn, x.get_mpz_t());
assert(n > 0);
while (n > 0) {
if (x[n - 1]) return n;
n--;
}
return 1;
}
/*
get random value less than in[]
n = (bitSize + sizeof(T) * 8) / (sizeof(T) * 8)

@ -66,7 +66,7 @@ bool strToMpzArray(size_t *pBitSize, Unit *y, size_t maxBitSize, mpz_class& x, c
const size_t bitSize = Gmp::getBitSize(x);
if (bitSize > maxBitSize) throw cybozu::Exception("fp:strToMpzArray:too large str") << str << bitSize << maxBitSize;
if (pBitSize) *pBitSize = bitSize;
fp::toArray(y, (maxBitSize + UnitBitSize - 1) / UnitBitSize, x);
Gmp::getArray(y, (maxBitSize + UnitBitSize - 1) / UnitBitSize, x);
return isMinus;
}
@ -76,11 +76,7 @@ struct OpeFunc {
static inline void set_mpz_t(mpz_t& z, const Unit* p, int n = (int)N)
{
z->_mp_alloc = n;
int i = n;
while (i > 0 && p[i - 1] == 0) {
i--;
}
z->_mp_size = i;
z->_mp_size = getNonZeroArraySize(p, n);
z->_mp_d = (mp_limb_t*)const_cast<Unit*>(p);
}
static inline void set_zero(mpz_t& z, Unit *p, size_t n)
@ -109,7 +105,7 @@ struct OpeFunc {
if (mpz_cmp(mz, mp) >= 0) {
mpz_sub(mz, mz, mp);
}
toArray(z, N, mz);
Gmp::getArray(z, N, mz);
}
static inline void subC(Unit *z, const Unit *x, const Unit *y, const Unit *p)
{
@ -124,7 +120,7 @@ struct OpeFunc {
set_mpz_t(mp, p);
mpz_add(mz, mz, mp);
}
toArray(z, N, mz);
Gmp::getArray(z, N, mz);
}
static inline void mulPreC(Unit *z, const Unit *x, const Unit *y)
{
@ -133,7 +129,7 @@ struct OpeFunc {
set_mpz_t(mx, x);
set_mpz_t(my, y);
mpz_mul(mz, mx, my);
toArray(z, N * 2, mz);
Gmp::getArray(z, N * 2, mz);
}
// x[N * 2] -> y[N]
static inline void modC(Unit *y, const Unit *x, const Unit *p)
@ -152,7 +148,7 @@ struct OpeFunc {
set_mpz_t(mx, x);
set_mpz_t(mp, op.p);
mpz_invert(my.get_mpz_t(), mx, mp);
toArray(y, N, my.get_mpz_t());
Gmp::getArray(y, N, my);
}
static inline bool isZeroC(const Unit *x)
{
@ -223,10 +219,10 @@ static void initForMont(Op& op, const Unit *p)
const size_t N = op.N;
assert(N >= 2);
mpz_class t = 1;
toArray(op.one, N, t);
Gmp::getArray(op.one, N, t);
t = (t << (N * 64)) % op.mp;
t = (t * t) % op.mp;
toArray(op.RR, N, t);
Gmp::getArray(op.RR, N, t);
FpGenerator *fg = op.fg;
if (fg == 0) return;
fg->init(p, (int)N);
@ -313,21 +309,25 @@ void arrayToStr(std::string& str, const Unit *x, size_t n, int base, bool withPr
}
}
bool copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, bool doMask)
void copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, bool doMask)
{
const size_t fpByteSize = sizeof(Unit) * op.N;
if (xByteSize > fpByteSize) {
if (!doMask) return false;
if (!doMask) throw cybozu::Exception("fp:copyAndMask:bad size") << xByteSize << fpByteSize;
xByteSize = fpByteSize;
}
memcpy(y, x, xByteSize);
memset((char *)y + xByteSize, 0, fpByteSize - xByteSize);
if (!doMask) return compareArray(y, op.p, op.N) < 0;
if (!doMask) {
if (compareArray(y, op.p, op.N) >= 0) throw cybozu::Exception("fp:copyAndMask:large x");
return;
}
/*
x &= mask(op.bitSize - 1);
*/
const Unit r = op.bitSize % UnitBitSize;
y[op.N - 1] &= r ? (Unit(1) << (r - 1)) - 1 : Unit(-1);
assert(compareArray(y, op.p, op.N) < 0);
return true;
}
} } // mcl::fp

@ -295,6 +295,7 @@ CYBOZU_TEST_AUTO(another)
CYBOZU_TEST_EQUAL(a, 1);
}
void fff(){}
CYBOZU_TEST_AUTO(setArray)
{
@ -306,7 +307,6 @@ CYBOZU_TEST_AUTO(setArray)
int b2[] = { 0x12, 0x34 };
x.setArray(b2, 2);
CYBOZU_TEST_EQUAL(x, Fp("0x3400000012"));
x.setStr("0xffffffffffff");
Fp::setModulo("0x10000000000001234567a5");
const struct {
@ -316,6 +316,8 @@ CYBOZU_TEST_AUTO(setArray)
} tbl[] = {
{ { 0x234567a4, 0x00000001, 0x00100000}, 1, "0x234567a4" },
{ { 0x234567a4, 0x00000001, 0x00100000}, 2, "0x1234567a4" },
{ { 0x234567a4, 0x00000001, 0x00080000}, 3, "0x08000000000001234567a4" },
{ { 0x234567a4, 0x00000001, 0x00100000}, 3, "0x10000000000001234567a4" },
};
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
x.setArray(tbl[i].buf, tbl[i].bufN);
@ -325,6 +327,32 @@ CYBOZU_TEST_AUTO(setArray)
CYBOZU_TEST_EXCEPTION(x.setArray(large, 3), cybozu::Exception);
}
CYBOZU_TEST_AUTO(setArrayMask)
{
Fp::setModulo("1000000000000000000117");
char b1[] = { 0x56, 0x34, 0x12 };
Fp x;
x.setArrayMask(b1, 3);
CYBOZU_TEST_EQUAL(x, 0x123456);
int b2[] = { 0x12, 0x34 };
x.setArrayMask(b2, 2);
CYBOZU_TEST_EQUAL(x, Fp("0x3400000012"));
Fp::setModulo("0x10000000000001234567a5");
const struct {
uint32_t buf[3];
size_t bufN;
const char *expected;
} tbl[] = {
{ { 0x234567a4, 0x00000001, 0x00100000}, 1, "0x234567a4" },
{ { 0x234567a4, 0x00000001, 0x00100000}, 2, "0x1234567a4" },
{ { 0x234567a4, 0x00000001, 0x00100000}, 3, "0x00000000000001234567a4" },
};
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
x.setArrayMask(tbl[i].buf, tbl[i].bufN);
CYBOZU_TEST_EQUAL(x, Fp(tbl[i].expected));
}
}
CYBOZU_TEST_AUTO(set64bit)
{
@ -359,7 +387,8 @@ CYBOZU_TEST_AUTO(getArray)
mpz_class x(tbl[i].s);
const size_t bufN = 8;
uint32_t buf[bufN];
size_t n = mcl::Gmp::getArray(buf, bufN, x);
mcl::Gmp::getArray(buf, bufN, x);
size_t n = mcl::fp::getNonZeroArraySize(buf, bufN);
CYBOZU_TEST_EQUAL(n, tbl[i].vn);
CYBOZU_TEST_EQUAL_ARRAY(buf, tbl[i].v, n);
}

@ -121,3 +121,19 @@ CYBOZU_TEST_AUTO(getRandVal)
}
}
CYBOZU_TEST_AUTO(maskArray)
{
const size_t n = 4;
uint16_t org[n] = { 0x1234, 0xabce, 0xef32, 0xffff };
for (size_t i = 0; i <= sizeof(org) * 8; i++) {
uint16_t x[n];
memcpy(x, org, sizeof(org));
mcl::fp::maskArray(x, n, i);
mpz_class t;
mcl::Gmp::setArray(t, org, n);
t &= (mpz_class(1) << i) - 1;
uint16_t y[n];
mcl::Gmp::getArray(y, n, t);
CYBOZU_TEST_EQUAL_ARRAY(x, y, n);
}
}

@ -130,12 +130,10 @@ struct Test {
compare();
modulo();
ope();
cvtInt();
power();
power_Zn();
setArray();
set64bit();
getArray();
bench();
}
void cstr()
@ -434,21 +432,6 @@ struct Test {
CYBOZU_TEST_EQUAL(z, castTo<Fp>(tbl[i].x));
}
}
void cvtInt()
{
#if 0
Fp x;
x = 12345;
uint64_t y = x.cvtInt();
CYBOZU_TEST_EQUAL(y, 12345u);
x.setStr("123456789012342342342342342");
CYBOZU_TEST_EXCEPTION(x.cvtInt(), cybozu::Exception);
bool err = false;
CYBOZU_TEST_NO_EXCEPTION(x.cvtInt(&err));
CYBOZU_TEST_ASSERT(err);
#endif
}
void power()
{
Fp x, y, z;
@ -503,30 +486,6 @@ struct Test {
CYBOZU_TEST_EQUAL(x, y);
}
}
void getArray()
{
const struct {
const char *s;
uint32_t v[4];
size_t vn;
} tbl[] = {
{ "0", { 0, 0, 0, 0 }, 1 },
{ "1234", { 1234, 0, 0, 0 }, 1 },
{ "0xaabbccdd12345678", { 0x12345678, 0xaabbccdd, 0, 0 }, 2 },
{ "0x11112222333344445555666677778888", { 0x77778888, 0x55556666, 0x33334444, 0x11112222 }, 4 },
};
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
mpz_class x(tbl[i].s);
const size_t bufN = 8;
uint32_t buf[bufN];
size_t n = mcl::Gmp::getArray(buf, bufN, x);
CYBOZU_TEST_EQUAL(n, tbl[i].vn);
for (size_t j = 0; j < n; j++) {
CYBOZU_TEST_EQUAL(buf[j], tbl[i].v[j]);
}
}
}
void bench()
{
Fp x("-123456789");

Loading…
Cancel
Save