我在Sergey Chernenko的一篇关于FFT的文章中包含了一个C函数。该功能通过执行奇偶分解来重新排列数据。但是不是使用位反转,而是通过以镜像方式添加1来实现,这比我测试的其他反转代码快得多。
/*
http://www.librow.com/articles/article-10 (Sergey Chernenko)
*/
void rearrange(float* Data, const unsigned int N) {
// Swap position
unsigned int Target = 0;
// Process all positions of input signal
for (unsigned int Position = 0; Position < N; ++Position)
{
// Only for not yet swapped entries
if (Target > Position)
{
// Swap entries
const float Temp = Data[Target];
Data[Target] = Data[Position];
Data[Position] = Temp;
}
// Bit mask
unsigned int Mask = N;
// While bit is set
while (Target & (Mask >>= 1))
// Drop bit
Target &= ~Mask;
// The current bit is 0 - set it
Target |= Mask;
}
}
我感兴趣的部分是镜像递增代码。我理解C中的逐位操作,我可以在心理上仔细阅读这个片段并验证它是否有效。我还不明白为什么它有效。我如何提出这个解决方案?
// Bit mask
unsigned int Mask = N;
// While bit is set
while (Target & (Mask >>= 1))
// Drop bit
Target &= ~Mask;
// The current bit is 0 - set it
Target |= Mask;
答案 0 :(得分:2)
要理解为什么这有效,首先要考虑正常增量如何起作用:给定一个任意位模式,一个增量找到一个连续的运行(可能是空的)直到零,清除所有的一个,并设置第一个零到一个,像这样:
0000 0001 - 0 -> 1 | No ones at the back (an empty run): insert 1 right away.
0111 1000 - 7 -> 8 | Replace a run of three ones with zeros, then insert 1
1011 1100 - 11 -> 12 | Replace a run of two ones with zeros, then insert 1
现在考虑一下你的算法:常规增量检测从数字后面开始的运行;你的循环检测从数字前面开始的运行。由于您说算法“以镜像方式添加一个”,N
必须是Target
中可能存在的两个最高幂的两倍。 while
循环尝试在Target
中找到1
中孤独Mask
的位置与零匹配的位置 - 第一个“洞”。循环体清除目标中的所有部分,从最高阶开始。一旦循环停止,Target |= Mask
将1
插入到循环找到的“洞”中。
答案 1 :(得分:1)
它只是按位置模拟加法1。除非职位逆转。
要添加1,您将继续修改位位置(从最低位开始),直到不再有进位。