diff --git a/BAN/include/BAN/Math.h b/BAN/include/BAN/Math.h index 622628a9..784a17ed 100644 --- a/BAN/include/BAN/Math.h +++ b/BAN/include/BAN/Math.h @@ -82,6 +82,37 @@ namespace BAN::Math return x + 1; } + template + requires is_same_v || is_same_v || is_same_v + inline constexpr int clz(T x) + { + if constexpr (is_same_v) + return __builtin_clz(x); + if constexpr (is_same_v) + return __builtin_clzl(x); + return __builtin_clzll(x); + } + + template requires(sizeof(T) <= sizeof(unsigned long long)) + inline constexpr int ctz(T x) + { + if constexpr (sizeof(T) <= sizeof(unsigned int)) + return __builtin_ctz(x); + if constexpr (sizeof(T) <= sizeof(unsigned long)) + return __builtin_ctzl(x); + return __builtin_ctzll(x); + } + + template requires(sizeof(T) <= sizeof(unsigned long long)) + inline constexpr int popcount(T x) + { + if constexpr (sizeof(T) <= sizeof(unsigned int)) + return __builtin_popcount(x); + if constexpr (sizeof(T) <= sizeof(unsigned long)) + return __builtin_popcountl(x); + return __builtin_popcountll(x); + } + template __attribute__((always_inline)) inline constexpr bool will_multiplication_overflow(T a, T b) @@ -102,11 +133,7 @@ namespace BAN::Math requires is_same_v || is_same_v || is_same_v inline constexpr T ilog2(T x) { - if constexpr(is_same_v) - return sizeof(T) * 8 - __builtin_clz(x) - 1; - if constexpr(is_same_v) - return sizeof(T) * 8 - __builtin_clzl(x) - 1; - return sizeof(T) * 8 - __builtin_clzll(x) - 1; + return sizeof(T) * 8 - clz(x) - 1; } // This is ugly but my clangd does not like including