[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:
Herman S.
2026-03-26 16:25:22 +09:00
parent 0bd565eade
commit 3efc88abbb

View File

@@ -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>