[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
|
#else
|
||||||
inline bool bit_scan_forward(uint32_t v, uint32_t* out_first_set_index) {
|
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;
|
*out_first_set_index = i - 1;
|
||||||
return i != 0;
|
return i != 0;
|
||||||
}
|
}
|
||||||
@@ -315,11 +315,19 @@ inline bool bit_scan_forward(int64_t v, uint32_t* out_first_set_index) {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T log2_floor(T v) {
|
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>
|
template <typename T>
|
||||||
inline T log2_ceil(T v) {
|
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>
|
template <typename T>
|
||||||
|
|||||||
Reference in New Issue
Block a user