Skip to content

Commit 5ccd6ab

Browse files
authored
Merge pull request #28 from Exerg/bugfix/clz_portability
Fixing clz portability
2 parents 8983567 + 9731721 commit 5ccd6ab

File tree

1 file changed

+32
-1
lines changed

1 file changed

+32
-1
lines changed

include/wfc/utility/math.hpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,19 @@
44
#include <limits>
55
#include <type_traits>
66

7+
#ifndef __has_builtin
8+
#define WFC__has_builtin(x) 0
9+
#else
10+
#define WFC__has_builtin(x) __has_builtin(x)
11+
#endif
12+
713
namespace wfc
814
{
915
namespace details
1016
{
17+
#if WFC__has_builtin(__builtin_clz) && WFC__has_builtin(__builtin_clzl) && WFC__has_builtin(__builtin_clzll)
1118
template <typename T>
12-
T clz(T x) // FIXME
19+
T clz(T x)
1320
{
1421
assert(x != 0); // clz is undefined for 0
1522

@@ -30,6 +37,27 @@ namespace wfc
3037
static_assert(!std::is_same_v<T, T>);
3138
}
3239
}
40+
#else
41+
template <typename T>
42+
T clz(T x)
43+
{
44+
static_assert(std::is_unsigned_v<T>, "T should be unsigned");
45+
46+
T mask = T(1) << T(std::numeric_limits<T>::digits - 1);
47+
48+
T result = 0;
49+
50+
for (std::size_t i = 0; i < std::numeric_limits<T>::digits; ++i) {
51+
if ((mask & x) != 0) {
52+
return result;
53+
}
54+
++result;
55+
mask >>= 1;
56+
}
57+
58+
return result;
59+
}
60+
#endif
3361
} // namespace details
3462

3563
template <typename T>
@@ -53,4 +81,7 @@ namespace wfc
5381
return nbr && !(nbr & (nbr - 1));
5482
}
5583
} // namespace wfc
84+
85+
#undef WFC__has_builtin
86+
5687
#endif // WFC_MATH_HPP

0 commit comments

Comments
 (0)