选择位掩码中与选择器位图中的 1 位重叠的设置位范围
Posted
技术标签:
【中文标题】选择位掩码中与选择器位图中的 1 位重叠的设置位范围【英文标题】:Select spans of set bits in a bitmask that overlap with a 1-bit in a selector bitmap 【发布时间】:2016-05-19 04:31:04 【问题描述】:给定:
一个位掩码a
(比如std::uint64_t
),其中至少包含一组(1
)位。
选择器位掩码b
,它是a
(即a & b == b
)的子集,并且至少设置了一个位。
我想在a
中选择与b
中的位重叠的连续 1 位跨度:
a = 0b1111001110001100;
b = 0b0000001010001000;
//c=0b0000001110001100
// XXXX YYY ZZ
c
中的 XXXX 组为 0,因为 b & XXXX
为 false。复制 ZZ 组是因为 b
设置了 Z 位之一。出于同样的原因,YYY 组也设置在c
中。 注意b
可以在a
的一个组中拥有多个设置位。
因此,对于a
中每个连续的1
s 组,如果b
在任何这些位置有1
,则设置c
中的所有这些位。一个更复杂的例子:
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
? (即没有循环)?
补充:
使用丹尼斯回答中的提示,我只能想象基于循环的算法:
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;
【问题讨论】:
“一个段”是否包括长度为 1 的段? @M.M 是的,1-segment 只是 1-s 的非零长度序列。 我花了大约 10 分钟来解码您的描述,因此我进行了编辑以澄清未来的读者。我假设您无意中遗漏了英特尔的 BMI1/BMI2 扩展,而不是因为Haswell is too new。您确实提到了 AVX,这绝不是基线:即使在 Skylake Celeron/Pentium 上也不支持,只有 i3 和更高版本。谢谢,英特尔 :( 实际上,没有任何 BMI 指令本身显然是有用的。不过,可能pext
/ pdep
作为构建块。你绝对需要你指定格式的输出吗? Denis 的答案丢失了有关每个组有多大的信息,但每个匹配组的结果中确实有 1。
@PeterCordes 感谢您的指正。非常感谢。
【参考方案1】:
如果是uint64_t
,你可以这样做:
让我们设置a = 0b11011101101
。至少有一个 0 位很重要。位掩码有 4 个单独的区域,用 1 位填充。如果你做c=a+(a&b)
,那么如果在该区域中至少设置了一位b
,则每个填充1的区域都会溢出。所以你可以检查,哪个区域被溢出了。例如,如果您想要a
的第 2 和第 3 区域中的 1 位,您可以这样做:
assert(c & 0b00100010000);
// ^^^ ^^ this segments overflows
【讨论】:
在我的真实情况下,MSB 为零。不错。 解释:a&b == b
,所以这一步是多余的。使用& ~a
进行屏蔽会删除a
中选定组的进位以外的所有位。以上是关于选择位掩码中与选择器位图中的 1 位重叠的设置位范围的主要内容,如果未能解决你的问题,请参考以下文章