簡體   English   中英

選擇位掩碼中的設置位的跨度,該位掩碼與選擇器位圖中的1位重疊

[英]Select spans of set bits in a bitmask that overlap with a 1-bit in a selector bitmap

鑒於:

  • 位掩碼a (例如, std::uint64_t ),其包含至少一個set( 1 )位。
  • 選擇器位掩碼b其中的一個子集a (即a & b == b ),和具有至少一個比特組。

我想選擇在連續的1比特的跨度a ,其與在比特重疊b

a = 0b1111001110001100;
b = 0b0000001010001000;
//c=0b0000001110001100
//    XXXX  YYY   ZZ

XXXX組在c為0,因為b & XXXX為false。 復制ZZ組是因為b設置了Z位之一。 出於同樣的原因,YYY組也設置在c中。 注意, b可以在一個單一的基團有多個組比特a

因此,對於每一個連續的組的1以s a ,設置所有那些比特的c如果b具有1在任何這些位置的。 一個更復雜的例子:

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);

是否有任何位邏輯指令/內在函數(MMX,SSE,AVX,BMI1 / BMI2)或位操作技巧,它允許我有效地從ab計算c (即沒有循環)?


額外:

使用Denis回答的提示我只能想象基於循環的算法:

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;

uint64_t情況下,你可以這樣做:

我們設置a = 0b11011101101 至少有一個0位很重要。 位掩碼有4個獨立區域,填充1位。 如果你做c=a+(a&b) ,那么如果設置了該區域中至少有一位b ,則每個填充1的區域將溢出。 那么你可以檢查一下,哪個區域溢出了。 例如,如果你想要a的2-nd和3-rd區域中a 1位,你可以這樣做:

    assert(c & 0b00100010000);
    //              ^^^ ^^ this segments overflows

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM