Algorithm 位扩展/复制算法?

Algorithm 位扩展/复制算法?,algorithm,bit-manipulation,bit,expansion,duplication,Algorithm,Bit Manipulation,Bit,Expansion,Duplication,是否有一种高效(快速)算法可以执行位扩展/复制 例如,将8位值中的每个位扩展3(创建24位值): 已经提出的暴力方法是创建一个查找表。将来,扩展值可能需要可变。也就是说,在上面的示例中,我们将扩展3,但可能需要扩展一些其他值。这将需要多个查找表,如果可能的话,我希望避免使用这些表。您可以一次输入一位。当然,它会比查找表慢,但是如果你在为一个小的、8位的微控制器写东西,而没有足够的空间放一个表,它应该有最小的ROM占用空间。如果出于某种原因,算术计算比内存访问快,那么它有可能比查找表快。如果计算是

是否有一种高效(快速)算法可以执行位扩展/复制

例如,将8位值中的每个位扩展3(创建24位值):


已经提出的暴力方法是创建一个查找表。将来,扩展值可能需要可变。也就是说,在上面的示例中,我们将扩展3,但可能需要扩展一些其他值。这将需要多个查找表,如果可能的话,我希望避免使用这些表。

您可以一次输入一位。当然,它会比查找表慢,但是如果你在为一个小的、8位的微控制器写东西,而没有足够的空间放一个表,它应该有最小的ROM占用空间。

如果出于某种原因,算术计算比内存访问快,那么它有可能比查找表快。如果计算是矢量化的(PPC AltiVec或Intel SSE)和/或程序的其他部分需要使用缓存的每一位,则这可能是可能的

如果膨胀系数=3,则只需要7条说明:

out = (((in * 0x101 & 0x0F00F) * 0x11 & 0x0C30C3) * 5 & 0x249249) * 7;
或其他替代方案,包括10条说明:

out = (in | in << 8) & 0x0F00F;
out = (out | out << 4) & 0x0C30C3;
out = (out | out << 2) & 0x249249;
out *= 7;

out=(在|中,如果你只处理8位值,那么查找表几乎肯定是最好的选择。它占用的空间非常小。你能详细介绍一下你的用例以及你希望常见的操作吗?输入是一个恒定的串行位流。在当前的需求中,每个数据块一次到达8字节,而然后,h需要将每一位扩展3以作为另一个位流发送。192位中的64位输出。未来的需求可能包括添加“头”每个扩展的8位值之前的位,当然还有填充到字节边界的位。LUT很快,但考虑到它需要多久运行一次,任何潜在的性能改进都是值得赞赏的。许多体系结构都有可以大大加快此类计算的指令。如果您不怕破坏跨平台兼容性级别使用这些指令几乎可以肯定是一种胜利——如果你在优化某些东西,那么在算法上这是“微不足道的”然后转向低级优化是关键。@Kaganar同意。这是针对PPC嵌入式系统的,我见过其他位操作的优化,但这种位扩展问题似乎并不常见。我知道有比我更聪明的人已经发现了这一点。;)确切的体系结构是什么?(是的,嵌入式应用程序解释了为什么你对速度如此狂热——固定硬件上的固定预算。)回答很棒。我的同事和我在进行一些手工操作和白板头脑风暴时接近了这一点,但这比我们的方法要有效得多。一旦我们实现了其余的代码,我将不得不运行一些测试,看看结果如何。是否有人与这背后的数学有联系?我一直在搜索,但一直没有找到答案ly设法找到了魔法,但没有解释它是如何工作的。我看到魔法数字有一些模式,但其他一切都让我迷惑不解。nvm,我找到了它。帮助写出二进制文件,然后找到模式。尽管如此,任何关于这个主题的链接都将不胜感激。@cory.todd:受.
out = (in | in << 8) & 0x0F00F;
out = (out | out << 4) & 0x0C30C3;
out = (out | out << 2) & 0x249249;
out *= 7;
unsigned mask = 0x0FF;
unsigned out = in;
for (scale = 4; scale != 0; scale /= 2)
{
  shift = scale * (N - 1);
  mask &= ~(mask << scale);
  mask |= mask << (scale * N);
  out = out * ((1 << shift) + 1) & mask;
}
out *= (1 << N) - 1;
unsigned mask = 0x0FF;
unsigned out = in;
for (scale = 4; scale != 0; scale /= 2)
{
  shift = scale * (N - 1);
  mask &= ~(mask << scale);
  mask |= mask << (scale * N);
  out = (out | out << shift) & mask;
}
out *= (1 << N) - 1;