Код: Выделить всё
// C++ version
bool is_pow_4(unsigned a) {
return (std::popcount(a) == 1) && (std::countr_zero(a) % 2 == 0);
}
Код: Выделить всё
// C version
int is_pow_4(unsigned a) {
return (__builtin_popcount(a) == 1) && (__builtin_ctz(a) % 2 == 0);
}
Я ожидал код без ветвей, однако вижу два перехода и инструкция повторения. Насколько я помню, представитель — это, по сути, цикл, но на уровне сборки. Кажется, что std::countr_zero/
Код: Выделить всё
__builtin_ctzВывод C++:
Код: Выделить всё
is_pow_4(unsigned int):
lea edx, [rdi-1]
mov ecx, edi
xor eax, eax
xor ecx, edx
cmp edx, ecx
jb .L7
.L1:
ret
.L7:
mov eax, 1
test edi, edi
je .L1
xor eax, eax
rep bsf eax, edi
not eax
and eax, 1
ret
Я понимаю, что цикл ограничен шириной целого числа (32), поэтому я думаю, что сложность код — O(1), но я все равно был удивлен, обнаружив цикл.
Правильно ли я понимаю? Является ли этот код циклом на x86? Это потому, что, хотя есть инструкция popcount x86, в инструкции x86 нет подсчета начальных/конечных нулей?
Подробнее здесь: https://stackoverflow.com/questions/781 ... mbly-using
Мобильная версия