leading_zeroes(): 0 is not a valid input

This commit is contained in:
Joao Paulo Magalhaes 2020-11-19 22:55:48 +00:00
parent 216d191384
commit 8a04a06a88
2 changed files with 14 additions and 17 deletions

View File

@ -3,6 +3,7 @@
#include <cfloat> #include <cfloat>
#include <cstdint> #include <cstdint>
#include <cassert>
#if defined(_MSC_VER) && !defined(__clang__) #if defined(_MSC_VER) && !defined(__clang__)
#define FASTFLOAT_VISUAL_STUDIO 1 #define FASTFLOAT_VISUAL_STUDIO 1
@ -89,26 +90,23 @@ struct value128 {
/* result might be undefined when input_num is zero */ /* result might be undefined when input_num is zero */
fastfloat_really_inline int leading_zeroes(uint64_t input_num) { fastfloat_really_inline int leading_zeroes(uint64_t input_num) {
assert(input_num > 0);
#ifdef FASTFLOAT_VISUAL_STUDIO #ifdef FASTFLOAT_VISUAL_STUDIO
#if defined(_M_X64) || defined(_M_ARM64) #if defined(_M_X64) || defined(_M_ARM64)
unsigned long leading_zero = 0; unsigned long leading_zero = 0;
// Search the mask data from most significant bit (MSB) // Search the mask data from most significant bit (MSB)
// to least significant bit (LSB) for a set bit (1). // to least significant bit (LSB) for a set bit (1).
if (_BitScanReverse64(&leading_zero, input_num)) return (int)(_BitScanReverse64(&leading_zero, input_num) - leading_zero);
return (int)(63 - leading_zero); #else
else int n = 0;
return 64; if(input_num & uint64_t(0xffffffff00000000)) input_num >>= 32, n |= 32;
#else if(input_num & uint64_t( 0xffff0000)) input_num >>= 16, n |= 16;
if(!input_num) return 64; if(input_num & uint64_t( 0xff00)) input_num >>= 8, n |= 8;
int n = 0; if(input_num & uint64_t( 0xf0)) input_num >>= 4, n |= 4;
if(input_num & uint64_t(0xffffffff00000000)) input_num >>= 32, n |= 32; if(input_num & uint64_t( 0xc)) input_num >>= 2, n |= 2;
if(input_num & uint64_t( 0xffff0000)) input_num >>= 16, n |= 16; if(input_num & uint64_t( 0x2)) input_num >>= 1, n |= 1;
if(input_num & uint64_t( 0xff00)) input_num >>= 8, n |= 8; return 63 - n;
if(input_num & uint64_t( 0xf0)) input_num >>= 4, n |= 4; #endif
if(input_num & uint64_t( 0xc)) input_num >>= 2, n |= 2;
if(input_num & uint64_t( 0x2)) input_num >>= 1, n |= 1;
return 63 - n;
#endif
#else #else
return __builtin_clzll(input_num); return __builtin_clzll(input_num);
#endif #endif

View File

@ -7,7 +7,6 @@
TEST_CASE("leading_zeroes") { TEST_CASE("leading_zeroes") {
constexpr const uint64_t bit = 1; constexpr const uint64_t bit = 1;
CHECK(fast_float::leading_zeroes(0) == 64);
CHECK(fast_float::leading_zeroes(bit << 0) == 63); CHECK(fast_float::leading_zeroes(bit << 0) == 63);
CHECK(fast_float::leading_zeroes(bit << 1) == 62); CHECK(fast_float::leading_zeroes(bit << 1) == 62);
CHECK(fast_float::leading_zeroes(bit << 2) == 61); CHECK(fast_float::leading_zeroes(bit << 2) == 61);