【发布时间】:2022-01-13 08:28:11
【问题描述】:
我有两个整数值:
d_a = 6 和d_b = 3,所谓设置位之间的距离。
使用适当距离创建的蒙版如下所示:
uint64_t a = 0x1041041041041041; // 0001 0000 0100 0001 0000 0100 0001 0000
// 0100 0001 0000 0100 0001 0000 0100 0001
uint64_t b = 0x9249249249249249; // 1001 0010 0100 1001 0010 0100 1001 0010
// 0100 1001 0010 0100 1001 0010 0100 1001
目标是有一个target 掩码,它的位设置为d_b,但同时考虑到a 掩码中设置的位(例如,第一个设置的位被移位)。
第二件事是target 掩码中的距离不是恒定的,即target 掩码中设置位之间的零数量应等于d_b,或者只要它们之间设置@987654331 中的位就增加@
uint64_t target = 0x4488912224488912; // 0100 0100 1000 1000 1001 0001 0010 0010
// 0010 0100 0100 1000 1000 1001 0001 0010
可视化问题的图片:
蓝色条是a,黄色条是b。
我宁愿使用位操作内在函数而不是逐位操作。
编辑: 实际上,我有以下代码,但我正在寻找指令数量较少的解决方案。
void set_target_mask(int32_t d_a, int32_t d_b, int32_t n_bits_to_set, uint8_t* target)
{
constexpr int32_t n_bit_byte = std::numeric_limits<uint8_t>::digits;
int32_t null_cnt = -1;
int32_t n_set_bit = 0;
int32_t pos = 0;
while(n_set_bit != n_bits_to_set)
{
int32_t byte_idx = pos / n_bit_byte;
int32_t bit_idx = pos % n_bit_byte;
if(pos % d_a == 0)
{
pos++;
continue;
}
null_cnt++;
if(null_cnt % d_b == 0)
{
target[byte_idx] |= 1 << bit_idx;
n_set_bit++;
}
pos++;
}
}
【问题讨论】:
-
您能解释一下如何将
target与a和b结合起来吗?我不确定我是否能听从你的解释。 -
我的目标是把它们结合起来。假设
a表示已经预留资源:``` uint64 available = 0xFFFFFFFFFFFFFFFF ^ a ```现在我需要使用available根据d_b创建target -
但是组合规则是什么?为什么你不能,比如说,
OR在他们之间? -
标量
OR或简单的左移或右移没有内在函数,因为它们不是必需的:|和<<onuint64_t已经表达了与整数相同的行为或者会。除非您的意思是要一次对多个 uint64_t 元素执行此操作,使用_mm_or_si128或其他什么?仍然不清楚如何解决冲突,尽管您可以使用(x & (x<<1)) == 0检测它们,等等,直到d_b的班次计数。或者像x - (x>>d_b)或(x<<d_b) - x这样的东西可以在每个地区获得口罩? (未经测试,不确定是否完全有效) -
我认为
pdep方法也适合数组处理,因为设置为uint64_t的总位可以由popcnt确定,并且可以通过左移调整掩码,
标签: c++ x86 bit-manipulation intrinsics