选择位掩码中与选择器位图中的1位重叠的设置位的跨度
Select spans of set bits in a bitmask that overlap with a 1-bit in a selector bitmap
给定:
- 比特掩码
a
(例如,std::uint64_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;
在uint64_t
的情况下,您可以使用以下技巧:
让我们设置a = 0b11011101101
。至少有一个0位是很重要的。位掩码有4个单独的区域,用1个位填充。如果执行c=a+(a&b)
,则如果在此区域中设置了b
的至少一位,则每个1-填充区域都将溢出。所以你可以检查一下,哪个区域被飞越了。例如,如果您想要a
的第2和第3区域中的1位,您可以这样做:
assert(c & 0b00100010000);
// ^^^ ^^ this segments overflows
相关文章:
- 内置函数可查看CPP中的成员变量
- Ardunio UNO解决了多个重叠的定时器循环
- 最高有效数字侧的第N位
- 如何获取一个数字的前3位
- 在c++中检查长方体是否尽可能快地重叠(无迭代)
- QTableView:endMoveRows在模型中重置水平页眉大小
- C / C++ 移位/偏移/向左或向右移动位图?
- 对字符串进行位操作
- 如何在24位SDL_Surface上设置像素的颜色
- 将浮动的heightmap数组导出为16位原始值
- 将尾部调用void(i32,..)位转换为llvm::函数以获取FnAttribute
- 算术序列与区间的最大重叠
- C++Union/Struct位域的实现和可移植性
- 为什么C++逐位AND运算符在不同大小的操作数中表现为这样
- 将按位if条件转换为普通if条件
- 对字符数组中的元素执行逐位操作
- 将位字段导出到数组
- 将应用程序从32位移植到64位时出现问题
- 选择位掩码中与选择器位图中的1位重叠的设置位的跨度
- 如何读取和重置字符位