C语言 如何写一个SWAR比较,把0xFF在一个车道上的比赛?



我试图写一个SWAR比较相等操作,在uint64_t上工作,假装是uint8_t的8个'车道'。基于Hacker’s Delight和Bit Twiddling Hacks中的技术,我所取得的最接近的结果如下:

uint64_t compare_eq (uint64_t x, uint64_t y) {
uint64_t xored = x ^ y;
uint64_t mask = 0x7F * 0x0101010101010101ULL;
uint64_t tmp = (xored & mask) + mask;
return ~(tmp | xored | mask);
}

然而,这将0x80放入匹配的"车道"中,而0x00放入不匹配的"车道"中,而我希望0xFF在匹配的"车道"中,0x00在不匹配的"车道"中。有没有可能不写分支?

为了记录,这只是一个非零字节计算高位的变体(少一条指令),加上@njuffa和@Nate Eldredge的评论(可能比4386427的答案更有效)。

uint64_t compare_eq (uint64_t x, uint64_t y) {
uint64_t xored = x ^ y;
uint64_t mask = ((((xored >> 1) | 0x8080808080808080) - xored) & 0x8080808080808080);
return (mask << 1) - (mask >> 7);
}

首先,在发布的代码中有一个错误(拼写错误?):

uint64_t mask = 0x7F * 0x0101010101010101ULL;
^^
Missing 0x

一旦你在车道上有0x80或0x00,你可以除以0x80并乘以0xff。

:

uint64_t compare_eq (uint64_t x, uint64_t y) {
uint64_t xored = x ^ y;
uint64_t mask = 0x7F * 0x0101010101010101ULL;
uint64_t tmp = (xored & mask) + mask;
uint64_t res = ~(tmp | xored | mask);
res = res / 0x80;
res = res * 0xff;
return res;
}

相关内容

  • 没有找到相关文章

最新更新