我的解决方案:(对于输入块的每一位,都有这样一条线)
*parity ^= (((x[0] >> 30) & 0x00000001) * 0xc3e0d69f);
所有类型都是uint32。该行取输入x的第二位,将其移至LSB并将所有其他位设置为零。然后,32位奇偶校验与该位的相应奇偶校验集进行异或。
我发现这种乘法解决方案是执行此条件XOR的最快方法。有更快的方法吗?
答案 0 :(得分:4)
See here用于计算单词,字节等的奇偶校验的一些简洁的黑客
答案 1 :(得分:2)
我不完全明白你的意思是什么样的平价,但是如果这行代码是你想做的那样,它可能会有所改进。
一般规则:{0,1}中的 x x * N == - x & ; Ñ
这是因为-x表示0表示所有位都复位,1表示-1表示所有位都置位。
因此原始代码行可能会被重写为:
*parity ^= (-((x[0] >> 30) & 0x00000001) & 0xc3e0d69f);
在许多微处理器上乘以比乘法更短的时间计算了两个运算,但你应该检查一下。
此外,代码可以利用右移签名
*parity ^= (((int32_t)x[0] << 1 >> 31) & 0xc3e0d69f);
第一次移位将第30位移至第31位,即符号位,然后在所有其他位置上第二次扩展符号位,因为在大多数机器上的移位作为底板( x / 2 N ),因此用符号位(abc...yz>>3 == aaaabc...yz
)填充位移位。
但是这些技巧在C标准中被称为未定义的行为,因此不可移植。小心使用它们。
答案 2 :(得分:1)
有些处理器会为您完成此操作。请参阅x86的parity flag。
答案 3 :(得分:0)
如果我正确理解了这个问题,那你就是在做
for (i = 0; i < 32; i++)
*parity ^= (((x[0] >> i) & 1) * SOME_CONST[i]);
如果是这样,最好使用查找表:
for (i = 0; i < 4; i++)
*parity ^= PARITY_LUT[i][ (x[0] >> (i*8)) & 0xFF];
它将花费256kb,但速度会快得多。
答案 4 :(得分:0)
奇偶校验计算任务等同于计数。也称为“计数集位”,“填充续”或简称为popcount。一些处理器具有有效的指令来进行计算(POPCNT,VCNT)。
我建议使用最低的popcount。
可以通过内联汇编器或使用内置函数来访问它: __builtin_popcount()/ __popcnt()/ std :: bitset :: count()用于GCC / VS / C ++
我个人更喜欢使用 __ builtin_parity()