I would like to toggle a bit n times without loop.
like 1(bit) after toggling 3 times will be 0 and so on. For toggling a bit 1 time I use bit^=1 . I actually searching a bit manipulation formula to do so.
If I understand correctly, you want to toggle a bit N
times.
Now, Toggling a bin N times equals toggling N%2 times so:
b ^= (N%2);
Modulo 2 is the same as N&1
so you can also write:
b ^= (N&1);
generalised solution:
int toggle_bit_in_word(int word, int bit, int ntimes)
{
auto archetype = ntimes & 1;
auto toggler = archetype << bit;
return word ^= toggler;
}
gcc 5.3 produces this code:
toggle_bit_in_word(int, int, int):
and edx, 1
shlx edx, edx, esi
mov eax, edx
xor eax, edi
ret
for fun, let's write it the naiive way and enjoy the hilarity:
int toggle_bit_in_word_naiive(int word, int bit, int ntimes)
{
auto toggler = 1 << bit;
while (ntimes--)
word ^= toggler;
return word;
}
output (5.3):
toggle_bit_in_word_naiive(int, int, int):
mov ecx, 1
mov eax, edi
shlx esi, ecx, esi
lea edi, [rdx-1]
test edx, edx
je .L48
lea ecx, [rdx-8]
shr ecx, 3
add ecx, 1
lea r9d, [0+rcx*8]
cmp edi, 12
jbe .L4
vmovd xmm1, esi
xor r8d, r8d
vpxor xmm0, xmm0, xmm0
vpbroadcastd ymm1, xmm1
.L5:
add r8d, 1
vpxor ymm0, ymm0, ymm1
cmp ecx, r8d
ja .L5
vpxor xmm1, xmm1, xmm1
vperm2i128 ymm2, ymm0, ymm1, 33
vpxor ymm0, ymm0, ymm2
sub edi, r9d
vperm2i128 ymm2, ymm0, ymm1, 33
vpalignr ymm2, ymm2, ymm0, 8
vpxor ymm0, ymm0, ymm2
vperm2i128 ymm1, ymm0, ymm1, 33
vpalignr ymm1, ymm1, ymm0, 4
vpxor ymm0, ymm0, ymm1
vmovd ecx, xmm0
xor eax, ecx
cmp edx, r9d
je .L47
vzeroupper
.L4:
xor eax, esi
test edi, edi
je .L48
xor eax, esi
cmp edi, 1
je .L48
xor eax, esi
cmp edi, 2
je .L48
xor eax, esi
cmp edi, 3
je .L48
xor eax, esi
cmp edi, 4
je .L48
xor eax, esi
cmp edi, 5
je .L48
xor eax, esi
cmp edi, 6
je .L48
xor eax, esi
cmp edi, 7
je .L48
xor eax, esi
cmp edi, 8
je .L48
xor eax, esi
cmp edi, 9
je .L48
xor eax, esi
cmp edi, 10
je .L48
xor eax, esi
xor esi, eax
cmp edi, 11
cmovne eax, esi
ret
.L47:
vzeroupper
.L48:
ret
8-/
of course, when an optimiser has all the information it needs, even naiive code becomes efficient:
int main(int argc, char**argv)
{
return toggle_bit_in_word_naiive(argc, 3, 3);
}
result:
main:
mov eax, edi
xor eax, 8
ret
This is impossible if you only ever manipulate bits independently.
That's because a particular bit does not know its previous two states.
You need a minimum of 2 bits if you want a cycle with a periodicity of 4.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.