add portable mul for 32-bit

dev
MITSUNARI Shigeo 7 years ago
parent 2b5628f243
commit 2f643448bc
  1. 50
      include/mcl/vint.hpp
  2. 19
      src/fp.cpp

@ -44,26 +44,56 @@ inline void split64(uint32_t *H, uint32_t *L, uint64_t x)
} }
/* /*
[H:L] <= a * b [H:L] <= x * y
@return L @return L
*/ */
static inline Unit mulUnit(Unit *H, Unit a, Unit b) static inline Unit mulUnit(Unit *pH, Unit x, Unit y)
{ {
#if MCL_SIZEOF_UNIT == 4 #if MCL_SIZEOF_UNIT == 4
uint64_t t = uint64_t(a) * b; uint64_t t = uint64_t(x) * y;
uint32_t L; uint32_t L;
split64(H, &L, t); split64(pH, &L, t);
return L; return L;
#else #elif MCL_VINT_MUL_PORTABLE
#if defined(_WIN64) && !defined(__INTEL_COMPILER) uint32_t a = uint32_t(x >> 32);
return _umul128(a, b, H); uint32_t b = uint32_t(x);
uint32_t c = uint32_t(y >> 32);
uint32_t d = uint32_t(y);
uint64_t ad = uint64_t(d) * a;
uint64_t bd = uint64_t(d) * b;
uint64_t L = uint32_t(bd);
ad += bd >> 32; // [ad:L]
uint64_t ac = uint64_t(c) * a;
uint64_t bc = uint64_t(c) * b;
uint64_t H = uint32_t(bc);
ac += bc >> 32; // [ac:H]
/*
adL
acH
*/
uint64_t t = (ac << 32) | H;
ac >>= 32;
H = t + ad;
if (H < t) {
ac++;
}
/*
ac:H:L
*/
L |= H << 32;
H = (ac << 32) | uint32_t(H >> 32);
*pH = H;
return L;
#elif defined(_WIN64) && !defined(__INTEL_COMPILER)
return _umul128(x, y, pH);
#else #else
typedef __attribute__((mode(TI))) unsigned int uint128; typedef __attribute__((mode(TI))) unsigned int uint128;
uint128 t = uint128(a) * b; uint128 t = uint128(x) * y;
*H = uint64_t(t >> 64); *pH = uint64_t(t >> 64);
return uint64_t(t); return uint64_t(t);
#endif #endif
#endif
} }
/* /*

@ -438,22 +438,23 @@ void Op::init(const std::string& mstr, size_t maxBitSize, Mode mode, size_t mclM
Xbyak > llvm_mont > llvm > gmp_mont > gmp Xbyak > llvm_mont > llvm > gmp_mont > gmp
*/ */
#ifdef MCL_USE_XBYAK #ifdef MCL_USE_XBYAK
if (mode == fp::FP_AUTO) mode = fp::FP_XBYAK; if (mode == FP_AUTO) mode = FP_XBYAK;
if (mode == fp::FP_XBYAK && bitSize > 256) { if (mode == FP_XBYAK && bitSize > 256) {
mode = fp::FP_AUTO; mode = FP_AUTO;
} }
if (!fp::isEnableJIT()) { if (!isEnableJIT()) {
mode = fp::FP_AUTO; mode = FP_AUTO;
} }
#else #else
if (mode == fp::FP_XBYAK) mode = fp::FP_AUTO; if (mode == FP_XBYAK) mode = FP_AUTO;
#endif #endif
#ifdef MCL_USE_LLVM #ifdef MCL_USE_LLVM
if (mode == fp::FP_AUTO) mode = fp::FP_LLVM_MONT; if (mode == FP_AUTO) mode = FP_LLVM_MONT;
#else #else
if (mode == fp::FP_LLVM || mode == fp::FP_LLVM_MONT) mode = fp::FP_AUTO; if (mode == FP_LLVM || mode == FP_LLVM_MONT) mode = FP_AUTO;
#endif #endif
isMont = mode == fp::FP_GMP_MONT || mode == fp::FP_LLVM_MONT || mode == fp::FP_XBYAK; if (mode == FP_AUTO) mode = FP_GMP_MONT;
isMont = mode == FP_GMP_MONT || mode == FP_LLVM_MONT || mode == FP_XBYAK;
#ifndef NDEBUG #ifndef NDEBUG
fprintf(stderr, "mode=%s, isMont=%d, maxBitSize=%d" fprintf(stderr, "mode=%s, isMont=%d, maxBitSize=%d"
#ifdef MCL_USE_XBYAK #ifdef MCL_USE_XBYAK

Loading…
Cancel
Save