FFT algorithms (collection)

ver. 1

                #include < complex  >
                #include < iostream >
                #include < valarray  >
                 
                const double PI = 3.141592653589793238460;
                 
                typedef std::complex Complex;
                typedef std::valarray CArray;
                 
                // Cooley–Tukey FFT (in-place, divide-and-conquer)
                // Higher memory requirements and redundancy although more intuitive
                
                void fft(CArray& x)
                {
                    const size_t N = x.size();
                    if (N <= 1) return;
                 
                    // divide
                    CArray even = x[std::slice(0, N/2, 2)];
                    CArray  odd = x[std::slice(1, N/2, 2)];
                 
                    // conquer
                    fft(even);
                    fft(odd);
                 
                    // combine
                    for (size_t k = 0; k < N/2; ++k)
                    {
                        Complex t = std::polar(1.0, -2 * PI * k / N) * odd[k];
                        x[k    ] = even[k] + t;
                        x[k+N/2] = even[k] - t;
                    }
                }
                
                // inverse fft (in-place)
                void ifft(CArray& x)
                {
                    // conjugate the complex numbers
                    x = x.apply(std::conj);
                 
                    // forward fft
                    fft( x );
                 
                    // conjugate the complex numbers again
                    x = x.apply(std::conj);
                 
                    // scale the numbers
                    x /= x.size();
                }
                 
                int main()
                {
                    const Complex test[] = { 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0 };
                    CArray data(test, 8);
                 
                    // forward fft
                    fft(data);
                 
                    std::cout << "fft" << std::endl;
                    for (int i = 0; i < 8; ++i)
                    {
                        std::cout << data[i] << std::endl;
                    }
                 
                    // inverse fft
                    ifft(data);
                 
                    std::cout << std::endl << "ifft" << std::endl;
                    for (int i = 0; i < 8; ++i)
                    {
                        std::cout << data[i] << std::endl;
                    }
                    return 0;
                }

        

ver. 2

                    #include < complex > 
                    #include < iostream > 
                    #include <  valarray > 
                     
                    const double PI = 3.141592653589793238460;
                     
                    typedef std::complex Complex;
                    typedef std::valarray CArray;
                     
                    // Cooley-Tukey FFT (in-place, breadth-first, decimation-in-frequency)
                    // Better optimized but less intuitive
                    // !!! Warning : in some cases this code make result different from not optimased version above (need to fix bug)
                    // The bug is now fixed @2017/05/30 
                    void fft(CArray &x)
                    {
                        // DFT
                        unsigned int N = x.size(), k = N, n;
                        double thetaT = 3.14159265358979323846264338328L / N;
                        Complex phiT = Complex(cos(thetaT), -sin(thetaT)), T;
                        while (k > 1)
                        {
                            n = k;
                            k >>= 1;
                            phiT = phiT * phiT;
                            T = 1.0L;
                            for (unsigned int l = 0; l < k; l++)
                            {
                                for (unsigned int a = l; a < N; a += n)
                                {
                                    unsigned int b = a + k;
                                    Complex t = x[a] - x[b];
                                    x[a] += x[b];
                                    x[b] = t * T;
                                }
                                T *= phiT;
                            }
                        }
                        // Decimate
                        unsigned int m = (unsigned int)log2(N);
                        for (unsigned int a = 0; a < N; a++)
                        {
                            unsigned int b = a;
                            // Reverse bits
                            b = (((b & 0xaaaaaaaa) >> 1) | ((b & 0x55555555) << 1));
                            b = (((b & 0xcccccccc) >> 2) | ((b & 0x33333333) << 2));
                            b = (((b & 0xf0f0f0f0) >> 4) | ((b & 0x0f0f0f0f) << 4));
                            b = (((b & 0xff00ff00) >> 8) | ((b & 0x00ff00ff) << 8));
                            b = ((b >> 16) | (b << 16)) >> (32 - m);
                            if (b > a)
                            {
                                Complex t = x[a];
                                x[a] = x[b];
                                x[b] = t;
                            }
                        }
                        //// Normalize (This section make it not working correctly)
                        //Complex f = 1.0 / sqrt(N);
                        //for (unsigned int i = 0; i < N; i++)
                        //	x[i] *= f;
                    }
                    
                    // inverse fft (in-place)
                    void ifft(CArray& x)
                    {
                        // conjugate the complex numbers
                        x = x.apply(std::conj);
                     
                        // forward fft
                        fft( x );
                     
                        // conjugate the complex numbers again
                        x = x.apply(std::conj);
                     
                        // scale the numbers
                        x /= x.size();
                    }
                     
                    int main()
                    {
                        const Complex test[] = { 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0 };
                        CArray data(test, 8);
                     
                        // forward fft
                        fft(data);
                     
                        std::cout << "fft" << std::endl;
                        for (int i = 0; i < 8; ++i)
                        {
                            std::cout << data[i] << std::endl;
                        }
                     /*
                        // inverse fft
                        ifft(data);
                     
                        std::cout << std::endl << "ifft" << std::endl;
                        for (int i = 0; i < 8; ++i)
                        {
                            std::cout << data[i] << std::endl;
                        }
                    
                        */
                        return 0;
                    }

            

ver. 3

                    #include < iostream >
                    #include < complex >
                    #define MAX 200
                    
                    using namespace std;
                    
                    #define M_PI 3.1415926535897932384
                    
                    int log2(int N)    /*function to calculate the log2(.) of int numbers*/
                    {
                      int k = N, i = 0;
                      while(k) {
                        k >>= 1;
                        i++;
                      }
                      return i - 1;
                    }
                    
                    int check(int n)    //checking if the number of element is a power of 2
                    {
                      return n > 0 && (n & (n - 1)) == 0;
                    }
                    
                    int reverse(int N, int n)    //calculating revers number
                    {
                      int j, p = 0;
                      for(j = 1; j <= log2(N); j++) {
                        if(n & (1 << (log2(N) - j)))
                          p |= 1 << (j - 1);
                      }
                      return p;
                    }
                    
                    void ordina(complex* f1, int N) //using the reverse order in the array
                    {
                      complex f2[MAX];
                      for(int i = 0; i < N; i++)
                        f2[i] = f1[reverse(N, i)];
                      for(int j = 0; j < N; j++)
                        f1[j] = f2[j];
                    }
                    
                    void transform(complex* f, int N) //
                    {
                      ordina(f, N);    //first: reverse order
                      complex *W;
                      W = (complex *)malloc(N / 2 * sizeof(complex));
                      W[1] = polar(1., -2. * M_PI / N);
                      W[0] = 1;
                      for(int i = 2; i < N / 2; i++)
                        W[i] = pow(W[1], i);
                      int n = 1;
                      int a = N / 2;
                      for(int j = 0; j < log2(N); j++) {
                        for(int i = 0; i < N; i++) {
                          if(!(i & n)) {
                            complex temp = f[i];
                            complex Temp = W[(i * a) % (n * a)] * f[i + n];
                            f[i] = temp + Temp;
                            f[i + n] = temp - Temp;
                          }
                        }
                        n *= 2;
                        a = a / 2;
                      }
                      free(W);
                    }
                    
                    void FFT(complex* f, int N, double d)
                    {
                      transform(f, N);
                      for(int i = 0; i < N; i++)
                        f[i] *= d; //multiplying by step
                    }
                    
                    int main()
                    {
                      int n;
                      
                          //  do {
                          //      cout << "specify array dimension (MUST be power of 2)" << endl;
                          //      cin >> n;
                          //  } while(!check(n));
                    
                    
                        
                      double d;
                      
                      // cout << "specify sampling step" << endl; //just write 1 in order to have the same results of matlab fft(.)
                      // cin >> d;
                      d = 1;
                    
                      complex vec[MAX];
                     
                      cout << "specify the array" << endl;
                            for(int i = 0; i < n; i++) {
                                cout << "specify element number: " << i << endl;
                                cin >> vec[i];
                            }
                     
                      FFT(vec, n, d);
                      cout << "...printing the FFT of the array specified" << endl;
                    
                      for(int j = 0; j < n; j++)
                        cout << vec[j] << endl;
                      
                      return 0;
                    }