[Base] Fix math.h portability: use __builtin_ffs and fix lzcnt narrowing
ffs() can collide with POSIX macro definitions on some platforms; __builtin_ffs is the portable GCC/Clang intrinsic. log2_floor/log2_ceil passed template types directly to lzcnt which has only uint32_t and uint64_t overloads, causing implicit narrowing on smaller types.
This commit is contained in:
@@ -296,7 +296,7 @@ inline bool bit_scan_forward(uint64_t v, uint32_t* out_first_set_index) {
|
||||
}
|
||||
#else
|
||||
inline bool bit_scan_forward(uint32_t v, uint32_t* out_first_set_index) {
|
||||
int i = ffs(v);
|
||||
int i = __builtin_ffs(v);
|
||||
*out_first_set_index = i - 1;
|
||||
return i != 0;
|
||||
}
|
||||
@@ -315,11 +315,19 @@ inline bool bit_scan_forward(int64_t v, uint32_t* out_first_set_index) {
|
||||
|
||||
template <typename T>
|
||||
inline T log2_floor(T v) {
|
||||
return sizeof(T) * 8 - 1 - lzcnt(v);
|
||||
if constexpr (sizeof(T) <= sizeof(uint32_t)) {
|
||||
return sizeof(T) * 8 - 1 - lzcnt(static_cast<uint32_t>(v));
|
||||
} else {
|
||||
return sizeof(T) * 8 - 1 - lzcnt(static_cast<uint64_t>(v));
|
||||
}
|
||||
}
|
||||
template <typename T>
|
||||
inline T log2_ceil(T v) {
|
||||
return sizeof(T) * 8 - lzcnt(v - 1);
|
||||
if constexpr (sizeof(T) <= sizeof(uint32_t)) {
|
||||
return sizeof(T) * 8 - lzcnt(static_cast<uint32_t>(v - 1));
|
||||
} else {
|
||||
return sizeof(T) * 8 - lzcnt(static_cast<uint64_t>(v - 1));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
||||
Reference in New Issue
Block a user