Skip to content

Instantly share code, notes, and snippets.

@foonathan
Last active April 14, 2016 09:46
Show Gist options
  • Save foonathan/101c497dd3800165ebce to your computer and use it in GitHub Desktop.
Save foonathan/101c497dd3800165ebce to your computer and use it in GitHub Desktop.
A clz() implementation wrapping __builtin_clz() - see blog post http://foonathan.github.io/blog/2016/02/11/implementation-challenge-2.html
#include <climits>
#include <cstdint>
#include <type_traits>
struct clzll_tag {};
struct clzl_tag : clzll_tag {};
struct clz_tag : clzl_tag {};
template <typename T, typename = typename std::enable_if<sizeof(T) <= sizeof(unsigned int)>::type>
unsigned clz_impl(clz_tag, T x)
{
return __builtin_clz(x) - (sizeof(unsigned int) * CHAR_BIT - sizeof(T) * CHAR_BIT);
}
template <typename T, typename = typename std::enable_if<sizeof(T) <= sizeof(unsigned long)>::type>
unsigned clz_impl(clzl_tag, T x)
{
return __builtin_clzl(x) - (sizeof(unsigned long) * CHAR_BIT - sizeof(T) * CHAR_BIT);
}
template <typename T, typename = typename std::enable_if<sizeof(T) <= sizeof(unsigned long long)>::type>
unsigned clz_impl(clzll_tag, T x)
{
return __builtin_clzll(x) - (sizeof(unsigned long long) * CHAR_BIT - sizeof(T) * CHAR_BIT);
}
unsigned clz(std::uint8_t x)
{
return clz_impl(clz_tag{}, x);
}
unsigned clz(std::uint16_t x)
{
return clz_impl(clz_tag{}, x);
}
unsigned clz(std::uint32_t x)
{
return clz_impl(clz_tag{}, x);
}
unsigned clz(std::uint64_t x)
{
return clz_impl(clz_tag{}, x);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment