diff --git a/README.md b/README.md index c672479..e3d9b4c 100644 --- a/README.md +++ b/README.md @@ -85,8 +85,6 @@ fastdiv_s32(a,M,d);// is a / d for all 32-bit a, d must not be one of -1, 1, or In C++, it is much the same except that every function is in the `fastmod` namespace so you need to prefix the calls with `fastmod::` (e.g., `fastmod::is_divisible`). -The signed operations (`fastmod_s32` and `fastdiv_s32`) are currently unsupported under Visual Studio. - ## Go version * There is a Go version of this library: https://github.com/bmkessler/fastdiv diff --git a/include/fastmod.h b/include/fastmod.h index bcfb89f..6689e9f 100644 --- a/include/fastmod.h +++ b/include/fastmod.h @@ -39,9 +39,14 @@ namespace fastmod { FASTMOD_API uint64_t mul128_u32(uint64_t lowbits, uint32_t d) { return __umulh(lowbits, d); } +FASTMOD_API uint64_t mul128_from_u64(uint64_t lowbits, uint64_t d) { + return __umulh(lowbits, d); +} FASTMOD_API uint64_t mul128_s32(uint64_t lowbits, int32_t d) { - // not equivalent to ((__int128_t)lowbits * d) >> 64 - return __mulh(lowbits, d); + if(d < 0) { + return mul128_from_u64(lowbits, (int64_t)d) - lowbits; + } + return mul128_u32(lowbits, d); } @@ -50,9 +55,14 @@ FASTMOD_API uint64_t mul128_s32(uint64_t lowbits, int32_t d) { FASTMOD_API uint64_t mul128_u32(uint64_t lowbits, uint32_t d) { return ((__uint128_t)lowbits * d) >> 64; } - +FASTMOD_API uint64_t mul128_from_u64(uint64_t lowbits, uint64_t d) { + return ((__uint128_t)lowbits * d) >> 64; +} FASTMOD_API uint64_t mul128_s32(uint64_t lowbits, int32_t d) { - return ((__int128_t)lowbits * d) >> 64; + if(d < 0) { + return mul128_from_u64(lowbits, (int64_t)d) - lowbits; + } + return mul128_u32(lowbits, d); } // This is for the 64-bit functions. @@ -124,11 +134,8 @@ FASTMOD_API int32_t fastmod_s32(int32_t a, uint64_t M, int32_t positive_d) { return highbits - ((positive_d - 1) & (a >> 31)); } -#ifndef _MSC_VER - // fastdiv computes (a / d) given a precomputed M, assumes that d must not // be one of -1, 1, or -2147483648 -// Unsupported under VS, todo: fix. FASTMOD_API int32_t fastdiv_s32(int32_t a, uint64_t M, int32_t d) { uint64_t highbits = mul128_s32(M, a); highbits += (a < 0 ? 1 : 0); @@ -137,6 +144,8 @@ FASTMOD_API int32_t fastdiv_s32(int32_t a, uint64_t M, int32_t d) { return (int32_t)(highbits); } +#ifndef _MSC_VER + // What follows is the 64-bit functions. // They are currently not supported on Visual Studio // due to the lack of a mul128_u64 function.