[英]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)或位操作技巧,它允許我有效地從a
和b
計算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.