diff options
author | MITSUNARI Shigeo <herumi@nifty.com> | 2017-04-08 08:25:00 +0800 |
---|---|---|
committer | MITSUNARI Shigeo <herumi@nifty.com> | 2017-04-08 13:35:10 +0800 |
commit | 22ea6ac90222d3e4b3a8549c55779388ede78301 (patch) | |
tree | 1f240ec930f350b49dece7f05e80c6261adbab02 | |
parent | 84a05e93499d6a01abdf95a634e5521e51b361ee (diff) | |
download | tangerine-mcl-22ea6ac90222d3e4b3a8549c55779388ede78301.tar.gz tangerine-mcl-22ea6ac90222d3e4b3a8549c55779388ede78301.tar.zst tangerine-mcl-22ea6ac90222d3e4b3a8549c55779388ede78301.zip |
add copyByteToUnitAsLE and copyUnitToByteAsLE
_
-rw-r--r-- | include/mcl/fp.hpp | 10 | ||||
-rw-r--r-- | src/fp.cpp | 55 | ||||
-rw-r--r-- | test/fp_test.cpp | 40 |
3 files changed, 100 insertions, 5 deletions
diff --git a/include/mcl/fp.hpp b/include/mcl/fp.hpp index 3a6d0fc..ddfdb07 100644 --- a/include/mcl/fp.hpp +++ b/include/mcl/fp.hpp @@ -75,6 +75,10 @@ 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); +// copy src to dst as little endian +void copyUnitToByteAsLE(void *dst, const Unit *src, size_t byteSize); +// copy src to dst as little endian +void copyByteToUnitAsLE(Unit *dst, const void *src, size_t byteSize); void copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, bool doMask); uint64_t getUint64(bool *pb, const fp::Block& b); @@ -235,7 +239,7 @@ public: const size_t n = getByteSize(); if (str.size() != n) throw cybozu::Exception("FpT:setStr:bad size") << str.size() << n << ioMode; if (ioMode & IoArrayRaw) { - memcpy(v_, str.c_str(), n); + fp::copyByteToUnitAsLE(v_, str.c_str(), n); if (!isValid()) throw cybozu::Exception("FpT:setStr:bad value") << str; } else { setArray(&str[0], n); @@ -315,14 +319,14 @@ public: const size_t n = getByteSize(); if (ioMode & IoArrayRaw) { str.resize(n); - memcpy(&str[0], v_, str.size()); + fp::copyUnitToByteAsLE(&str[0], v_, str.size()); return; } fp::Block b; getBlock(b); if (ioMode & IoArray) { str.resize(n); - memcpy(&str[0], b.p, str.size()); + fp::copyUnitToByteAsLE(&str[0], b.p, str.size()); return; } fp::arrayToStr(str, b.p, b.n, ioMode & ~IoPrefix, (ioMode & IoPrefix) != 0); @@ -1,6 +1,7 @@ #include <mcl/op.hpp> #include <mcl/util.hpp> #include <cybozu/crypto.hpp> +#include <cybozu/endian.hpp> #include "conversion.hpp" #include "fp_generator.hpp" #include "low_func.hpp" @@ -36,6 +37,22 @@ void Op::destroyFpGenerator(FpGenerator *) } #endif +inline void setUnitAsLE(void *p, Unit x) +{ +#if CYBOZU_OS_BIT == 32 + cybozu::Set32bitAsLE(p, x); +#else + cybozu::Set64bitAsLE(p, x); +#endif +} +inline Unit getUnitAsLE(const void *p) +{ +#if CYBOZU_OS_BIT == 32 + return cybozu::Get32bitAsLE(p); +#else + return cybozu::Get64bitAsLE(p); +#endif +} /* use prefix if base conflicts with prefix */ @@ -468,6 +485,38 @@ void arrayToStr(std::string& str, const Unit *x, size_t n, int base, bool withPr } } +void copyUnitToByteAsLE(void *dst, const Unit *src, size_t byteSize) +{ + uint8_t *p = reinterpret_cast<uint8_t*>(dst); + while (byteSize >= sizeof(Unit)) { + setUnitAsLE(p, *src++); + p += sizeof(Unit); + byteSize -= sizeof(Unit); + } + if (byteSize == 0) return; + Unit x = *src; + while (byteSize) { + *p++ = static_cast<uint8_t>(x); + x >>= 8; + byteSize--; + } +} + +void copyByteToUnitAsLE(Unit *dst, const void *src, size_t byteSize) +{ + const uint8_t *p = reinterpret_cast<const uint8_t*>(src); + while (byteSize >= sizeof(Unit)) { + *dst++ = getUnitAsLE(p); + p += sizeof(Unit); + byteSize -= sizeof(Unit); + } + if (byteSize == 0) return; + Unit x = 0; + for (size_t i = 0; i < byteSize; i++) { + x |= Unit(p[i]) << (i * 8); + } + *dst = x; +} void copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, bool doMask) { const size_t fpByteSize = sizeof(Unit) * op.N; @@ -475,8 +524,10 @@ void copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, bool do if (!doMask) throw cybozu::Exception("fp:copyAndMask:bad size") << xByteSize << fpByteSize; xByteSize = fpByteSize; } - memcpy(y, x, xByteSize); - memset((char *)y + xByteSize, 0, fpByteSize - xByteSize); + copyByteToUnitAsLE(y, x, xByteSize); + for (size_t i = (xByteSize + sizeof(Unit) - 1) / sizeof(Unit); i < op.N; i++) { + y[i] = 0; + } if (!doMask) { if (isGreaterOrEqualArray(y, op.p, op.N)) throw cybozu::Exception("fp:copyAndMask:large x"); return; diff --git a/test/fp_test.cpp b/test/fp_test.cpp index 390c6ab..f0b4f0d 100644 --- a/test/fp_test.cpp +++ b/test/fp_test.cpp @@ -889,6 +889,46 @@ CYBOZU_TEST_AUTO(main) #endif } +CYBOZU_TEST_AUTO(copyUnitToByteAsLE) +{ + using namespace mcl::fp; +#if CYBOZU_OS_BIT == 32 + const Unit src[] = { 0x12345678, 0xaabbccdd, 0xffeeddcc, 0x87654321 }; +#else + const Unit src[] = { uint64_t(0xaabbccdd12345678ull), uint64_t(0x87654321ffeeddcc) }; +#endif + const uint8_t ok[] = { 0x78, 0x56, 0x34, 0x12, 0xdd, 0xcc, 0xbb, 0xaa, 0xcc, 0xdd, 0xee, 0xff, 0x21, 0x43, 0x65, 0x87 }; + const size_t okN = CYBOZU_NUM_OF_ARRAY(ok); + for (size_t i = 0; i < okN; i++) { + uint8_t buf[okN] = {}; + copyUnitToByteAsLE(buf, src, i); + CYBOZU_TEST_EQUAL_ARRAY(ok, buf, i); + } + mcl::fp::Unit dst[2]; + for (size_t i = 1; i <= sizeof(dst); i++) { + memset(dst, 0xff, sizeof(dst)); + mcl::fp::copyByteToUnitAsLE(dst, ok, i); + if (i < sizeof(Unit)) { + CYBOZU_TEST_EQUAL(src[0] & ((uint64_t(1) << (i * 8)) - 1), dst[0]); + CYBOZU_TEST_EQUAL(dst[1], Unit(-1)); + continue; + } + CYBOZU_TEST_EQUAL(dst[0], src[0]); + if (i == sizeof(Unit)) { + CYBOZU_TEST_EQUAL(dst[1], Unit(-1)); + continue; + } + if (i < sizeof(dst)) { + CYBOZU_TEST_EQUAL(src[1] & ((uint64_t(1) << ((i - sizeof(Unit)) * 8)) - 1), dst[1]); + continue; + } + CYBOZU_TEST_EQUAL(src[1], dst[1]); + } + dst[0] = 1; + copyByteToUnitAsLE(dst, ok, 0); + CYBOZU_TEST_EQUAL(dst[0], 1); +} + int main(int argc, char *argv[]) try { |