- A Bitmaske
a
(sagen wir,std::uint64_t
), die mindestens einen Satz (1
) Bit enthält. Eine Selektor-Bitmaskeb
, die eine Teilmenge vona
ist (d.
Ich möchte a
Spannweiten von zusammenhängenden 1-Bits wählen, die in b
mit einem Bit überlappen:
a = 0b1111001110001100;
b = 0b0000001010001000;
//c=0b0000001110001100
// XXXX YYY ZZ
Die XXXX Gruppe 0 in c
weil b & XXXX
falsch ist. Die ZZ-Gruppe wird kopiert, weil b
eines der Z-Bits gesetzt hat. Die YYY-Gruppe wird aus dem gleichen Grund auch in c
eingestellt. Beachten Sie, dass b
mehrere Set-Bits in einer einzelnen Gruppe in a
haben kann.
So wird für jede zusammenhängende Gruppe von 1
s in a
, setzen alle diese Bits in c
wenn b
ein 1
in jedem dieser Positionen hat. Ein komplexeres Beispiel:
std::uint64_t a = 0b1101110110101;
std::uint64_t b = 0b0001010010001;
// desired c == 0b0001110110001
// contiguous groups ^^^ ^^ ^that overlap with a 1 in b
assert(a & b == b); // b is a subset of a
std::uint64_t c = some_magic_operation(a, b);
assert(c == 0b0001110110001);
Gibt es irgendwelche Bit-Logikanweisungen/intrinsics (MMX, SSE, AVX, BMI1/BMI2) oder Bit-Manipulations Tricks, die mir c
von a
und b
effizient berechnen können? (d. h. ohne Schleifen)?
ZUSÄTZLICH:
Mit Hinweis von Denis' Antwort, die ich nur Loop-basierte Algorithmus vorstellen kann:
std::uint64_t a = 0b0110111001001101;
std::uint64_t b = 0b0100101000001101;
assert(a & b == b); // subset
std::cout << std::bitset<16>(a) << std::endl;
std::cout << std::bitset<16>(b) << std::endl;
std::uint64_t x = (a + b) & ~a;
std::uint64_t c = 0;
while ((x = (a & (x >> 1)))) { // length of longest 1-series times
c |= x;
}
std::cout << std::bitset<16>(c) << std::endl;
bedeutet "ein Segment" umfassen Segmente der Länge 1? –
@ M.M Ja, 1-Segment ist nur eine nicht-Null-Sequenz von 1-s. – Orient
Ich brauchte ungefähr 10 Minuten, um deine Beschreibung zu entschlüsseln, also machte ich eine Bearbeitung, um sie für zukünftige Leser zu klären. Ich nehme an, Sie haben Intels BMI1/BMI2-Erweiterungen aus Versehen weggelassen, nicht weil [Haswell ist zu neu] (https://en.wikipedia.org/wiki/Bit_Manipulation_Instruction_Sets#Supporting_CPUs). Sie haben AVX erwähnt, was keineswegs eine Basis ist: nicht einmal auf [Skylake Celeron/Pentium] (http://ark.intel.com/products/90732), nur i3 und höher. Danke, Intel :( –