diff --git a/src/fp.cpp b/src/fp.cpp index eb8a7de..3a70db5 100644 --- a/src/fp.cpp +++ b/src/fp.cpp @@ -3,6 +3,10 @@ #include #include #include +#if defined(__EMSCRIPTEN__) && MCL_SIZEOF_UNIT == 4 +#define FOR_WASM +#include "low_funct.hpp" +#endif #if defined(MCL_STATIC_CODE) || defined(MCL_USE_XBYAK) || (defined(MCL_USE_LLVM) && (CYBOZU_HOST == CYBOZU_HOST_INTEL)) @@ -268,6 +272,20 @@ void setOp2(Op& op) } else { op.fp_add = Add::f; op.fp_sub = Sub::f; +#ifdef FOR_WASM + switch (N) { + case 8: + op.fp_add = mcl::addModT<8>; + op.fp_sub = mcl::subModT<8>; + break; + case 12: + op.fp_add = mcl::addModT<12>; + op.fp_sub = mcl::subModT<12>; + break; + default: + break; + } +#endif } if (op.isMont) { if (op.isFullBit) { diff --git a/src/low_funct.hpp b/src/low_funct.hpp new file mode 100644 index 0000000..a9751dd --- /dev/null +++ b/src/low_funct.hpp @@ -0,0 +1,67 @@ +#pragma once +/** + @file + @author MITSUNARI Shigeo(@herumi) + @license modified new BSD license + http://opensource.org/licenses/BSD-3-Clause +*/ +#include +#include + +// for 32bit not full version + +namespace mcl { + +template +void copyT(uint32_t *y, const uint32_t *x) +{ + for (size_t i = 0; i < N; i++) { + y[i] = x[i]; + } +} + +template +void addT(uint32_t *z, const uint32_t *x, const uint32_t *y) +{ + bool c = false; + for (size_t i = 0; i < N; i++) { + uint64_t v = uint64_t(x[i]) + y[i] + c; + z[i] = uint32_t(v); + c = (v >> 32) != 0; + } +} + +template +bool subT(uint32_t *z, const uint32_t *x, const uint32_t *y) +{ + bool c = false; + for (size_t i = 0; i < N; i++) { + uint64_t v = uint64_t(x[i]) - y[i] - c; + z[i] = uint32_t(v); + c = (v >> 32) != 0; + } + return c; +} + +template +void addModT(uint32_t *z, const uint32_t *x, const uint32_t *y, const uint32_t *p) +{ + uint32_t t[N]; + addT(z, x, y); + bool c = subT(t, z, p); + if (!c) { + copyT(z, t); + } +} + +template +void subModT(uint32_t *z, const uint32_t *x, const uint32_t *y, const uint32_t *p) +{ + bool c = subT(z, x, y); + if (c) { + addT(z, z, p); + } +} + +} // mcl +