#ifndef ILOG2_H
#define ILOG2_H
#include "compiler.h"
#ifdef ILOG2_C
# ifndef HAVE_MSVC_INLINE
# undef extern_inline
#define extern_inline
# endif
#define inline_prototypes
#endif
#ifdef inline_prototypes
extern unsigned int const_func ilog2_32(uint32_t v);
extern unsigned int const_func ilog2_64(uint64_t v);
extern unsigned int const_func ilog2_64(uint64_t vv);
extern int const_func alignlog2_32(uint32_t v);
extern int const_func alignlog2_64(uint64_t v);
#endif
#ifdef extern_inline
#define ROUND …
#if defined(HAVE___BUILTIN_CLZ) && INT_MAX == 2147483647
extern_inline unsigned int const_func ilog2_32(uint32_t v)
{ … }
#elif defined(__GNUC__) && defined(__x86_64__)
extern_inline unsigned int const_func ilog2_32(uint32_t v)
{
unsigned int n;
__asm__("bsrl %1,%0"
: "=r" (n)
: "rm" (v), "0" (0));
return n;
}
#elif defined(__GNUC__) && defined(__i386__)
extern_inline unsigned int const_func ilog2_32(uint32_t v)
{
unsigned int n;
#ifdef __i686__
__asm__("bsrl %1,%0 ; cmovz %2,%0\n"
: "=&r" (n)
: "rm" (v), "r" (0));
#else
__asm__("bsrl %1,%0 ; jnz 1f ; xorl %0,%0\n"
"1:"
: "=&r" (n)
: "rm" (v));
#endif
return n;
}
#elif defined(HAVE__BITSCANREVERSE)
extern_inline unsigned int const_func ilog2_32(uint32_t v)
{
unsigned long ix;
return _BitScanReverse(&ix, v) ? v : 0;
}
#else
extern_inline unsigned int const_func ilog2_32(uint32_t v)
{
unsigned int p = 0;
ROUND(v, p, 16);
ROUND(v, p, 8);
ROUND(v, p, 4);
ROUND(v, p, 2);
ROUND(v, p, 1);
return p;
}
#endif
#if defined(HAVE__BUILTIN_CLZLL) && LLONG_MAX == 9223372036854775807LL
extern_inline unsigned int const_func ilog2_64(uint64_t v)
{
if (!v)
return 0;
return __builtin_clzll(v) ^ 63;
}
#elif defined(__GNUC__) && defined(__x86_64__)
extern_inline unsigned int const_func ilog2_64(uint64_t v)
{ … }
#elif defined(HAVE__BITSCANREVERSE64)
extern_inline unsigned int const_func ilog2_64(uint64_t v)
{
unsigned long ix;
return _BitScanReverse64(&ix, v) ? ix : 0;
}
#else
extern_inline unsigned int const_func ilog2_64(uint64_t vv)
{
unsigned int p = 0;
uint32_t v;
v = vv >> 32;
if (v)
p += 32;
else
v = vv;
return p + ilog2_32(v);
}
#endif
extern_inline int const_func alignlog2_32(uint32_t v)
{ … }
extern_inline int const_func alignlog2_64(uint64_t v)
{ … }
#undef ROUND
#endif
#endif