Algorithm Gold Rader位反转算法

Algorithm Gold Rader位反转算法,algorithm,language-agnostic,bit-manipulation,fft,Algorithm,Language Agnostic,Bit Manipulation,Fft,我试图理解这个位反转算法。我找到了很多源代码,但它并没有真正解释伪代码是如何工作的。例如,我发现下面的伪代码来自 这是我找到的做FFT的源代码的完整版本 /************************************************ * FFT code from the book Numerical Recipes in C * * Visit www.nr.com for the licence. * ***********************

我试图理解这个位反转算法。我找到了很多源代码,但它并没有真正解释伪代码是如何工作的。例如,我发现下面的伪代码来自

这是我找到的做FFT的源代码的完整版本

/************************************************
* FFT code from the book Numerical Recipes in C *
* Visit www.nr.com for the licence.             *
************************************************/

// The following line must be defined before including math.h to correctly define M_PI
#define _USE_MATH_DEFINES
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#define PI  M_PI    /* pi to machine precision, defined in math.h */
#define TWOPI   (2.0*PI)

/*
 FFT/IFFT routine. (see pages 507-508 of Numerical Recipes in C)

 Inputs:
    data[] : array of complex* data points of size 2*NFFT+1.
        data[0] is unused,
        * the n'th complex number x(n), for 0 <= n <= length(x)-1, is stored as:
            data[2*n+1] = real(x(n))
            data[2*n+2] = imag(x(n))
        if length(Nx) < NFFT, the remainder of the array must be padded with zeros

    nn : FFT order NFFT. This MUST be a power of 2 and >= length(x).
    isign:  if set to 1, 
                computes the forward FFT
            if set to -1, 
                computes Inverse FFT - in this case the output values have
                to be manually normalized by multiplying with 1/NFFT.
 Outputs:
    data[] : The FFT or IFFT results are stored in data, overwriting the input.
*/

void four1(double data[], int nn, int isign)
{
    int n, mmax, m, j, istep, i;
    double wtemp, wr, wpr, wpi, wi, theta;
    double tempr, tempi;

    n = nn << 1;
    j = 1;
    for (i = 1; i < n; i += 2) {
        if (j > i) {
            //swap the real part
            tempr = data[j];     data[j] = data[i];     data[i] = tempr;
            //swap the complex part
            tempr = data[j+1]; data[j+1] = data[i+1]; data[i+1] = tempr;
        }
        m = n >> 1;
        while (m >= 2 && j > m) {
            j -= m;
            m >>= 1;
        }
        j += m;
    }
    mmax = 2;
    while (n > mmax) {
    istep = 2*mmax;
    theta = TWOPI/(isign*mmax);
    wtemp = sin(0.5*theta);
    wpr = -2.0*wtemp*wtemp;
    wpi = sin(theta);
    wr = 1.0;
    wi = 0.0;
    for (m = 1; m < mmax; m += 2) {
        for (i = m; i <= n; i += istep) {
        j =i + mmax;
        tempr = wr*data[j]   - wi*data[j+1];
        tempi = wr*data[j+1] + wi*data[j];
        data[j]   = data[i]   - tempr;
        data[j+1] = data[i+1] - tempi;
        data[i] += tempr;
        data[i+1] += tempi;
        }
        wr = (wtemp = wr)*wpr - wi*wpi + wr;
        wi = wi*wpr + wtemp*wpi + wi;
    }
    mmax = istep;
    }
}

/********************************************************
* The following is a test routine that generates a ramp *
* with 10 elements, finds their FFT, and then finds the *
* original sequence using inverse FFT                   *
********************************************************/

int main(int argc, char * argv[])
{
    int i;
    int Nx;
    int NFFT;
    double *x;
    double *X;

    /* generate a ramp with 10 numbers */
    Nx = 10;
    printf("Nx = %d\n", Nx);
    x = (double *) malloc(Nx * sizeof(double));
    for(i=0; i<Nx; i++)
    {
        x[i] = i;
    }

    /* calculate NFFT as the next higher power of 2 >= Nx */
    NFFT = (int)pow(2.0, ceil(log((double)Nx)/log(2.0)));
    printf("NFFT = %d\n", NFFT);

    /* allocate memory for NFFT complex numbers (note the +1) */
    X = (double *) malloc((2*NFFT+1) * sizeof(double));

    /* Storing x(n) in a complex array to make it work with four1. 
    This is needed even though x(n) is purely real in this case. */
    for(i=0; i<Nx; i++)
    {
        X[2*i+1] = x[i];
        X[2*i+2] = 0.0;
    }
    /* pad the remainder of the array with zeros (0 + 0 j) */
    for(i=Nx; i<NFFT; i++)
    {
        X[2*i+1] = 0.0;
        X[2*i+2] = 0.0;
    }

    printf("\nInput complex sequence (padded to next highest power of 2):\n");
    for(i=0; i<NFFT; i++)
    {
        printf("x[%d] = (%.2f + j %.2f)\n", i, X[2*i+1], X[2*i+2]);
    }

    /* calculate FFT */
    four1(X, NFFT, 1);

    printf("\nFFT:\n");
    for(i=0; i<NFFT; i++)
    {
        printf("X[%d] = (%.2f + j %.2f)\n", i, X[2*i+1], X[2*i+2]);
    }

    /* calculate IFFT */
    four1(X, NFFT, -1);

    /* normalize the IFFT */
    for(i=0; i<NFFT; i++)
    {
        X[2*i+1] /= NFFT;
        X[2*i+2] /= NFFT;
    }

    printf("\nComplex sequence reconstructed by IFFT:\n");
    for(i=0; i<NFFT; i++)
    {
        printf("x[%d] = (%.2f + j %.2f)\n", i, X[2*i+1], X[2*i+2]);
    }

    getchar();
}

/*

Nx = 10
NFFT = 16

Input complex sequence (padded to next highest power of 2):
x[0] = (0.00 + j 0.00)
x[1] = (1.00 + j 0.00)
x[2] = (2.00 + j 0.00)
x[3] = (3.00 + j 0.00)
x[4] = (4.00 + j 0.00)
x[5] = (5.00 + j 0.00)
x[6] = (6.00 + j 0.00)
x[7] = (7.00 + j 0.00)
x[8] = (8.00 + j 0.00)
x[9] = (9.00 + j 0.00)
x[10] = (0.00 + j 0.00)
x[11] = (0.00 + j 0.00)
x[12] = (0.00 + j 0.00)
x[13] = (0.00 + j 0.00)
x[14] = (0.00 + j 0.00)
x[15] = (0.00 + j 0.00)

FFT:
X[0] = (45.00 + j 0.00)
X[1] = (-25.45 + j 16.67)
X[2] = (10.36 + j -3.29)
X[3] = (-9.06 + j -2.33)
X[4] = (4.00 + j 5.00)
X[5] = (-1.28 + j -5.64)
X[6] = (-2.36 + j 4.71)
X[7] = (3.80 + j -2.65)
X[8] = (-5.00 + j 0.00)
X[9] = (3.80 + j 2.65)
X[10] = (-2.36 + j -4.71)
X[11] = (-1.28 + j 5.64)
X[12] = (4.00 + j -5.00)
X[13] = (-9.06 + j 2.33)
X[14] = (10.36 + j 3.29)
X[15] = (-25.45 + j -16.67)

Complex sequence reconstructed by IFFT:
x[0] = (0.00 + j -0.00)
x[1] = (1.00 + j -0.00)
x[2] = (2.00 + j 0.00)
x[3] = (3.00 + j -0.00)
x[4] = (4.00 + j -0.00)
x[5] = (5.00 + j 0.00)
x[6] = (6.00 + j -0.00)
x[7] = (7.00 + j -0.00)
x[8] = (8.00 + j 0.00)
x[9] = (9.00 + j 0.00)
x[10] = (0.00 + j -0.00)
x[11] = (0.00 + j -0.00)
x[12] = (0.00 + j 0.00)
x[13] = (-0.00 + j -0.00)
x[14] = (0.00 + j 0.00)
x[15] = (0.00 + j 0.00)

*/
/************************************************
*FFT代码来自C语言中的数字配方一书*
*有关许可证,请访问www.nr.com*
************************************************/
//在包含math.h之前,必须定义以下行才能正确定义M_PI
#定义使用数学定义
#包括
#包括
#包括
#定义PI M_PI/*PI到机器精度,在math.h中定义*/
#定义TWOPI(2.0*PI)
/*
FFT/IFFT例行程序。(参见第507-508页C中的数字配方)
投入:
数据[]:大小为2*NFFT+1的复杂*数据点数组。
数据[0]未使用,
*第n个复数x(n),表示0>1;
而(m>=2&&j>m){
j-=m;
m>>=1;
}
j+=m;
}
mmax=2;
而(n>mmax){
istep=2*mmax;
θ=TWOPI/(isign*mmax);
wtemp=sin(0.5*θ);
wpr=-2.0*wtemp*wtemp;
wpi=sin(θ);
wr=1.0;
wi=0.0;
对于(m=1;m对于(i=m;i,位反转算法通过反转每个项目的二进制地址来创建数据集的排列;例如,在16个项目集中,地址:
0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111

将更改为:
1000 0100 1100 0010 1010 0110 1110 0001 1001 0101 1101 0011 1011 0111 1111

然后将相应的项目移动到其新地址

或以十进制表示:
01234567891011213141415

变成
0841221061419513111715

伪代码中while循环的作用是将变量j设置为这个序列(顺便说一句,j的初始值应该是0)

您将看到序列是这样组成的:
0

01

0213

04261537

0841221061419513111715

每一个序列都是通过将前一个版本乘以2,然后再重复添加1来生成的。或者换一种方式来看:通过重复前一个序列,与值+n/2交错(这更详细地描述了算法中发生的情况)

然后在for循环的每次迭代中交换项目i和j,但仅当i函数位反转(数据){ var n=数据长度; var j=0; 对于(i=0;i虽然首先,谢谢大家回答我的问题。我在和帮助我的人交谈,我想我现在明白我的C++代码了。也许我的问题不太清楚,但是我想做的是用C++实现FFT。我在这个问题中给出的C++代码只是我发现的FFT源代码的前半部分。基本上,C++代码的这一部分是将输入分为实数和虚数,将实数存储到奇数索引中,并将虚数存储到偶数索引中。(RealE0,IIGNOR1,RealE1,IVIL1,RealE2,IMAGI2,…)索引开始于1,因为我们不需要交换第0索引。 下面的交换操作是交换实数和虚数

tempr = data[j];     data[j] = data[i];     data[i] = tempr;
tempr = data[j+1]; data[j+1] = data[i+1]; data[i+1] = tempr;
例如,我们的数组长度为8(nn=8)然后,我们将2输入*NN=16,将输入分成实数组和IMAG数,并将其存储到16的数组中。因此,第一次通过C++代码< <代码> >循环> <代码> j=1 < /C> >代码> i=1 < /代码>,将跳过<代码> < < /C> >代码> < < /C> >语句,现在在第二个for循环中,<代码> j=9 < /COD>,<代码> i=3 < /COD>因此if语句将为true,数据[9]、数据[3]将被交换,数据[9+1]和数据[3+1]将被交换。这是进行位反转,因为索引3和4具有第一个输入的实数和imag数,索引9和10具有第四个输入的实数和imag数

结果,001=1(第一次输入)

是交换的,所以,这是使用索引进行位反转


我还没有真正理解while循环,但我从@m69知道,这只是一种设置序列的方法,这样它就可以进行位反转。我对自己问题的解释对有同样问题的人来说非常有用。再次感谢大家。

这是一个关于何时不编写可移植代码的好例子。在右边的chip,这只是一条单周期吞吐量的单指令。奇怪,但在我整个行业生涯中,我从未做过一点反转。@MartinJames你可能没有做过FFT或数字处理。我们早餐吃这些东西。那么,有人能解释一下这个sudo代码中的位反转算法吗?伪代码h由于至少有一个bug,因为<代码> j>代码>从未被初始化。谢谢您的帮助,这有助于解释C++代码的while循环。
/************************************************
* FFT code from the book Numerical Recipes in C *
* Visit www.nr.com for the licence.             *
************************************************/

// The following line must be defined before including math.h to correctly define M_PI
#define _USE_MATH_DEFINES
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#define PI  M_PI    /* pi to machine precision, defined in math.h */
#define TWOPI   (2.0*PI)

/*
 FFT/IFFT routine. (see pages 507-508 of Numerical Recipes in C)

 Inputs:
    data[] : array of complex* data points of size 2*NFFT+1.
        data[0] is unused,
        * the n'th complex number x(n), for 0 <= n <= length(x)-1, is stored as:
            data[2*n+1] = real(x(n))
            data[2*n+2] = imag(x(n))
        if length(Nx) < NFFT, the remainder of the array must be padded with zeros

    nn : FFT order NFFT. This MUST be a power of 2 and >= length(x).
    isign:  if set to 1, 
                computes the forward FFT
            if set to -1, 
                computes Inverse FFT - in this case the output values have
                to be manually normalized by multiplying with 1/NFFT.
 Outputs:
    data[] : The FFT or IFFT results are stored in data, overwriting the input.
*/

void four1(double data[], int nn, int isign)
{
    int n, mmax, m, j, istep, i;
    double wtemp, wr, wpr, wpi, wi, theta;
    double tempr, tempi;

    n = nn << 1;
    j = 1;
    for (i = 1; i < n; i += 2) {
        if (j > i) {
            //swap the real part
            tempr = data[j];     data[j] = data[i];     data[i] = tempr;
            //swap the complex part
            tempr = data[j+1]; data[j+1] = data[i+1]; data[i+1] = tempr;
        }
        m = n >> 1;
        while (m >= 2 && j > m) {
            j -= m;
            m >>= 1;
        }
        j += m;
    }
    mmax = 2;
    while (n > mmax) {
    istep = 2*mmax;
    theta = TWOPI/(isign*mmax);
    wtemp = sin(0.5*theta);
    wpr = -2.0*wtemp*wtemp;
    wpi = sin(theta);
    wr = 1.0;
    wi = 0.0;
    for (m = 1; m < mmax; m += 2) {
        for (i = m; i <= n; i += istep) {
        j =i + mmax;
        tempr = wr*data[j]   - wi*data[j+1];
        tempi = wr*data[j+1] + wi*data[j];
        data[j]   = data[i]   - tempr;
        data[j+1] = data[i+1] - tempi;
        data[i] += tempr;
        data[i+1] += tempi;
        }
        wr = (wtemp = wr)*wpr - wi*wpi + wr;
        wi = wi*wpr + wtemp*wpi + wi;
    }
    mmax = istep;
    }
}

/********************************************************
* The following is a test routine that generates a ramp *
* with 10 elements, finds their FFT, and then finds the *
* original sequence using inverse FFT                   *
********************************************************/

int main(int argc, char * argv[])
{
    int i;
    int Nx;
    int NFFT;
    double *x;
    double *X;

    /* generate a ramp with 10 numbers */
    Nx = 10;
    printf("Nx = %d\n", Nx);
    x = (double *) malloc(Nx * sizeof(double));
    for(i=0; i<Nx; i++)
    {
        x[i] = i;
    }

    /* calculate NFFT as the next higher power of 2 >= Nx */
    NFFT = (int)pow(2.0, ceil(log((double)Nx)/log(2.0)));
    printf("NFFT = %d\n", NFFT);

    /* allocate memory for NFFT complex numbers (note the +1) */
    X = (double *) malloc((2*NFFT+1) * sizeof(double));

    /* Storing x(n) in a complex array to make it work with four1. 
    This is needed even though x(n) is purely real in this case. */
    for(i=0; i<Nx; i++)
    {
        X[2*i+1] = x[i];
        X[2*i+2] = 0.0;
    }
    /* pad the remainder of the array with zeros (0 + 0 j) */
    for(i=Nx; i<NFFT; i++)
    {
        X[2*i+1] = 0.0;
        X[2*i+2] = 0.0;
    }

    printf("\nInput complex sequence (padded to next highest power of 2):\n");
    for(i=0; i<NFFT; i++)
    {
        printf("x[%d] = (%.2f + j %.2f)\n", i, X[2*i+1], X[2*i+2]);
    }

    /* calculate FFT */
    four1(X, NFFT, 1);

    printf("\nFFT:\n");
    for(i=0; i<NFFT; i++)
    {
        printf("X[%d] = (%.2f + j %.2f)\n", i, X[2*i+1], X[2*i+2]);
    }

    /* calculate IFFT */
    four1(X, NFFT, -1);

    /* normalize the IFFT */
    for(i=0; i<NFFT; i++)
    {
        X[2*i+1] /= NFFT;
        X[2*i+2] /= NFFT;
    }

    printf("\nComplex sequence reconstructed by IFFT:\n");
    for(i=0; i<NFFT; i++)
    {
        printf("x[%d] = (%.2f + j %.2f)\n", i, X[2*i+1], X[2*i+2]);
    }

    getchar();
}

/*

Nx = 10
NFFT = 16

Input complex sequence (padded to next highest power of 2):
x[0] = (0.00 + j 0.00)
x[1] = (1.00 + j 0.00)
x[2] = (2.00 + j 0.00)
x[3] = (3.00 + j 0.00)
x[4] = (4.00 + j 0.00)
x[5] = (5.00 + j 0.00)
x[6] = (6.00 + j 0.00)
x[7] = (7.00 + j 0.00)
x[8] = (8.00 + j 0.00)
x[9] = (9.00 + j 0.00)
x[10] = (0.00 + j 0.00)
x[11] = (0.00 + j 0.00)
x[12] = (0.00 + j 0.00)
x[13] = (0.00 + j 0.00)
x[14] = (0.00 + j 0.00)
x[15] = (0.00 + j 0.00)

FFT:
X[0] = (45.00 + j 0.00)
X[1] = (-25.45 + j 16.67)
X[2] = (10.36 + j -3.29)
X[3] = (-9.06 + j -2.33)
X[4] = (4.00 + j 5.00)
X[5] = (-1.28 + j -5.64)
X[6] = (-2.36 + j 4.71)
X[7] = (3.80 + j -2.65)
X[8] = (-5.00 + j 0.00)
X[9] = (3.80 + j 2.65)
X[10] = (-2.36 + j -4.71)
X[11] = (-1.28 + j 5.64)
X[12] = (4.00 + j -5.00)
X[13] = (-9.06 + j 2.33)
X[14] = (10.36 + j 3.29)
X[15] = (-25.45 + j -16.67)

Complex sequence reconstructed by IFFT:
x[0] = (0.00 + j -0.00)
x[1] = (1.00 + j -0.00)
x[2] = (2.00 + j 0.00)
x[3] = (3.00 + j -0.00)
x[4] = (4.00 + j -0.00)
x[5] = (5.00 + j 0.00)
x[6] = (6.00 + j -0.00)
x[7] = (7.00 + j -0.00)
x[8] = (8.00 + j 0.00)
x[9] = (9.00 + j 0.00)
x[10] = (0.00 + j -0.00)
x[11] = (0.00 + j -0.00)
x[12] = (0.00 + j 0.00)
x[13] = (-0.00 + j -0.00)
x[14] = (0.00 + j 0.00)
x[15] = (0.00 + j 0.00)

*/
0                                               
0                       1                       
0           2           1           3           
0     4     2     6     1     5     3     7     
0  8  4 12  2 10  6 14  1  9  5 13  3 11  7 15  
tempr = data[j];     data[j] = data[i];     data[i] = tempr;
tempr = data[j+1]; data[j+1] = data[i+1]; data[i+1] = tempr;
         100 = 4  (fourth input)