gpt4 book ai didi

c++ - 将特定位置的位收集成一个新值

转载 作者:太空狗 更新时间:2023-10-29 21:02:59 26 4
gpt4 key购买 nike

我有一个大小为 N 个字符的位掩码,它是静态已知的(即可以在编译时计算,但它不是一个常量,所以我不能只写下来),位设置为1 表示“想要的”位。我有一个相同大小的值,只有在运行时才知道。我想从该值中按顺序收集“想要的”位到新值的开头。为简单起见,我们假设所需位数 <= 32。

完全未优化的引用代码,希望具有正确的行为:

template<int N, const char mask[N]>
unsigned gather_bits(const char* val)
{
unsigned result = 0;
char* result_p = (char*)&result;
int pos = 0;
for (int i = 0; i < N * CHAR_BIT; i++)
{
if (mask[i/CHAR_BIT] & (1 << (i % CHAR_BIT)))
{
if (val[i/CHAR_BIT] & (1 << (i % CHAR_BIT)))
{
if (pos < sizeof(unsigned) * CHAR_BIT)
{
result_p[pos/CHAR_BIT] |= 1 << (pos % CHAR_BIT);
}
else
{
abort();
}
}
pos += 1;
}
}
return result;
}

尽管我不确定该公式是否真的允许在编译时访问掩码的内容。但无论如何,它是可用的,也许 constexpr 函数或其他东西会是更好的主意。我不是在这里寻找必要的 C++ 魔法(我会弄清楚),只是寻找算法。

输入/输出示例,为清楚起见,使用 16 位值和虚数二进制表示法:

mask   = 0b0011011100100110
val = 0b0101000101110011
--
wanted = 0b__01_001__1__01_ // retain only those bits which are set in the mask
result = 0b0000000001001101 // bring them to the front
^ gathered bits begin here

我的问题是:

  • 执行此操作的最高效方法是什么? (是否有任何硬件说明可以提供帮助?)

  • 如果掩码和值都被限制为unsigned,即单个单词,而不是无界字符数组,会怎样?然后可以用固定的、简短的指令序列来完成吗?

最佳答案

pext(并行位提取)完全符合您在 Intel Haswell 中的要求。我不知道该指令的性能如何,但可能比替代方案更好。此操作也称为“压缩权限”或简称为“压缩”,Hacker's Delight 的实现是这样的:

unsigned compress(unsigned x, unsigned m) {
unsigned mk, mp, mv, t;
int i;

x = x & m; // Clear irrelevant bits.
mk = ~m << 1; // We will count 0's to right.

for (i = 0; i < 5; i++) {
mp = mk ^ (mk << 1); // Parallel prefix.
mp = mp ^ (mp << 2);
mp = mp ^ (mp << 4);
mp = mp ^ (mp << 8);
mp = mp ^ (mp << 16);
mv = mp & m; // Bits to move.
m = m ^ mv | (mv >> (1 << i)); // Compress m.
t = x & mv;
x = x ^ t | (t >> (1 << i)); // Compress x.
mk = mk & ~mp;
}
return x;
}

关于c++ - 将特定位置的位收集成一个新值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14200255/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com