perf(math): scan least significand bit with MSVC x64 intrinsic
This commit is contained in:
@@ -7,6 +7,9 @@
|
||||
#include <cstring>
|
||||
#include <initializer_list>
|
||||
#include <limits>
|
||||
#if defined(_MSC_VER) && defined(_M_X64)
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
#if defined(_M_X64) || defined(__SSE2__)
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
@@ -114,8 +117,14 @@ inline int LowestBitExponent(double value) {
|
||||
? -1074
|
||||
: static_cast<int>(encoded_exponent) - 1075;
|
||||
if (encoded_exponent != 0U) significand |= 1ULL << 52U;
|
||||
#if defined(_MSC_VER) && defined(_M_X64)
|
||||
// The finite, nonzero precondition makes the significand nonzero.
|
||||
unsigned long trailing = 0;
|
||||
_BitScanForward64(&trailing, significand);
|
||||
return exponent + static_cast<int>(trailing);
|
||||
#else
|
||||
int trailing = 0;
|
||||
// Strip large zero groups first without vendor/compiler intrinsics.
|
||||
// Preserve the portable search outside the supported MSVC x64 path.
|
||||
for (const int shift : {32, 16, 8, 4, 2, 1}) {
|
||||
const auto mask = (1ULL << shift) - 1U;
|
||||
if ((significand & mask) == 0U) {
|
||||
@@ -124,6 +133,7 @@ inline int LowestBitExponent(double value) {
|
||||
}
|
||||
}
|
||||
return exponent + trailing;
|
||||
#endif
|
||||
}
|
||||
/// @brief Gives a product and its FMA residual when the dyadic tail fits.
|
||||
/// @note Rejects underflow-risk exact tails, even if the rounded high is finite.
|
||||
|
||||
Reference in New Issue
Block a user