C++ 在与选择器位图中的1位重叠的位掩码中选择设置位的范围
鉴于:C++ 在与选择器位图中的1位重叠的位掩码中选择设置位的范围,c++,x86,bit-manipulation,bmi,C++,X86,Bit Manipulation,Bmi,鉴于: 一种位掩码A(例如,std::uint64\u t),它至少包含一组(1)位 一种选择器位掩码b,它是A的子集(即A&b==b),并且至少有一个位集 我想在a中选择与b中的位重叠的连续1位跨距: a = 0b1111001110001100; b = 0b0000001010001000; //c=0b0000001110001100 // XXXX YYY ZZ XXXX组在c中为0,因为b&XXXX为false。复制ZZ组是因为b设置了一个Z位。出于同样的原因,YY
- 一种位掩码
(例如,A
),它至少包含一组(std::uint64\u t
)位1
- 一种选择器位掩码
,它是b
的子集(即A
),并且至少有一个位集A&b==b
a
中选择与b
中的位重叠的连续1位跨距:
a = 0b1111001110001100;
b = 0b0000001010001000;
//c=0b0000001110001100
// XXXX YYY ZZ
XXXX组在c
中为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
?(即无环)
其他: 使用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;
std::uint64\u t a=0B0110111001101;
std::uint64_t b=0B010010100000101;
断言(a&b==b);//子集
std::cout(a)1)){//最长1系列时间的长度
c |=x;
}
std::cout(c)在uint64\u t
的情况下,您可以执行以下操作:
让我们设置a=0b11011101101
。至少有一个0位很重要。位掩码有4个单独的区域,用1位填充。如果执行c=a+(a&b)
,则如果此区域中至少设置了一位b
,则每个1填充区域将溢出。所以你可以检查一下,哪个区域被飞越了。例如,如果您希望在a
的第2和第3区域中使用1位,则可以执行以下操作:
assert(c & 0b00100010000);
// ^^^ ^^ this segments overflows
“a段”包括长度为1的段吗?@M.M是的,1段只是长度为1-s的非零序列。我花了大约10分钟来解码你的描述,所以我做了一个编辑以澄清未来的读者。我想你遗漏了英特尔的BMI1/BMI2扩展是偶然的,不是因为。您确实提到了AVX,它绝对不是基线:甚至在上也不受支持,只有i3和更高版本。谢谢,英特尔:(事实上,BMI指令本身都没有明显的用处。不过,可能将pext
/pdep
作为构建块。您是否绝对需要指定格式的输出?Denis的回答会丢失关于每个组有多大的信息,但每个匹配组的结果中都有一个1。@PeterCordes谢谢您的更正。我非常感谢。在我的实际情况中,MSB为零。很好。解释:a&b==b
,因此该步骤是多余的。使用&~a
掩蔽将删除a
中选定组执行之外的所有位。