This page is optimized for mobile devices, if you would prefer the desktop version just click here

0.8 Appendix 1 - simple ffts

This Appendix contains source code listings corresponding to the simple implementations in Implementation details .

#include <complex.h>#include <stdio.h>#include <stdlib.h>#include <math.h>  typedef complex float data_t;  #define W(N,k) (cexp(-2.0f * M_PI * I * (float)k / (float)N))  void ditfft2(data_t *in, data_t *out, int stride, int N) {if(N == 2) { out[0]   = in[0] + in[stride]; out[N/2] = in[0] - in[stride]; }else{ditfft2(in, out, stride << 1, N >> 1); ditfft2(in+stride, out+N/2, stride << 1, N >> 1);{  /* k=0 -> no multiplication */ data_t Ek = out[0]; data_t Ok = out[N/2]; out[0]   = Ek + Ok; out[N/2] = Ek - Ok; }  int k;for(k=1;k<N/2;k++) { data_t Ek = out[k]; data_t Ok = out[(k+N/2)]; out[k]        = Ek + W(N,k) * Ok; out[(k+N/2) ] = Ek - W(N,k) * Ok; }} }
Simple radix-2 FFT
#include <complex.h>#include <stdio.h>#include <stdlib.h>#include <math.h>  typedef complex float data_t;  #define W(N,k) (cexp(-2.0f * M_PI * I * (float)k / (float)N))  void splitfft(data_t *in, data_t *out, int stride, int N) {if(N == 1) { out[0] = in[0];}else if(N == 2) { out[0]   = in[0] + in[stride]; out[N/2] = in[0] - in[stride]; }else{splitfft(in, out, stride << 1, N >> 1); splitfft(in+stride, out+N/2, stride << 2, N >> 2);   splitfft(in+3*stride, out+3*N/4, stride << 2, N >> 2);{ data_t Uk  = out[0]; data_t Zk  = out[0+N/2]; data_t Uk2 = out[0+N/4]; data_t Zdk = out[0+3*N/4]; out[0]       = Uk  + (Zk + Zdk); out[0+N/2]   = Uk  - (Zk + Zdk); out[0+N/4]   = Uk2 - I*(Zk - Zdk); out[0+3*N/4] = Uk2 + I*(Zk - Zdk); }int k; for(k=1;k<N/4;k++) { data_t Uk  = out[k]; data_t Zk  = out[k+N/2]; data_t Uk2 = out[k+N/4]; data_t Zdk = out[k+3*N/4]; out[k]       = Uk  + (W(N,k)*Zk + W(N,3*k)*Zdk); out[k+N/2]   = Uk  - (W(N,k)*Zk + W(N,3*k)*Zdk); out[k+N/4]   = Uk2 - I*(W(N,k)*Zk - W(N,3*k)*Zdk); out[k+3*N/4] = Uk2 + I*(W(N,k)*Zk - W(N,3*k)*Zdk); }} }
Simple split-radix FFT
#include <complex.h>#include <stdio.h>#include <stdlib.h>#include <math.h>  typedef complex float data_t;  #define W(N,k) (cexp(-2.0f * M_PI * I * (float)k / (float)N))  void conjfft(data_t *base, int TN,data_t *in, data_t *out, int stride, int N) { if(N == 1) {if(in < base) in += TN; out[0] = in[0];}else if(N == 2) { data_t *i0 = in, *i1 = in + stride;if(i0 < base) i0 += TN; if(i1 < base) i1 += TN; out[0]   = *i0 + *i1; out[N/2] = *i0 - *i1; }else{conjfft(base, TN, in, out, stride << 1, N >> 1); conjfft(base, TN, in+stride, out+N/2, stride << 2, N >> 2);   conjfft(base, TN, in-stride, out+3*N/4, stride << 2, N >> 2);{ data_t Uk  = out[0]; data_t Zk  = out[0+N/2]; data_t Uk2 = out[0+N/4]; data_t Zdk = out[0+3*N/4]; out[0]       = Uk  + (Zk + Zdk); out[0+N/2]   = Uk  - (Zk + Zdk); out[0+N/4]   = Uk2 - I*(Zk - Zdk); out[0+3*N/4] = Uk2 + I*(Zk - Zdk); }int k; for(k=1;k<N/4;k++) { data_t Uk  = out[k]; data_t Zk  = out[k+N/2]; data_t Uk2 = out[k+N/4]; data_t Zdk = out[k+3*N/4]; data_t w = W(N,k);out[k]       = Uk  + (w*Zk + conj(w)*Zdk);out[k+N/2]   = Uk  - (w*Zk + conj(w)*Zdk);out[k+N/4]   = Uk2 - I*(w*Zk - conj(w)*Zdk);out[k+3*N/4] = Uk2 + I*(w*Zk - conj(w)*Zdk);} }}
Simple conjugate-pair FFT
#include <stdio.h>#include <math.h>#include <stdlib.h>#include <complex.h>  typedef complex float data_t;  #define W(N,k) (cexp(-2.0f * M_PI * I * (float)(k) / (float)(N)))  floats(int n, int k) {   if (n <= 4) return 1.0f;    int k4 = k % (n/4);    if (k4 <= n/8) return (s(n/4,k4) * cosf(2.0f * M_PI * (float)k4 / (float)n));   return (s(n/4,k4) * sinf(2.0f * M_PI * (float)k4 / (float)n));}  void tangentfft8(data_t *base, int TN, data_t *in, data_t *out, int stride, int N) {   if(N == 1) {if(in < base) in += TN; out[0] = in[0];  }else if(N == 2) { data_t *i0 = in, *i1 = in + stride;if(i0 < base) i0 += TN; if(i1 < base) i1 += TN; out[0]   = *i0 + *i1; out[N/2] = *i0 - *i1;   }else if(N == 4) {    tangentfft8(base, TN, in, out, stride << 1, N >> 1);     tangentfft8(base, TN, in+stride, out+2, stride << 1, N >> 1);      data_t temp1 = out[0] + out[2];     data_t temp2 = out[0] - out[2];    out[0] = temp1;    out[2] = temp2;    temp1 = out[1] - I*out[3];     temp2 = out[1] + I*out[3];    out[1] = temp1;    out[3] = temp2;    }else{    tangentfft8(base, TN, in, out, stride << 2, N >> 2);     tangentfft8(base, TN, in+(stride*2), out+2*N/8, stride << 3, N >> 3);     tangentfft8(base, TN, in-(stride*2), out+3*N/8, stride << 3, N >> 3);     tangentfft8(base, TN, in+(stride), out+4*N/8, stride << 2, N >> 2);     tangentfft8(base, TN, in-(stride), out+6*N/8, stride << 2, N >> 2); int k;    for(k=0;k<N/8;k++) {       float s4 = s(N/4,k)/s(N,k);      float s4_n8 = s(N/4,k+N/8)/s(N,k+N/8);  float s2     = s(N/2,k)/s(N,k); float s2_n8 = s(N/2,k+N/8)/s(N,k+N/8);     data_t w0 = W(N,k)*s4;data_t w1 = W(N,k+N/8)*s4_n8; data_t w2 = W(N,2*k)*s(N/8,k)/s(N/2,k);        data_t zk_p   = w0       * out[k+4*N/8];       data_t zk_n   = conj(w0) * out[k+6*N/8];       data_t zk2_p  = w1       * out[k+5*N/8];       data_t zk2_n  = conj(w1) * out[k+7*N/8];       data_t uk     = out[k]                  * s4;       data_t uk2    = out[k+N/8]              * s4_n8;       data_t yk_p   = w2       * out[k+2*N/8];       data_t yk_n   = conj(w2) * out[k+3*N/8];data_t y0 = (yk_p + yk_n)*s2; data_t y1 = (yk_p - yk_n)*I*s2_n2;        out[k]       = uk + y0 + (zk_p + zk_n);       out[k+4*N/8] = uk + y0 - (zk_p + zk_n);       out[k+2*N/8] = uk - y0 - I*(zk_p - zk_n);       out[k+6*N/8] = uk - y0 + I*(zk_p - zk_n);       out[k+1*N/8] = uk2 - y1 +   (zk2_p + zk2_n);       out[k+3*N/8] = uk2 + y1 - I*(zk2_p - zk2_n);       out[k+5*N/8] = uk2 - y1 -   (zk2_p + zk2_n);       out[k+7*N/8] = uk2 + y1 + I*(zk2_p - zk2_n);     }  }  }  void tangentfft4(data_t *base, int TN,  data_t *in, data_t *out, int stride, int N) {if(N == 1) { if(in < base) in += TN; out[0] = in[0];}else if(N == 2) { data_t *i0 = in, *i1 = in + stride;if(i0 < base) i0 += TN; if(i1 < base) i1 += TN; out[0]   = *i0 + *i1; out[N/2] = *i0 - *i1; }else{tangentfft4(base, TN, in, out, stride << 1, N >> 1); tangentfft8(base, TN, in+stride, out+N/2, stride << 2, N >> 2);   tangentfft8(base, TN, in-stride, out+3*N/4, stride << 2, N >> 2);{ data_t Uk  = out[0]; data_t Zk  = out[0+N/2]; data_t Uk2 = out[0+N/4]; data_t Zdk = out[0+3*N/4]; out[0]       = Uk  + (Zk + Zdk); out[0+N/2]   = Uk  - (Zk + Zdk); out[0+N/4]   = Uk2 - I*(Zk - Zdk); out[0+3*N/4] = Uk2 + I*(Zk - Zdk); }int k; for(k=1;k<N/4;k++) { data_t Uk  = out[k]; data_t Zk  = out[k+N/2]; data_t Uk2 = out[k+N/4]; data_t Zdk = out[k+3*N/4]; data_t w = W(N,k)*s(N/4,k);out[k]       = Uk  + (w*Zk + conj(w)*Zdk);out[k+N/2]   = Uk  - (w*Zk + conj(w)*Zdk);out[k+N/4]   = Uk2 - I*(w*Zk - conj(w)*Zdk);out[k+3*N/4] = Uk2 + I*(w*Zk - conj(w)*Zdk);} }}
Simple tangent FFT
<< Chapter < Page Page > Chapter >>

Read also:

OpenStax, Computing the fast fourier transform on simd microprocessors. OpenStax CNX. Jul 15, 2012 Download for free at http://cnx.org/content/col11438/1.2
Google Play and the Google Play logo are trademarks of Google Inc.
Jobilize.com uses cookies to ensure that you get the best experience. By continuing to use Jobilize.com web-site, you agree to the Terms of Use and Privacy Policy.