我正在尝试制作一个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机器上)
答案 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位数,然后它开始看起来更有趣。