是否有一种高效(快速)的算法可以执行位扩展/复制?
例如,将8位值中的每个位扩展3次(创建24位值):
1101 0101 => 11111100 01110001 11000111
提出的暴力方法是创建一个查找表。将来,扩展值可能需要是可变的。也就是说,在上面的例子中,我们是通过3进行扩展,但可能需要通过其他值进行扩展。如果可能的话,我希望避免使用多个查找表。
是否有一种高效(快速)的算法可以执行位扩展/复制?
例如,将8位值中的每个位扩展3次(创建24位值):
1101 0101 => 11111100 01110001 11000111
提出的暴力方法是创建一个查找表。将来,扩展值可能需要是可变的。也就是说,在上面的例子中,我们是通过3进行扩展,但可能需要通过其他值进行扩展。如果可能的话,我希望避免使用多个查找表。
如果算术计算比内存访问快,那么有机会比查找表更快。如果计算可以向量化(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;
对于其他扩展因子>=3:
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;
对于扩展因子大于等于2的其他替代方案:
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;
shift
和mask
的值最好在处理位流之前进行计算。