aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMITSUNARI Shigeo <herumi@nifty.com>2017-04-08 08:25:00 +0800
committerMITSUNARI Shigeo <herumi@nifty.com>2017-04-08 13:35:10 +0800
commit22ea6ac90222d3e4b3a8549c55779388ede78301 (patch)
tree1f240ec930f350b49dece7f05e80c6261adbab02
parent84a05e93499d6a01abdf95a634e5521e51b361ee (diff)
downloadtangerine-mcl-22ea6ac90222d3e4b3a8549c55779388ede78301.tar.gz
tangerine-mcl-22ea6ac90222d3e4b3a8549c55779388ede78301.tar.zst
tangerine-mcl-22ea6ac90222d3e4b3a8549c55779388ede78301.zip
add copyByteToUnitAsLE and copyUnitToByteAsLE
_
-rw-r--r--include/mcl/fp.hpp10
-rw-r--r--src/fp.cpp55
-rw-r--r--test/fp_test.cpp40
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);
diff --git a/src/fp.cpp b/src/fp.cpp
index 490699e..ed6601d 100644
--- a/src/fp.cpp
+++ b/src/fp.cpp
@@ -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
{