7. ビットの長さ(1/4)
xを確保するのに必要なビットの長さ
x == 0のとき1とする
int bitLen(uint32_t x) {
if (x == 0) return 1;
for (int i = 0; i < 32; i++) {
if (x < (1u << i)) return i;
}
return 32;
}
__builtin_clzを使う
これはcount leading zeroなので32から結果を引く
この関数はx == 0のときは未定義なので別に処理する
if (x == 0) return 1;
return 32 - __builtin_clz(x);
2013/3/30 #x86opti 5 7 /24
8. ビットの長さ(2/4)
gcc 4.7とclang 3.3
// gcc // clang
test edi, edi mov eax, 1
mov eax, 1 test edi, edi
je .Z je .Z
bsr edi, edi bsr eax, edi
mov al, 32 xor eax, -32
xor edi, 31 add eax, 33
sub eax, edi
.Z: ret .Z: ret
clangの方がちょっと賢い感じだがなんか微妙
bsr(x) == 32 - __builin_clz(x)なので回りくどい
少し変えてみる
if (x == 0) return 1;
// return 32 - __builtin_clz(x);
return (__builtin_clz(x) ^ 0x1f) + 1;
2013/3/30 #x86opti 5 8 /24
9. ビットの長さ(3/4)
なぜかgccだけよくなった
xorとaddがキャンセルした
// gcc // clang
test edi, edi mov eax, 1
mov eax, 1 test edi, edi
je .Zero je .Zero
bsr edi, edi bsr eax, edi
add eax, 1 xor eax, -32
add eax, 33
.Zero: ret .Zero: ret
VCでは_BitScanReverse(&ret, x)を使う
これはx == 0のときfalseを返す
unsigned long ret;
if (_BitScanReverse(&ret, x)) return ret + 1;
return 1;
2013/3/30 #x86opti 5 9 /24