在字节数组中计数0个b位子序列
Counting zero b-bit subsequences in a byte array
我正在寻找在任意大小的S (S通常很小)的uint8_t
数组中计数b位子序列(非重叠)的数量的最快方法。 0 (S通常很小)。
- b总是2的幂,有效值实际上只有:1、2、4、8、16和32
- 假设
uint8_t
的位数为8,且S * 8能被b 整除
例子:
- b = 4, array =
0xA0 0x39 0x04 0x30
-正确答案为3 - b = 1, array =
0xFF 0x1F 0xF8
-正确答案为6 - b = 16, array =
0x05 0x16 0x32 0x00
-正确答案为0
我目前正在做的是我"解包"成字节的位,然后memcmp与零缓冲区的子序列,但在我看来,应该有一个更快的方法来做到这一点。
您可以使用类似于检测字符串中的空字节的众所周知的方法的位旋转。例如,对于b=4,您可以读取32位字x
并执行
__builtin_popcount((x - 0x11111111) & (~x & 0x88888888))
这里,x - 0x11111111
产生一个值,如果4位组为零或已经设置,则每个4位组的高位为1;第二部分丢弃已经设置的部分,然后只计算剩余的位。
对于仅考虑从b
位偏移开始的序列的额外约束,有一个非常简单的解决方案(这里也不存在端序性问题,因为您只考虑整个零块):
size_t countZeroChunks(const uint8_t* bytes, size_t nbytes, uint8_t b) {
assert(b == 2 || b == 4 || b == 8 || b == 16 || b == 32);
size_t count = 0;
if(b <= 8) {
// chunks fit inside a byte
for(size_t i = 0; i < nbytes; ++i) {
uint8_t byte = *bytes++;
for(uint8_t offset = 0; offset < 8; offset += b) {
// collect bits in chunk
// e.g. for b=2 at offset=2
// yyyyxxyy >> 2 -> 00yyyyxx
// 00yyyyxx << 6 -> xx000000
uint8_t chunk = (byte >> offset) << ((8 - offset) % 8);
if(chunk == 0)
++count;
}
}
} else {
// chunks span multiple bytes
size_t nchunks = nbytes * 8 / b;
for(size_t i = 0; i < nchunks; ++i) {
// collect chunk from bytes
uint32_t chunk = 0;
for(size_t k = 0, bytesPerChunk = b / 8; k < bytesPerChunk; ++k)
chunk |= (uint32_t)(*bytes++) << (k * 8);
if(chunk == 0)
++count;
}
}
return count;
}
相关文章:
- 如何在C++中比较两个char数组
- 从文件中读取多个字节,并将它们存储在C++中进行比较
- 如何将字节数组元素替换为修改的十六进制 ASCII 符号?
- 基于字节数组生成静态范围整数值
- 复制后删除原始数组指针将前 3 个字节设置为 0
- 将文本文件的内容写入C 中的文件块(512个字节)的数组
- 解释为 4 个字节的两个整数之间的计算范数
- 如何将 BYTE 数组中的两个字节存储为 int(或类似的东西)
- SWIG-为具有四个参数的函数创建一个类型映射,该参数传递一个字节数组
- 从 5x10^8 个不同的数组元素读取,每次读取 4 个字节
- 在字节数组中嵌入多个整数
- 如何构造一个字节数组,其中包含多个数据类型值
- 使用std::copy将char数组中的两个字节复制到无符号short中
- 从char数组中读取n个字节,并将其作为double类型返回
- 将m个字节的数组拆分为n个字节的块
- 正在将char数组的最后8个字节设置为__uint64
- C++ wxsocket TCP 服务器发送无符号字符数组,但 python 客户端再获得 4 个字节
- 在字节数组中计数0个b位子序列
- 将3个独立的字节数组组合成一个字节数组
- 从字节数组中打印出26个字节