aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorRaulshc <[email protected]>2019-08-18 19:12:38 +0200
committerRaulshc <[email protected]>2019-08-18 19:12:38 +0200
commit550f1dce1fa00bc084e6dacbb40fdafb6867a015 (patch)
tree75b8af0e8e993540a8bfb32379a621f2efb174f4 /common
parentff66061091baedaa7d677ede65aba592c8f8aa5d (diff)
Move double2int function
Move inline double2int function to alnumeric.h from pshifter.cpp
Diffstat (limited to 'common')
-rw-r--r--common/alnumeric.h35
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