鉴于:
- 一个位掩码
a
(比如std::uint64_t
),它至少包含一个 set (1
) 位。 - 选择器位掩码
b
,它是a
(iea & b == b
) 的子集,并且具有至少一个位集。
我想选择与 ina
中的位重叠的连续 1 位跨度b
:
a = 0b1111001110001100;
b = 0b0000001010001000;
//c=0b0000001110001100
// XXXX YYY ZZ
XXXX 组为 0,c
因为b & XXXX
是假的。ZZ 组被复制,因为b
设置了 Z 位之一。c
出于同样的原因, 也设置了 YYY 组。请注意,b
在a
.
1
因此,对于s 中的每个连续组a
,将所有这些位设置为c
if在任何这些位置中b
有 a 。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)或位操作技巧可以让我高效c
地 进行计算?(即没有循环)?a
b
额外的:
使用丹尼斯回答中的提示,我只能想象基于循环的算法:
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;