add test of getInt64

dev
MITSUNARI Shigeo 9 years ago
parent 9485c39fd2
commit 2ad7898bee
  1. 49
      include/mcl/fp.hpp
  2. 63
      src/fp.cpp
  3. 27
      test/fp_test.cpp

@ -44,20 +44,8 @@ bool strToMpzArray(size_t *pBitSize, Unit *y, size_t maxBitSize, mpz_class& x, c
void copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, bool doMask);
inline bool isInUint64(uint64_t *pv, const fp::Block& b)
{
assert(fp::UnitBitSize == 32 || fp::UnitBitSize == 64);
const size_t start = 64 / fp::UnitBitSize;
for (size_t i = start; i < b.n; i++) {
if (b.p[i]) return false;
}
#if CYBOZU_OS_BIT == 32
*pv = b.p[0] | (uint64_t(b.p[1]) << 32);
#else
*pv = b.p[0];
#endif
return true;
}
uint64_t getUint64(bool *pb, const fp::Block& b);
int64_t getInt64(bool *pb, fp::Block& b, const fp::Op& op);
} // mcl::fp
@ -347,42 +335,13 @@ public:
{
fp::Block b;
getBlock(b);
uint64_t v;
if (fp::isInUint64(&v, b)) {
if (pb) *pb = true;
return v;
}
if (!pb) throw cybozu::Exception("fpT::getUint64:large value") << *this;
*pb = false;
return 0;
return fp::getUint64(pb, b);
}
int64_t getInt64(bool *pb = 0) const
{
fp::Block b;
getBlock(b);
bool isNegative = false;
if (fp::isGreaterArray(b.p, op_.half, op_.N)) {
op_.neg(b.p, b.p);
isNegative = true;
}
uint64_t v;
if (fp::isInUint64(&v, b)) {
const uint64_t c = uint64_t(1) << 63;
if (isNegative) {
if (v >= c) {
if (pb) *pb = true;
return int64_t(-v);
}
} else {
if (v < c) {
if (pb) *pb = true;
return int64_t(v);
}
}
}
if (!pb) throw cybozu::Exception("fpT::getInt64:large value") << *this;
*pb = false;
return 0;
return fp::getInt64(pb, b, op_);
}
static inline size_t getModBitLen() { return op_.bitSize; }
bool operator==(const FpT& rhs) const { return fp::isEqualArray(v_, rhs.v_, op_.N); }

@ -346,5 +346,68 @@ void copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, bool do
assert(isLessArray(y, op.p, op.N));
}
static bool isInUint64(uint64_t *pv, const fp::Block& b)
{
assert(fp::UnitBitSize == 32 || fp::UnitBitSize == 64);
const size_t start = 64 / fp::UnitBitSize;
for (size_t i = start; i < b.n; i++) {
if (b.p[i]) return false;
}
#if CYBOZU_OS_BIT == 32
*pv = b.p[0] | (uint64_t(b.p[1]) << 32);
#else
*pv = b.p[0];
#endif
return true;
}
uint64_t getUint64(bool *pb, const fp::Block& b)
{
uint64_t v;
if (isInUint64(&v, b)) {
if (pb) *pb = true;
return v;
}
if (!pb) {
std::string str;
arrayToStr(str, b.p, b.n, 10, false);
throw cybozu::Exception("fp::getUint64:large value") << str;
}
*pb = false;
return 0;
}
int64_t getInt64(bool *pb, fp::Block& b, const fp::Op& op)
{
bool isNegative = false;
if (fp::isGreaterArray(b.p, op.half, op.N)) {
op.neg(b.v_, b.p);
b.p = b.v_;
isNegative = true;
}
uint64_t v;
if (fp::isInUint64(&v, b)) {
const uint64_t c = uint64_t(1) << 63;
if (isNegative) {
if (v <= c) { // include c
if (pb) *pb = true;
return int64_t(-v);
}
} else {
if (v < c) { // not include c
if (pb) *pb = true;
return int64_t(v);
}
}
}
if (!pb) {
std::string str;
arrayToStr(str, b.p, b.n, 10, false);
throw cybozu::Exception("fp::getInt64:large value") << str << isNegative;
}
*pb = false;
return 0;
}
} } // mcl::fp

@ -387,6 +387,7 @@ CYBOZU_TEST_AUTO(getUint64)
uint64_t a = tbl[i];
Fp x(a);
uint64_t b = x.getUint64();
CYBOZU_TEST_ASSERT(!x.isNegative());
CYBOZU_TEST_EQUAL(a, b);
}
{
@ -407,6 +408,32 @@ CYBOZU_TEST_AUTO(getUint64)
}
}
CYBOZU_TEST_AUTO(getInt64)
{
Fp::setModulo("0x1000000000000000000f");
const int64_t tbl[] = {
0, 1, 123, 0xffffffff, int64_t(0x7fffffffffffffffull),
-1, -2, -12345678, int64_t(-9223372036854775808ull),
};
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
int64_t a = tbl[i];
Fp x(a);
CYBOZU_TEST_EQUAL(x.isNegative(), a < 0);
int64_t b = x.getInt64();
CYBOZU_TEST_EQUAL(a, b);
}
{
Fp x("0x8000000000000000");
CYBOZU_TEST_EXCEPTION(x.getInt64(), cybozu::Exception);
}
{
Fp x("0x8000000000000000");
bool b = true;
CYBOZU_TEST_EQUAL(x.getInt64(&b), 0);
CYBOZU_TEST_ASSERT(!b);
}
}
CYBOZU_TEST_AUTO(getArray)
{
const struct {

Loading…
Cancel
Save