diff options
author | Raulshc <[email protected]> | 2019-08-18 19:12:38 +0200 |
---|---|---|
committer | Raulshc <[email protected]> | 2019-08-18 19:12:38 +0200 |
commit | 550f1dce1fa00bc084e6dacbb40fdafb6867a015 (patch) | |
tree | 75b8af0e8e993540a8bfb32379a621f2efb174f4 /common | |
parent | ff66061091baedaa7d677ede65aba592c8f8aa5d (diff) |
Move double2int function
Move inline double2int function to alnumeric.h from pshifter.cpp
Diffstat (limited to 'common')
-rw-r--r-- | common/alnumeric.h | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/common/alnumeric.h b/common/alnumeric.h index b51893d6..0a05f4bf 100644 --- a/common/alnumeric.h +++ b/common/alnumeric.h @@ -250,6 +250,41 @@ inline int float2int(float f) noexcept #endif } +/** Converts double-to-int using standard behavior (truncation). */ +inline int double2int(double d) noexcept +{ +#if defined(HAVE_SSE_INTRINSICS) + return _mm_cvttsd_si32(_mm_set_sd(d)); + +#elif ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) && \ + !defined(__SSE2_MATH__)) || (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP < 2) + + int sign, shift; + int64_t mant; + union { + double d; + int64_t i64; + } conv; + + conv.d = d; + sign = (conv.i64 >> 63) | 1; + shift = ((conv.i64 >> 52) & 0x7ff) - (1023 + 52); + + /* Over/underflow */ + if UNLIKELY(shift >= 63 || shift < -52) + return 0; + + mant = (conv.i64 & 0xfffffffffffff_i64) | 0x10000000000000_i64; + if LIKELY(shift < 0) + return (int)(mant >> -shift) * sign; + return (int)(mant << shift) * sign; + +#else + + return static_cast<int>(d); +#endif +} + /** * Rounds a float to the nearest integral value, according to the current * rounding mode. This is essentially an inlined version of rintf, although |