根据许多掩码分割一个比特流的有效方法?

时间:2013-11-28 04:07:37

标签: bit-manipulation bit bitmask bitstream

我正在尝试制作一个Inverse Multiplexer,根据一些面具可以将一个比特流分成多个。

这是想法示例

这是一个24位流,每个字母代表1位:

abcdefgh ijklmnop qrstuvwx

给定三个掩码,每个掩码都没有共同点,如果&他们在一起[1,1,1,1,1,1,1,1]

[1, 1, 0, 0, 1, 0, 0, 0]
[0, 0, 1, 0, 0, 0, 1, 1]
[0, 0, 0, 1, 0, 1, 0, 0]

将这些蒙版应用于此

stream1 = ab__e___ ij__m___ qr__u___
stream2 = __c___gh __k___op __s___wx
stream3 = ___d_f__ ___l_n__ ___t_v__

因此原始比特流被分成三个比特流,如下所示:

stream1 = abeijmqru
stream2 = cghkopswx
stream3 = dflntv

以上只是一个例子,我需要对给定的比特流应用任意数量的掩码。在每个彼此之间保证掩码具有OR ZERO的结果。所有面具的AND都有自己的结果。所有面具的长度都相同。

我写了一个愚蠢的版本来暴力破解这个想法,这个想法基本上是在一个循环中逐个移位。认为它肯定没有效率。

我调查了这个http://graphics.stanford.edu/~seander/bithacks.html

毫无头绪。任何人都有更好的想法如何改善这一点? (在x86机器上)

2 个答案:

答案 0 :(得分:1)

如果每个位只映射到一个输出流,我认为定义哪些输出流分配给哪个输出流更有意义,而不是使用掩码。例如,您的示例掩码

[1, 1, 0, 0, 1, 0, 0, 0]
[0, 0, 1, 0, 0, 0, 1, 1]
[0, 0, 0, 1, 0, 1, 0, 0]

而是表示为将当前位分配给

的输出流
[0, 0, 1, 2, 0, 2, 1, 1]

还有一些将它们绑在一起的伪代码

stream_order = [0, 0, 1, 2, 0, 2, 1, 1]
index = 0
for bit in input_stream:
    n = stream_order[index]
    output_streams[n].push(bit)
    index++
    index %= len(stream_order)

答案 1 :(得分:1)

我想,因为你只有一个对应于单个“流”的位,所以你可以同时移动所有这些并查看“它属于哪个流”。这将允许适度的并行实现 - 尽管它将取决于架构和掩模的大小,这将有多高效。它还取决于您想要执行此操作的频率 - 一定量的预计算会使后续运行更有效。它确实听起来有点蛮力;可能并不比你已经做的更好。

当然,有一个可爱的问题Extracting bits with a single multiplication(我写了接受的答案......),它提出了一种通过单次乘法从较大数字中提取某些位的方法。这种方法的缺点是你无法对任意数量的设置位执行此操作 - 中间需要有多个空格。

原则上,这可以通过重复该过程两次或更多次,并在其间应用额外的掩模来解决。让我们看看这对于上面问题中的第一个掩码是如何工作的。

mask1 = 11001000
num =   abcdefgh
temp = num & mask1 = ab..e...
magic = 4 + 1
answer =     ab..e... 
           ab..e..... + 
           ------------
           ababe.e...
mask2 =    0011100000
ans & mask = abe.....

使用mask-multiply-mask(3次操作)将您想要的三个数字放入前三个位置。对于8位数字来说效率不是很高;但你可以将它扩展为32位数,然后它开始看起来更有趣。