我需要在位流中扫描16位字。 不保证在字节或字边界上对齐 。
实现此目标的最快方法是什么?暴力破解方法有很多种。使用表和/或移位,但是是否有任何“位旋转快捷方式”可以通过给出yes / no /也许包含每个字节或单词到达时的标志结果来减少计算量?
C代码,内在函数,x86机器代码都会很有趣。
使用简单的暴力有时是好的。
我认为预先计算该单词的所有移位值并将它们放入16个整数中,这样就得到了一个这样的数组(假设int宽度是的两倍short)
int
short
unsigned short pattern = 1234; unsigned int preShifts[16]; unsigned int masks[16]; int i; for(i=0; i<16; i++) { preShifts[i] = (unsigned int)(pattern<<i); //gets promoted to int masks[i] = (unsigned int) (0xffff<<i); }
然后,对于每一个无符号的空位,请从流中取出一个整数,并将该空位和前一个空位作一个整数,并将该无符号的整数与16个无符号的整数进行比较。如果其中任何一个匹配,您就得到了一个。
所以基本上是这样的:
int numMatch(unsigned short curWord, unsigned short prevWord) { int numHits = 0; int combinedWords = (prevWord<<16) + curWord; int i=0; for(i=0; i<16; i++) { if((combinedWords & masks[i]) == preShifsts[i]) numHits++; } return numHits; }
请注意,当在同一位上多次检测到模式时,这可能意味着多次命中:
例如32位0,而您要检测的模式是16 0,则意味着该模式被检测了16次!
假设它的编译时间大致与编写的时间相同,则每个输入字的时间成本为16个检查。对于每个输入位,这将执行&和和运算==,并进行分支或其他条件增量。并针对掩码的每一位进行表查找。
&
==
无需查找表;通过取而代之的是右移,combined我们可以获得效率显着提高的asm,如另一个答案所示,该答案还显示了如何在x86上使用SIMD将其向量化。
combined