Count leading zeros in a 128-bit integer

How can I count the number of leading zeros in a 128-bit integer ( uint128_t) effectively?

I know the GCC built-in functions:

  • __builtin_clz, __builtin_clzl,__builtin_clzll
  • __builtin_ffs, __builtin_ffsl,__builtin_ffsll

However, these functions only work with 32- and 64-bit integers.

I also found some SSE instructions:

  • __lzcnt16, __lzcnt,__lzcnt64

As you can guess, they only work with 16-, 32- and 64-bit integers.

Is there any similar effective built-in functionality for 128-bit integers?

+4
source share
3 answers
inline int clz_u128 (uint128_t u) {
  uint64_t hi = u>>64;
  uint64_t lo = u;
  int retval[3]={
    __builtin_clzll(hi),
    __builtin_clzll(lo)+64,
    128
  };
  int idx = !hi + ((!lo)&(!hi));
  return retval[idx];
}

. , , , , , .

__builtin_clzll 0: , undefined, undefined?

+5

"" , 64- , .

, :

/* inline */ int clz_u128 (uint128_t u)
{
    unsigned long long hi, lo; /* (or uint64_t) */
    int b = 128;

    if ((hi = u >> 64) != 0) {
        b = __builtin_clzll(hi);
    }
    else if ((lo = u & ~0ULL) != 0) {
        b = __builtin_clzll(lo) + 64;
    }

    return b;
}

, gcc __builtin_clzll bsrq - , .. - xor, (msb ^ 63) sub, (63 - msb), . gcc lzcnt -march= ().


: , "" , HI uint64_t .

+4

Yakk , gcc 128 . , x86-64, Intel Haswell , :

#include <immintrin.h>
#include <stdint.h>
// tested with compiler options: gcc -O3 -Wall -m64  -mlzcnt

inline int lzcnt_u128 (unsigned __int128 u) {
  uint64_t hi = u>>64;
  uint64_t lo = u;
  lo = (hi == 0) ? lo : -1ULL;
  return _lzcnt_u64(hi) + _lzcnt_u64(lo);
}

_lzcnt_u64 (gcc 5.4) lzcnt, ( 64), gcc __builtin_clzll(). cmove.

+3

All Articles