Obecnie jestem w trakcie pisania modułu wyliczającego drzewa, w którym napotkałem następujący problem:
Patrzę na zamaskowane bitsety, czyli bity, w których ustawione bity są podzbiorem maski, czyli 0000101
z maską 1010101
. Chcę tylko zwiększyć zestaw bitów, ale tylko w odniesieniu do bitów maskowanych. W tym przykładzie wynikiem będzie 0010000
. Aby było trochę jaśniej, wyodrębnij tylko zamaskowane bity, tj. 0011
Zwiększ je 0100
i ponownie rozprowadź na bity maski, dając 0010000
.
Czy ktoś widzi skuteczny sposób, aby to zrobić, oprócz wykonania operacji ręcznie przy użyciu kombinacji bitów skanów i masek przedrostków?
c++
c
bit-manipulation
intrinsics
Tobias Ribizel
źródło
źródło
x
. Prawdopodobniex = (x & ~mask) | (((x | ~mask) + 1) & mask);
.0101101
(np..1.1.0.
W bitach nie-maskujących i0.0.1.1
w "liczniku") czy potrzebowałyby0111000
(nowy "licznik"0.1.0.0
podczas zachowywania.1.1.0.
), czy jest po prostu0010000
akceptowalna. Ta odpowiedź (i prawdopodobnie inne, choć nie sprawdziłem) daje drugie; moja wersja powinna dawać tę pierwszą, jeśli jest to wymagane.Chociaż nie jest to intuicyjne w porównaniu z zaakceptowaną odpowiedzią, działa to tylko w 3 krokach:
x = -(x ^ mask) & mask;
Można to zweryfikować zgodnie z sugestią zch:
-(x ^ mask) = ~(x ^ mask) + 1 // assuming 2's complement = (x ^ ~mask) + 1 = (x | ~mask) + 1 // since x and ~mask have disjoint set bits
Wtedy staje się odpowiednikiem zaakceptowanej odpowiedzi.
źródło
-(x ^ mask) == (x | ~mask) + 1
ilekroć x jest podzbiorem maski, a następnie odniósł się do mojej odpowiedzi.-(x^mask) == ~((x ^ mask) - 1) == ~(x ^ mask) + 1 == (x ^ ~mask) + 1 == (x | ~mask) + 1
. Ostatnie równanie jest aktualne, ponieważ zestawy bitów są rozłączne, inne są zawsze prawdziwe (przynajmniej w uzupełnieniu do 2).Jeśli kolejność iteracji nie jest tak ważna, a operacja dekrementacji zaspokoi Twoje potrzeby, możliwe jest użycie tylko dwóch operacji:
Zacznijmy
x = mask
i uzyskaj poprzednią wartość za pomocą
x = (x - 1) & mask
x - 1
part zmienia ostatni niezerowy bit na zero i ustawia wszystkie mniej znaczące bity na 1. Następnie& mask
część pozostawia wśród nich tylko fragmenty maski.źródło