#include <cassert>
#include <cstdio>
#include <cstring>
#include <cstdint>
template <int N>
int find_high_bits_in_byte_r(uint8_t x, int base_idx)
{
uint8_t high = x >> N;
uint8_t low = ((1 << N) - 1) & x;
if (high > 0)
{
return find_high_bits_in_byte_r<N / 2>(high, base_idx + N);
}
else
{
return find_high_bits_in_byte_r<N / 2>(low, base_idx);
}
}
template <>
int find_high_bits_in_byte_r<0>(uint8_t x, int base_idx)
{
return base_idx;
}
int find_high_bits_in_byte(uint8_t x)
{
return find_high_bits_in_byte_r<4>(x, 0);
}
template <int N>
bool is_greater_than_zero(uint8_t data[N])
{
uint8_t zerofill[N] = { 0 };
auto retval = std::memcmp(data, zerofill, N);
return (retval != 0);
}
template <int N>
int find_high_bit_r(uint8_t data[N], int base_idx)
{
union container_t {
uint8_t data[N];
struct
{
uint8_t low[N / 2];
uint8_t high[N / 2];
};
} c;
std::memcpy(c.data, data, N);
if (is_greater_than_zero<N / 2>(c.high))
{
return find_high_bit_r<N / 2>(c.high, base_idx + N / 2);
}
else
{
return find_high_bit_r<N / 2>(c.low, base_idx);
}
}
template <>
int find_high_bit_r<1>(uint8_t data[1], int base_idx)
{
auto bit_idx = find_high_bits_in_byte(data[0]);
return bit_idx + base_idx * 8;
}
template <typename T>
int find_high_bit(T x)
{
if (x == 0)
{
return -1;
}
union container_t {
T val;
uint8_t data[sizeof(T)];
};
container_t c;
c.val = x;
return find_high_bit_r<sizeof(T)>(c.data, 0);
}
int main()
{
for (int i = 0; i < 8; i++)
{
assert(i == find_high_bits_in_byte(1 << i));
}
for (int i = 0; i < 32; i++)
{
assert(i == find_high_bit<uint32_t>(1 << i));
}
assert(3 == find_high_bit<uint32_t>(0b1011));
assert(27 == find_high_bit<uint32_t>(0b00001000'00000100'00000010'00000001));
return 0;
}
I2luY2x1ZGUgPGNhc3NlcnQ+CiNpbmNsdWRlIDxjc3RkaW8+CiNpbmNsdWRlIDxjc3RyaW5nPgojaW5jbHVkZSA8Y3N0ZGludD4KCnRlbXBsYXRlIDxpbnQgTj4KaW50IGZpbmRfaGlnaF9iaXRzX2luX2J5dGVfcih1aW50OF90IHgsIGludCBiYXNlX2lkeCkKewogICAgdWludDhfdCBoaWdoID0geCA+PiBOOwogICAgdWludDhfdCBsb3cgPSAoKDEgPDwgTikgLSAxKSAmIHg7CiAgICBpZiAoaGlnaCA+IDApCiAgICB7CiAgICAgICAgcmV0dXJuIGZpbmRfaGlnaF9iaXRzX2luX2J5dGVfcjxOIC8gMj4oaGlnaCwgYmFzZV9pZHggKyBOKTsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICByZXR1cm4gZmluZF9oaWdoX2JpdHNfaW5fYnl0ZV9yPE4gLyAyPihsb3csIGJhc2VfaWR4KTsKICAgIH0KfQoKdGVtcGxhdGUgPD4KaW50IGZpbmRfaGlnaF9iaXRzX2luX2J5dGVfcjwwPih1aW50OF90IHgsIGludCBiYXNlX2lkeCkKewogICAgcmV0dXJuIGJhc2VfaWR4Owp9CgppbnQgZmluZF9oaWdoX2JpdHNfaW5fYnl0ZSh1aW50OF90IHgpCnsKICAgIHJldHVybiBmaW5kX2hpZ2hfYml0c19pbl9ieXRlX3I8ND4oeCwgMCk7Cn0KCnRlbXBsYXRlIDxpbnQgTj4KYm9vbCBpc19ncmVhdGVyX3RoYW5femVybyh1aW50OF90IGRhdGFbTl0pCnsKICAgIHVpbnQ4X3QgemVyb2ZpbGxbTl0gPSB7IDAgfTsKICAgIGF1dG8gcmV0dmFsID0gc3RkOjptZW1jbXAoZGF0YSwgemVyb2ZpbGwsIE4pOwogICAgcmV0dXJuIChyZXR2YWwgIT0gMCk7Cn0KCnRlbXBsYXRlIDxpbnQgTj4KaW50IGZpbmRfaGlnaF9iaXRfcih1aW50OF90IGRhdGFbTl0sIGludCBiYXNlX2lkeCkKewogICAgdW5pb24gY29udGFpbmVyX3QgewogICAgICAgIHVpbnQ4X3QgZGF0YVtOXTsKICAgICAgICBzdHJ1Y3QKICAgICAgICB7CiAgICAgICAgICAgIHVpbnQ4X3QgbG93W04gLyAyXTsKICAgICAgICAgICAgdWludDhfdCBoaWdoW04gLyAyXTsKICAgICAgICB9OwogICAgfSBjOwogICAgc3RkOjptZW1jcHkoYy5kYXRhLCBkYXRhLCBOKTsKCiAgICBpZiAoaXNfZ3JlYXRlcl90aGFuX3plcm88TiAvIDI+KGMuaGlnaCkpCiAgICB7CiAgICAgICAgcmV0dXJuIGZpbmRfaGlnaF9iaXRfcjxOIC8gMj4oYy5oaWdoLCBiYXNlX2lkeCArIE4gLyAyKTsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICByZXR1cm4gZmluZF9oaWdoX2JpdF9yPE4gLyAyPihjLmxvdywgYmFzZV9pZHgpOwogICAgfQp9Cgp0ZW1wbGF0ZSA8PgppbnQgZmluZF9oaWdoX2JpdF9yPDE+KHVpbnQ4X3QgZGF0YVsxXSwgaW50IGJhc2VfaWR4KQp7CiAgICBhdXRvIGJpdF9pZHggPSBmaW5kX2hpZ2hfYml0c19pbl9ieXRlKGRhdGFbMF0pOwogICAgcmV0dXJuIGJpdF9pZHggKyBiYXNlX2lkeCAqIDg7Cn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBUPgppbnQgZmluZF9oaWdoX2JpdChUIHgpCnsKICAgIGlmICh4ID09IDApCiAgICB7CiAgICAgICAgcmV0dXJuIC0xOwogICAgfQoKICAgIHVuaW9uIGNvbnRhaW5lcl90IHsKICAgICAgICBUIHZhbDsKICAgICAgICB1aW50OF90IGRhdGFbc2l6ZW9mKFQpXTsKICAgIH07CiAgICBjb250YWluZXJfdCBjOwogICAgYy52YWwgPSB4OwogICAgcmV0dXJuIGZpbmRfaGlnaF9iaXRfcjxzaXplb2YoVCk+KGMuZGF0YSwgMCk7Cn0KCmludCBtYWluKCkKewogICAgZm9yIChpbnQgaSA9IDA7IGkgPCA4OyBpKyspCiAgICB7CiAgICAgICAgYXNzZXJ0KGkgPT0gZmluZF9oaWdoX2JpdHNfaW5fYnl0ZSgxIDw8IGkpKTsKICAgIH0KCiAgICBmb3IgKGludCBpID0gMDsgaSA8IDMyOyBpKyspCiAgICB7CiAgICAgICAgYXNzZXJ0KGkgPT0gZmluZF9oaWdoX2JpdDx1aW50MzJfdD4oMSA8PCBpKSk7CiAgICB9CgogICAgYXNzZXJ0KDMgPT0gZmluZF9oaWdoX2JpdDx1aW50MzJfdD4oMGIxMDExKSk7CiAgICBhc3NlcnQoMjcgPT0gZmluZF9oaWdoX2JpdDx1aW50MzJfdD4oMGIwMDAwMTAwMCcwMDAwMDEwMCcwMDAwMDAxMCcwMDAwMDAwMSkpOwoKICAgIHJldHVybiAwOwp9Cg==