如何编写将 0xFF 置于匹配通道中的 SWAR 比较?

Posted

技术标签:

【中文标题】如何编写将 0xFF 置于匹配通道中的 SWAR 比较?【英文标题】:How to write a SWAR comparison which puts 0xFF in a lane on matches? 【发布时间】:2021-08-07 20:33:19 【问题描述】:

我正在尝试编写一个 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 放入“通道” '那不是。不分支可以写吗?

【问题讨论】:

一旦你有字节宽的 MSB,(所以 0x800x00 每个字节通道)右移 7 然后乘以 0xff (255)。 @njuffa 对我来说,这看起来像是一个(体面的)答案 @njuffa:相当于(x << 1) - (x >> 7),如果你不相信你的编译器会为你解决这个问题。 @NateEldredge x << 1 如果上车道是 0x80 会溢出 @phuclv:是的,但无论如何结果都是正确的(无符号溢出在 C 中定义良好)。在这种情况下,顶部通道将从 0 中减去 1,即 0xff。 【参考方案1】:

为了记录,这只是一个变体,用于计算非零字节中的高位(少一条指令)与来自 @njuffa 和 @Nate Eldredge 的 cmets(可能比 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);

【讨论】:

哎呀,我忘了我必须反转哪种字节映射到 0 和 0x80 的逻辑。希望现在修复。 其实不,这不是问题所在。你能举一个输入错误结果的例子吗? 好的,我现在明白了,希望真的修好了。很抱歉造成混乱:-/【参考方案2】:

首先发布的代码中有一个错误(错字?):

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;

【讨论】:

以上是关于如何编写将 0xFF 置于匹配通道中的 SWAR 比较?的主要内容,如果未能解决你的问题,请参考以下文章

理解 Java 中的 &0xff 值

宏任务和微任务——三目算符与加号优先级——原生的js如何禁用button——0xff ^ 33 的结果是——in的用法——正则匹配网址

如何使用 xampp 将 phpmyadmin 置于联机状态?

如何访问discord.py中的哪个语音通道用户写入命令?

如何将 HTML 内容置于 Flash 影片之上?

将 UIImage 数据转换为 const unsigned char myArry[100]