aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMITSUNARI Shigeo <herumi@nifty.com>2018-05-17 15:08:43 +0800
committerMITSUNARI Shigeo <herumi@nifty.com>2018-05-17 15:08:43 +0800
commitb33f6fdaa09d89386b7fecc142df922d723b6f7d (patch)
tree344b978537fe914f5be45098b8b6ef530d3adf6c
parente280cc5443a8c9e404b10ca7dc1da51d5c251387 (diff)
downloaddexon-mcl-b33f6fdaa09d89386b7fecc142df922d723b6f7d.tar.gz
dexon-mcl-b33f6fdaa09d89386b7fecc142df922d723b6f7d.tar.zst
dexon-mcl-b33f6fdaa09d89386b7fecc142df922d723b6f7d.zip
reduce exception
-rw-r--r--Makefile2
-rw-r--r--include/mcl/fp.hpp67
-rw-r--r--include/mcl/op.hpp9
-rw-r--r--sample/bench.cpp3
-rw-r--r--src/conversion.hpp190
-rw-r--r--src/fp.cpp82
-rw-r--r--test/conversion_test.cpp57
-rw-r--r--test/fp_util_test.cpp38
8 files changed, 368 insertions, 80 deletions
diff --git a/Makefile b/Makefile
index 39f1341..f4230f3 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ LIB_DIR=lib
OBJ_DIR=obj
EXE_DIR=bin
SRC_SRC=fp.cpp bn_c256.cpp bn_c384.cpp bn_c512.cpp she_c256.cpp
-TEST_SRC=fp_test.cpp ec_test.cpp fp_util_test.cpp window_method_test.cpp elgamal_test.cpp fp_tower_test.cpp gmp_test.cpp bn_test.cpp bn384_test.cpp glv_test.cpp paillier_test.cpp she_test.cpp vint_test.cpp bn512_test.cpp ecdsa_test.cpp
+TEST_SRC=fp_test.cpp ec_test.cpp fp_util_test.cpp window_method_test.cpp elgamal_test.cpp fp_tower_test.cpp gmp_test.cpp bn_test.cpp bn384_test.cpp glv_test.cpp paillier_test.cpp she_test.cpp vint_test.cpp bn512_test.cpp ecdsa_test.cpp conversion_test.cpp
TEST_SRC+=bn_c256_test.cpp bn_c384_test.cpp bn_c512_test.cpp she_c256_test.cpp she_c384_test.cpp
TEST_SRC+=aggregate_sig_test.cpp
TEST_SRC+=bls12_test.cpp
diff --git a/include/mcl/fp.hpp b/include/mcl/fp.hpp
index 0fb347c..0bd04c6 100644
--- a/include/mcl/fp.hpp
+++ b/include/mcl/fp.hpp
@@ -92,6 +92,23 @@ void loadWord(std::string& s, InputStream& is)
}
}
+template<class InputStream>
+size_t loadWord(char *buf, size_t bufSize, InputStream& is)
+{
+ if (bufSize == 0) return 0;
+ char c;
+ if (!skipSpace(&c, is)) return 0;
+ size_t pos = 0;
+ buf[pos++] = c;
+ for (;;) {
+ if (!cybozu::readChar(&c, is)) break;
+ if (isSpace(c)) break;
+ if (pos == bufSize) return 0;
+ buf[pos++] = c;
+ }
+ return pos;
+}
+
} // local
} // mcl::fp
@@ -243,46 +260,72 @@ public:
if (isMont()) op_.fromMont(v_, v_);
}
template<class InputStream>
- void load(InputStream& is, int ioMode = IoSerialize)
+ void load(InputStream& is, int ioMode, bool *pb)
{
bool isMinus = false;
+ *pb = false;
if (ioMode & (IoArray | IoArrayRaw | IoSerialize)) {
const size_t n = getByteSize();
v_[op_.N - 1] = 0;
- if (cybozu::readSome(v_, n, is) != n) throw cybozu::Exception("FpT:load:can't read") << n;
+ if (cybozu::readSome(v_, n, is) != n) {
+ return;
+ }
} else {
- std::string str;
- fp::local::loadWord(str, is);
- fp::strToArray(&isMinus, v_, op_.N, str, ioMode);
+ char buf[1024];
+ size_t n = fp::local::loadWord(buf, sizeof(buf), is);
+ if (n == 0 || !fp::strToArray(&isMinus, v_, op_.N, buf, n, ioMode)) {
+ return;
+ }
+ }
+ if (fp::isGreaterOrEqualArray(v_, op_.p, op_.N)) {
+ return;
}
- if (fp::isGreaterOrEqualArray(v_, op_.p, op_.N)) throw cybozu::Exception("FpT:load:large value");
if (isMinus) {
neg(*this, *this);
}
if (!(ioMode & IoArrayRaw)) {
toMont();
}
+ *pb = true;
}
template<class OutputStream>
- void save(OutputStream& os, int ioMode = IoSerialize) const
+ void save(OutputStream& os, int ioMode, bool *pb) const
{
const size_t n = getByteSize();
if (ioMode & (IoArray | IoArrayRaw | IoSerialize)) {
if (ioMode & IoArrayRaw) {
- cybozu::write(os, v_, n);
+ cybozu::write(os, v_, n, pb);
} else {
fp::Block b;
getBlock(b);
- cybozu::write(os, b.p, n);
+ cybozu::write(os, b.p, n, pb);
}
return;
}
fp::Block b;
getBlock(b);
- std::string str;
// use low 8-bit ioMode for Fp
- fp::arrayToStr(str, b.p, b.n, ioMode & 255);
- cybozu::write(os, str.c_str(), str.size());
+ char buf[2048];
+ size_t len = fp::arrayToStr(buf, sizeof(buf), b.p, b.n, ioMode & 255);
+ if (len == 0) {
+ *pb = false;
+ return;
+ }
+ cybozu::write(os, buf + sizeof(buf) - len, len, pb);
+ }
+ template<class OutputStream>
+ void save(OutputStream& os, int ioMode = IoSerialize) const
+ {
+ bool b;
+ save(os, ioMode, &b);
+ if (!b) throw cybozu::Exception("fp:save") << ioMode;
+ }
+ template<class InputStream>
+ void load(InputStream& is, int ioMode = IoSerialize)
+ {
+ bool b;
+ load(is, ioMode, &b);
+ if (!b) throw cybozu::Exception("fp:load") << ioMode;
}
/*
throw exception if x >= p
diff --git a/include/mcl/op.hpp b/include/mcl/op.hpp
index 4e577a2..7132721 100644
--- a/include/mcl/op.hpp
+++ b/include/mcl/op.hpp
@@ -323,9 +323,14 @@ private:
/*
conevrt string to array according to ioMode,
*/
-void strToArray(bool *pIsMinus, Unit *x, size_t xN, const std::string& str, int ioMode);
+bool strToArray(bool *pIsMinus, Unit *x, size_t xN, const std::string& str, int ioMode);
+bool strToArray(bool *pIsMinus, Unit *x, size_t xN, const char *buf, size_t bufSize, int ioMode);
-void arrayToStr(std::string& str, const Unit *x, size_t n, int ioMode);
+/*
+ return retavl is written size if success else 0
+ REMARK : the top of string is buf + bufSize - retval
+*/
+size_t arrayToStr(char *buf, size_t bufSize, const Unit *x, size_t n, int ioMode);
inline const char* getIoSeparator(int ioMode)
{
diff --git a/sample/bench.cpp b/sample/bench.cpp
index 67f5da5..14997f8 100644
--- a/sample/bench.cpp
+++ b/sample/bench.cpp
@@ -146,9 +146,10 @@ void benchToStr16()
};
Fp::init("0xffffffffffffffffffffffffffffffffffffffffffffff13");
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ char buf[128];
std::string str;
Fp x(tbl[i]);
- CYBOZU_BENCH("fp::toStr16", mcl::fp::toStr16, str, x.getUnit(), x.getUnitSize(), 16);
+ CYBOZU_BENCH("fp::arrayToHex", mcl::fp::arrayToHex, buf, sizeof(buf), x.getUnit(), x.getUnitSize(), true);
mpz_class y(tbl[i]);
CYBOZU_BENCH("gmp:getStr ", mcl::gmp::getStr, str, y, 16);
}
diff --git a/src/conversion.hpp b/src/conversion.hpp
index 2383efd..9292a72 100644
--- a/src/conversion.hpp
+++ b/src/conversion.hpp
@@ -14,11 +14,13 @@
namespace mcl { namespace fp {
/*
- convert x[0..n) to hex string
+ convert little endian x[0, xn) to buf
+ return written size if success else 0
+ data is buf[bufSize - retval, bufSize)
start "0x" if withPrefix
*/
template<class T>
-void toStr16(std::string& str, const T *x, size_t n, bool withPrefix = false)
+size_t arrayToHex(char *buf, size_t bufSize, const T *x, size_t n, bool withPrefix = false)
{
size_t fullN = 0;
if (n > 1) {
@@ -33,23 +35,28 @@ void toStr16(std::string& str, const T *x, size_t n, bool withPrefix = false)
const size_t topLen = cybozu::getHexLength(v);
const size_t startPos = withPrefix ? 2 : 0;
const size_t lenT = sizeof(T) * 2;
- str.resize(startPos + fullN * lenT + topLen);
+ const size_t totalSize = startPos + fullN * lenT + topLen;
+ if (totalSize > bufSize) return 0;
+ char *const top = buf + bufSize - totalSize;
if (withPrefix) {
- str[0] = '0';
- str[1] = 'x';
+ top[0] = '0';
+ top[1] = 'x';
}
- cybozu::itohex(&str[startPos], topLen, v, false);
+ cybozu::itohex(&top[startPos], topLen, v, false);
for (size_t i = 0; i < fullN; i++) {
- cybozu::itohex(&str[startPos + topLen + i * lenT], lenT, x[fullN - 1 - i], false);
+ cybozu::itohex(&top[startPos + topLen + i * lenT], lenT, x[fullN - 1 - i], false);
}
+ return totalSize;
}
/*
- convert x[0..n) to bin string
+ convert little endian x[0, xn) to buf
+ return written size if success else 0
+ data is buf[bufSize - retval, bufSize)
start "0b" if withPrefix
*/
template<class T>
-void toStr2(std::string& str, const T *x, size_t n, bool withPrefix)
+size_t arrayToBin(char *buf, size_t bufSize, const T *x, size_t n, bool withPrefix)
{
size_t fullN = 0;
if (n > 1) {
@@ -64,15 +71,18 @@ void toStr2(std::string& str, const T *x, size_t n, bool withPrefix)
const size_t topLen = cybozu::getBinLength(v);
const size_t startPos = withPrefix ? 2 : 0;
const size_t lenT = sizeof(T) * 8;
- str.resize(startPos + fullN * lenT + topLen);
+ const size_t totalSize = startPos + fullN * lenT + topLen;
+ if (totalSize > bufSize) return 0;
+ char *const top = buf + bufSize - totalSize;
if (withPrefix) {
- str[0] = '0';
- str[1] = 'b';
+ top[0] = '0';
+ top[1] = 'b';
}
- cybozu::itobin(&str[startPos], topLen, v);
+ cybozu::itobin(&top[startPos], topLen, v);
for (size_t i = 0; i < fullN; i++) {
- cybozu::itobin(&str[startPos + topLen + i * lenT], lenT, x[fullN - 1 - i]);
+ cybozu::itobin(&top[startPos + topLen + i * lenT], lenT, x[fullN - 1 - i]);
}
+ return totalSize;
}
/*
@@ -101,5 +111,155 @@ void fromStr16(T *x, size_t xn, const char *str, size_t strLen)
for (size_t i = requireSize; i < xn; i++) x[i] = 0;
}
+namespace local {
-} } // mcl::fp
+/*
+ q = x[] / x
+ @retval r = x[] % x
+ @note accept q == x
+*/
+inline uint32_t divU32(uint32_t *q, const uint32_t *x, size_t xn, uint32_t y)
+{
+ if (xn == 0) return 0;
+ uint32_t r = 0;
+ for (int i = (int)xn - 1; i >= 0; i--) {
+ uint64_t t = (uint64_t(r) << 32) | x[i];
+ q[i] = uint32_t(t / y);
+ r = uint32_t(t % y);
+ }
+ return r;
+}
+
+/*
+ z[0, xn) = x[0, xn) * y
+ return z[xn]
+ @note accept z == x
+*/
+inline uint32_t mulU32(uint32_t *z, const uint32_t *x, size_t xn, uint32_t y)
+{
+ uint32_t H = 0;
+ for (size_t i = 0; i < xn; i++) {
+ uint32_t t = H;
+ uint64_t v = uint64_t(x[i]) * y;
+ uint32_t L = uint32_t(v);
+ H = uint32_t(v >> 32);
+ z[i] = t + L;
+ if (z[i] < t) {
+ H++;
+ }
+ }
+ return H;
+}
+
+/*
+ x[0, xn) += y
+ return 1 if overflow else 0
+*/
+inline uint32_t addU32(uint32_t *x, size_t xn, uint32_t y)
+{
+ uint32_t t = x[0] + y;
+ x[0] = t;
+ if (t >= y) return 0;
+ for (size_t i = 1; i < xn; i++) {
+ t = x[i] + 1;
+ x[i] = t;
+ if (t != 0) return 0;
+ }
+ return 1;
+}
+
+inline uint32_t decToU32(const char *p, size_t size, bool *pb)
+{
+ assert(0 < size && size <= 9);
+ uint32_t x = 0;
+ for (size_t i = 0; i < size; i++) {
+ char c = p[i];
+ if (c < '0' || c > '9') {
+ *pb = false;
+ return 0;
+ }
+ x = x * 10 + uint32_t(c - '0');
+ }
+ *pb = true;
+ return x;
+}
+
+} // mcl::fp::local
+
+/*
+ little endian x[0, xn) to buf
+ return written size if success else 0
+ data is buf[bufSize - retval, bufSize)
+*/
+template<class UT>
+inline size_t arrayToDec(char *buf, size_t bufSize, const UT *x, size_t xn)
+{
+ const size_t maxN = 64;
+ uint32_t t[maxN];
+ if (sizeof(UT) == 8) {
+ xn *= 2;
+ }
+ if (xn > maxN) return 0;
+ memcpy(t, x, xn * sizeof(t[0]));
+
+ const size_t width = 9;
+ const uint32_t i1e9 = 1000000000U;
+ size_t pos = 0;
+ for (;;) {
+ uint32_t r = local::divU32(t, t, xn, i1e9);
+ while (xn > 0 && t[xn - 1] == 0) xn--;
+ size_t len = cybozu::itoa_local::uintToDec(buf, bufSize - pos, r);
+ if (len == 0) return 0;
+ assert(0 < len && len <= width);
+ if (xn == 0) return pos + len;
+ // fill (width - len) '0'
+ for (size_t j = 0; j < width - len; j++) {
+ buf[bufSize - pos - width + j] = '0';
+ }
+ pos += width;
+ }
+}
+
+/*
+ convert buf[0, bufSize) to x[0, num)
+ return written num if success else 0
+*/
+template<class UT>
+inline size_t convertDecToArray(UT *_x, size_t xSize, const char *buf, size_t bufSize)
+{
+ assert(sizeof(UT) == 4 || sizeof(UT) == 8);
+ const size_t width = 9;
+ const uint32_t i1e9 = 1000000000U;
+ if (xSize == 0) return 0;
+ if (sizeof(UT) == 8) {
+ xSize *= 2;
+ }
+ uint32_t *x = reinterpret_cast<uint32_t*>(_x);
+ size_t xn = 1;
+ x[0] = 0;
+ while (bufSize > 0) {
+ size_t n = bufSize % width;
+ if (n == 0) n = width;
+ bool b;
+ uint32_t v = local::decToU32(buf, n, &b);
+ if (!b) return 0;
+ uint32_t H = local::mulU32(x, x, xn, i1e9);
+ if (H > 0) {
+ if (xn == xSize) return 0;
+ x[xn++] = H;
+ }
+ H = local::addU32(x, xn, v);
+ if (H > 0) {
+ if (xn == xSize) return 0;
+ x[xn++] = H;
+ }
+ buf += n;
+ bufSize -= n;
+ }
+ if (sizeof(UT) == 8 && (xn & 1)) {
+ x[xn++] = 0;
+ }
+ return xn / (sizeof(UT) / 4);
+}
+
+} } // mcp::fp
diff --git a/src/fp.cpp b/src/fp.cpp
index f576366..bcbb23f 100644
--- a/src/fp.cpp
+++ b/src/fp.cpp
@@ -63,35 +63,39 @@ inline Unit getUnitAsLE(const void *p)
#endif
}
-const char *verifyStr(bool *isMinus, int *base, const std::string& str)
+bool parsePrefix(size_t *readSize, bool *isMinus, int *base, const char *buf, size_t bufSize)
{
- const char *p = str.c_str();
- if (*p == '-') {
+ if (bufSize == 0) return false;
+ size_t pos = 0;
+ if (*buf == '-') {
+ if (bufSize == 1) return false;
*isMinus = true;
- p++;
+ buf++;
+ pos++;
} else {
*isMinus = false;
}
- if (p[0] == '0') {
- if (p[1] == 'x') {
+ if (buf[0] == '0') {
+ if (bufSize > 1 && buf[1] == 'x') {
if (*base == 0 || *base == 16 || *base == (16 | IoPrefix)) {
*base = 16;
- p += 2;
+ pos += 2;
} else {
- throw cybozu::Exception("fp:verifyStr:0x conflicts with") << *base;
+ return false;
}
- } else if (p[1] == 'b') {
+ } else if (bufSize > 1 && buf[1] == 'b') {
if (*base == 0 || *base == 2 || *base == (2 | IoPrefix)) {
*base = 2;
- p += 2;
+ pos += 2;
} else {
- throw cybozu::Exception("fp:verifyStr:0b conflicts with") << *base;
+ return false;
}
}
}
if (*base == 0) *base = 10;
- if (*p == '\0') throw cybozu::Exception("fp:verifyStr:str is empty");
- return p;
+ if (pos == bufSize) return false;
+ *readSize = pos;
+ return true;
}
const char *ModeToStr(Mode mode)
@@ -442,13 +446,17 @@ void Op::init(const std::string& mstr, size_t maxBitSize, Mode mode, size_t mclM
{ // set mp and p
bool isMinus = false;
int base = 0;
- const char *pstr = verifyStr(&isMinus, &base, mstr);
- if (isMinus) throw cybozu::Exception("Op:init:mstr is minus") << mstr;
+ size_t readSize;
+ if (!parsePrefix(&readSize, &isMinus, &base, mstr.c_str(), mstr.size())) {
+ throw cybozu::Exception("fp:parsePrefix");
+ }
+ const char *pstr = mstr.c_str() + readSize;
if (!gmp::setStr(mp, pstr, base)) {
throw cybozu::Exception("Op:init:bad str") << mstr;
}
- if (mp == 0) throw cybozu::Exception("Op:init:mstr is zero") << mstr;
+ if (isMinus) throw cybozu::Exception("Op:init:mstr is minus") << mstr;
}
+ if (mp == 0) throw cybozu::Exception("Op:init:mstr is zero") << mstr;
gmp::getArray(p, (maxBitSize + fp::UnitBitSize - 1) / fp::UnitBitSize, mp);
bitSize = gmp::getBitSize(mp);
pmod4 = gmp::getUnit(mp, 0) % 4;
@@ -571,27 +579,20 @@ void Op::init(const std::string& mstr, size_t maxBitSize, Mode mode, size_t mclM
}
}
-void arrayToStr(std::string& str, const Unit *x, size_t n, int ioMode)
+size_t arrayToStr(char *buf, size_t bufSize, const Unit *x, size_t n, int ioMode)
{
int base = ioMode & ~IoPrefix;
bool withPrefix = (ioMode & IoPrefix) != 0;
switch (base) {
case 0:
case 10:
- {
- mpz_class t;
- gmp::setArray(t, x, n);
- gmp::getStr(str, t, 10);
- }
- return;
+ return mcl::fp::arrayToDec(buf, bufSize, x, n);
case 16:
- mcl::fp::toStr16(str, x, n, withPrefix);
- return;
+ return mcl::fp::arrayToHex(buf, bufSize, x, n, withPrefix);
case 2:
- mcl::fp::toStr2(str, x, n, withPrefix);
- return;
+ return mcl::fp::arrayToBin(buf, bufSize, x, n, withPrefix);
default:
- throw cybozu::Exception("fp:arrayToStr:bad base") << base;
+ return 0;
}
}
@@ -639,17 +640,22 @@ int detectIoMode(int ioMode, const std::ios_base& ios)
return ioMode;
}
-void strToArray(bool *pIsMinus, Unit *x, size_t xN, const std::string& str, int ioMode)
+bool strToArray(bool *pIsMinus, Unit *x, size_t xN, const char *buf, size_t bufSize, int ioMode)
{
assert(!(ioMode & (IoArray | IoArrayRaw | IoSerialize)));
// use low 8-bit ioMode for Fp
ioMode &= 0xff;
- const char *p = verifyStr(pIsMinus, &ioMode, str);
+ size_t readSize;
+ if (!parsePrefix(&readSize, pIsMinus, &ioMode, buf, bufSize)) return false;
+#if 0
+#else
mpz_class mx;
- if (!gmp::setStr(mx, p, ioMode)) {
- throw cybozu::Exception("fp:strToArray:bad format") << ioMode << str;
+ if (!gmp::setStr(mx, std::string(buf + readSize, bufSize - readSize), ioMode)) {
+ return false;
}
gmp::getArray(x, xN, mx);
+#endif
+ return true;
}
void copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, MaskMode maskMode)
@@ -704,11 +710,7 @@ uint64_t getUint64(bool *pb, const fp::Block& b)
if (pb) *pb = true;
return v;
}
- if (!pb) {
- std::string str;
- arrayToStr(str, b.p, b.n, 10);
- throw cybozu::Exception("fp::getUint64:large value") << str;
- }
+ if (!pb) throw cybozu::Exception("fp::getUint64:large value");
*pb = false;
return 0;
}
@@ -743,11 +745,7 @@ int64_t getInt64(bool *pb, fp::Block& b, const fp::Op& op)
}
}
}
- if (!pb) {
- std::string str;
- arrayToStr(str, b.p, b.n, 10);
- throw cybozu::Exception("fp::getInt64:large value") << str << isNegative;
- }
+ if (!pb) throw cybozu::Exception("fp::getInt64:large value");
*pb = false;
return 0;
}
diff --git a/test/conversion_test.cpp b/test/conversion_test.cpp
new file mode 100644
index 0000000..3f1f959
--- /dev/null
+++ b/test/conversion_test.cpp
@@ -0,0 +1,57 @@
+#include <cybozu/test.hpp>
+#include "../src/conversion.hpp"
+
+CYBOZU_TEST_AUTO(arrayToDec)
+{
+ const struct {
+ uint32_t x[5];
+ size_t xn;
+ const char *s;
+ } tbl[] = {
+ { { 0, 0, 0, 0, 0 }, 1, "0" },
+ { { 9, 0, 0, 0, 0 }, 1, "9" },
+ { { 123456789, 0, 0, 0, 0 }, 1, "123456789" },
+ { { 2147483647, 0, 0, 0, 0 }, 1, "2147483647" },
+ { { 0xffffffff, 0, 0, 0, 0 }, 1, "4294967295" },
+ { { 0x540be400, 0x2, 0, 0, 0 }, 2, "10000000000" },
+ { { 0xffffffff, 0xffffffff, 0, 0, 0 }, 2, "18446744073709551615" },
+ { { 0x89e80001, 0x8ac72304, 0, 0, 0 }, 2, "10000000000000000001" },
+ { { 0xc582ca00, 0x8ac72304, 0, 0, 0 }, 2, "10000000001000000000" },
+ { { 0, 0, 1, 0, 0 }, 3, "18446744073709551616" },
+ { { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0 }, 4, "340282366920938463463374607431768211455" },
+ { { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }, 5, "1461501637330902918203684832716283019655932542975" },
+ { { 0x3b9aca00, 0x5e3f3700, 0x1cbfa532, 0x04f6433a, 0xd83ff078 }, 5, "1234567901234560000000000000000000000001000000000" },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const size_t bufSize = 128;
+ char buf[bufSize] = {};
+ const char *str = tbl[i].s;
+ const uint32_t *x = tbl[i].x;
+ const size_t strLen = strlen(str);
+ size_t n = mcl::fp::arrayToDec(buf, bufSize, x, tbl[i].xn);
+ CYBOZU_TEST_EQUAL(n, strLen);
+ CYBOZU_TEST_EQUAL_ARRAY(buf + bufSize - n, str, n);
+ const size_t maxN = 32;
+ uint32_t xx[maxN] = {};
+ size_t xn = mcl::fp::convertDecToArray(xx, maxN, str, strLen);
+ CYBOZU_TEST_EQUAL(xn, tbl[i].xn);
+ CYBOZU_TEST_EQUAL_ARRAY(xx, x, xn);
+ }
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const size_t bufSize = 128;
+ char buf[bufSize] = {};
+ const char *str = tbl[i].s;
+ const size_t strLen = strlen(str);
+ uint64_t x[8] = {};
+ size_t xn = (tbl[i].xn + 1) / 2;
+ memcpy(x, tbl[i].x, tbl[i].xn * sizeof(uint32_t));
+ size_t n = mcl::fp::arrayToDec(buf, bufSize, x, xn);
+ CYBOZU_TEST_EQUAL(n, strLen);
+ CYBOZU_TEST_EQUAL_ARRAY(buf + bufSize - n, str, n);
+ const size_t maxN = 32;
+ uint64_t xx[maxN] = {};
+ size_t xxn = mcl::fp::convertDecToArray(xx, maxN, str, strLen);
+ CYBOZU_TEST_EQUAL(xxn, xn);
+ CYBOZU_TEST_EQUAL_ARRAY(xx, x, xn);
+ }
+}
diff --git a/test/fp_util_test.cpp b/test/fp_util_test.cpp
index fbbe166..72e6c7d 100644
--- a/test/fp_util_test.cpp
+++ b/test/fp_util_test.cpp
@@ -4,7 +4,7 @@
#include <mcl/gmp_util.hpp>
#include <mcl/fp.hpp>
-CYBOZU_TEST_AUTO(toStr16)
+CYBOZU_TEST_AUTO(arrayToHex)
{
const struct {
uint32_t x[4];
@@ -18,15 +18,39 @@ CYBOZU_TEST_AUTO(toStr16)
{ { 1, 2, 0xffffffff, 0x123abc }, 4, "123abcffffffff0000000200000001" },
};
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
- std::string str;
- mcl::fp::toStr16(str, tbl[i].x, tbl[i].n, false);
- CYBOZU_TEST_EQUAL(str, tbl[i].str);
- mcl::fp::toStr16(str, tbl[i].x, tbl[i].n, true);
- CYBOZU_TEST_EQUAL(str, std::string("0x") + tbl[i].str);
+ char buf[64];
+ size_t n = mcl::fp::arrayToHex(buf, sizeof(buf), tbl[i].x, tbl[i].n, false);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, tbl[i].str, n);
+ n = mcl::fp::arrayToHex(buf, sizeof(buf), tbl[i].x, tbl[i].n, true);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, (std::string("0x") + tbl[i].str).c_str(), n);
}
}
-// CYBOZU_TEST_AUTO(toStr2) // QQQ
+CYBOZU_TEST_AUTO(arrayToBin)
+{
+ const struct {
+ uint32_t x[4];
+ size_t n;
+ const char *str;
+ } tbl[] = {
+ { { 0, 0, 0, 0 }, 0, "0" },
+ { { 0x123, 0, 0, 0 }, 1, "100100011" },
+ { { 0x12345678, 0xaabbcc, 0, 0 }, 2, "10101010101110111100110000010010001101000101011001111000" },
+ { { 0, 0x12, 0x234a, 0 }, 3, "100011010010100000000000000000000000000001001000000000000000000000000000000000" },
+ { { 1, 2, 0xffffffff, 0x123abc }, 4, "100100011101010111100111111111111111111111111111111110000000000000000000000000000001000000000000000000000000000000001" },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ char buf[512];
+ size_t n = mcl::fp::arrayToBin(buf, sizeof(buf), tbl[i].x, tbl[i].n, false);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, tbl[i].str, n);
+ n = mcl::fp::arrayToBin(buf, sizeof(buf), tbl[i].x, tbl[i].n, true);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, (std::string("0b") + tbl[i].str).c_str(), n);
+ }
+}
// CYBOZU_TEST_AUTO(verifyStr) // QQQ
CYBOZU_TEST_AUTO(fromStr16)