3083 lines · 75.9 KB · C
RawDownload
/* Public domain FFT implementation in C by John Green */ #include <stdint.h>#include <stdlib.h>#include <math.h>#include "base.h" #ifndef M_PI#define M_PI 3.14159265358979323846#endif #define LOG2(n) (log(n) / log(2)) #define POW2(m) ((uint32_t) 1 << (m))       /* integer power of 2 for m<32 */ /* fft's with M bigger than this bust primary cache */#undef MCACHE#define MCACHE  (11 - (sizeof(SPFLOAT) / 8)) /* some math constants to 40 decimal places */#define MYPI      3.141592653589793238462643383279502884197   /* pi         */#define MYROOT2   1.414213562373095048801688724209698078569   /* sqrt(2)    */#define MYCOSPID8 0.9238795325112867561281831893967882868224  /* cos(pi/8)  */#define MYSINPID8 0.3826834323650897717284599840303988667613  /* sin(pi/8)  */ /****************************************************** routines to initialize tables used by fft routines ******************************************************/ static void fftCosInit(int M, SPFLOAT *Utbl){    /* Compute Utbl, the cosine table for ffts  */    /* of size (pow(2,M)/4 +1)                  */    /* INPUTS                                   */    /*   M = log2 of fft size                   */    /* OUTPUTS                                  */    /*   *Utbl = cosine table                   */    unsigned int fftN = POW2(M);    unsigned int i1;     Utbl[0] = 1.0;    for (i1 = 1; i1 < fftN/4; i1++)      Utbl[i1] = cos((2.0 * M_PI * (SPFLOAT)i1) / (SPFLOAT)fftN);    Utbl[fftN/4] = 0.0;} void fftBRInit(int M, int16_t *BRLow){    /* Compute BRLow, the bit reversed table for ffts */    /* of size pow(2,M/2 -1)                          */    /* INPUTS                                         */    /*   M = log2 of fft size                         */    /* OUTPUTS                                        */    /*   *BRLow = bit reversed counter table          */    int Mroot_1 = M / 2 - 1;    int Nroot_1 = POW2(Mroot_1);    int i1;    int bitsum;    int bitmask;    int bit;     for (i1 = 0; i1 < Nroot_1; i1++) {      bitsum = 0;      bitmask = 1;      for (bit = 1; bit <= Mroot_1; bitmask <<= 1, bit++)        if (i1 & bitmask)          bitsum = bitsum + (Nroot_1 >> bit);      BRLow[i1] = bitsum;    }} /****************** parts of ffts1 ******************/ static void bitrevR2(SPFLOAT *ioptr, int M, int16_t *BRLow){    /*** bit reverse and first radix 2 stage of forward or inverse fft ***/    SPFLOAT f0r;    SPFLOAT f0i;    SPFLOAT f1r;    SPFLOAT f1i;    SPFLOAT f2r;    SPFLOAT f2i;    SPFLOAT f3r;    SPFLOAT f3i;    SPFLOAT f4r;    SPFLOAT f4i;    SPFLOAT f5r;    SPFLOAT f5i;    SPFLOAT f6r;    SPFLOAT f6i;    SPFLOAT f7r;    SPFLOAT f7i;    SPFLOAT t0r;    SPFLOAT t0i;    SPFLOAT t1r;    SPFLOAT t1i;    SPFLOAT *p0r;    SPFLOAT *p1r;    SPFLOAT *IOP;    SPFLOAT *iolimit;    int Colstart;    int iCol;    unsigned int posA;    unsigned int posAi;    unsigned int posB;    unsigned int posBi;     const unsigned int Nrems2 = POW2((M + 3) / 2);    const unsigned int Nroot_1_ColInc = POW2(M) - Nrems2;    const unsigned int Nroot_1 = POW2(M / 2 - 1) - 1;    const unsigned int ColstartShift = (M + 1) / 2 + 1;     posA = POW2(M);               /* 1/2 of POW2(M) complexes */    posAi = posA + 1;    posB = posA + 2;    posBi = posB + 1;     iolimit = ioptr + Nrems2;    for (; ioptr < iolimit; ioptr += POW2(M / 2 + 1)) {      for (Colstart = Nroot_1; Colstart >= 0; Colstart--) {        iCol = Nroot_1;        p0r = ioptr + Nroot_1_ColInc + BRLow[Colstart] * 4;        IOP = ioptr + (Colstart << ColstartShift);        p1r = IOP + BRLow[iCol] * 4;        f0r = *(p0r);        f0i = *(p0r + 1);        f1r = *(p0r + posA);        f1i = *(p0r + posAi);        for (; iCol > Colstart;) {          f2r = *(p0r + 2);          f2i = *(p0r + (2 + 1));          f3r = *(p0r + posB);          f3i = *(p0r + posBi);          f4r = *(p1r);          f4i = *(p1r + 1);          f5r = *(p1r + posA);          f5i = *(p1r + posAi);          f6r = *(p1r + 2);          f6i = *(p1r + (2 + 1));          f7r = *(p1r + posB);          f7i = *(p1r + posBi);           t0r = f0r + f1r;          t0i = f0i + f1i;          f1r = f0r - f1r;          f1i = f0i - f1i;          t1r = f2r + f3r;          t1i = f2i + f3i;          f3r = f2r - f3r;          f3i = f2i - f3i;          f0r = f4r + f5r;          f0i = f4i + f5i;          f5r = f4r - f5r;          f5i = f4i - f5i;          f2r = f6r + f7r;          f2i = f6i + f7i;          f7r = f6r - f7r;          f7i = f6i - f7i;           *(p1r) = t0r;          *(p1r + 1) = t0i;          *(p1r + 2) = f1r;          *(p1r + (2 + 1)) = f1i;          *(p1r + posA) = t1r;          *(p1r + posAi) = t1i;          *(p1r + posB) = f3r;          *(p1r + posBi) = f3i;          *(p0r) = f0r;          *(p0r + 1) = f0i;          *(p0r + 2) = f5r;          *(p0r + (2 + 1)) = f5i;          *(p0r + posA) = f2r;          *(p0r + posAi) = f2i;          *(p0r + posB) = f7r;          *(p0r + posBi) = f7i;           p0r -= Nrems2;          f0r = *(p0r);          f0i = *(p0r + 1);          f1r = *(p0r + posA);          f1i = *(p0r + posAi);          iCol -= 1;          p1r = IOP + BRLow[iCol] * 4;        }        f2r = *(p0r + 2);        f2i = *(p0r + (2 + 1));        f3r = *(p0r + posB);        f3i = *(p0r + posBi);         t0r = f0r + f1r;        t0i = f0i + f1i;        f1r = f0r - f1r;        f1i = f0i - f1i;        t1r = f2r + f3r;        t1i = f2i + f3i;        f3r = f2r - f3r;        f3i = f2i - f3i;         *(p0r) = t0r;        *(p0r + 1) = t0i;        *(p0r + 2) = f1r;        *(p0r + (2 + 1)) = f1i;        *(p0r + posA) = t1r;        *(p0r + posAi) = t1i;        *(p0r + posB) = f3r;        *(p0r + posBi) = f3i;      }    }} static void fft2pt(SPFLOAT *ioptr){    /***   RADIX 2 fft      ***/    SPFLOAT f0r, f0i, f1r, f1i;    SPFLOAT t0r, t0i;     /* bit reversed load */    f0r = ioptr[0];    f0i = ioptr[1];    f1r = ioptr[2];    f1i = ioptr[3];     /* Butterflys           */    /*       f0   -       -       t0       f1   -  1 -  f1     */     t0r = f0r + f1r;    t0i = f0i + f1i;    f1r = f0r - f1r;    f1i = f0i - f1i;     /* store result */    ioptr[0] = t0r;    ioptr[1] = t0i;    ioptr[2] = f1r;    ioptr[3] = f1i;} static void fft4pt(SPFLOAT *ioptr){    /***   RADIX 4 fft      ***/    SPFLOAT f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i;    SPFLOAT t0r, t0i, t1r, t1i;     /* bit reversed load */    f0r = ioptr[0];    f0i = ioptr[1];    f1r = ioptr[4];    f1i = ioptr[5];    f2r = ioptr[2];    f2i = ioptr[3];    f3r = ioptr[6];    f3i = ioptr[7];     /* Butterflys           */    /*       f0   -       -       t0      -       -       f0       f1   -  1 -  f1      -       -       f1       f2   -       -       f2      -  1 -  f2       f3   -  1 -  t1      - -i -  f3     */     t0r = f0r + f1r;    t0i = f0i + f1i;    f1r = f0r - f1r;    f1i = f0i - f1i;     t1r = f2r - f3r;    t1i = f2i - f3i;    f2r = f2r + f3r;    f2i = f2i + f3i;     f0r = t0r + f2r;    f0i = t0i + f2i;    f2r = t0r - f2r;    f2i = t0i - f2i;     f3r = f1r - t1i;    f3i = f1i + t1r;    f1r = f1r + t1i;    f1i = f1i - t1r;     /* store result */    ioptr[0] = f0r;    ioptr[1] = f0i;    ioptr[2] = f1r;    ioptr[3] = f1i;    ioptr[4] = f2r;    ioptr[5] = f2i;    ioptr[6] = f3r;    ioptr[7] = f3i;} static void fft8pt(SPFLOAT *ioptr){    /***   RADIX 8 fft      ***/    SPFLOAT w0r = (SPFLOAT)(1.0 / MYROOT2);    /* cos(pi/4)   */    SPFLOAT f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i;    SPFLOAT f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i;    SPFLOAT t0r, t0i, t1r, t1i;    const SPFLOAT Two = 2.0;     /* bit reversed load */    f0r = ioptr[0];    f0i = ioptr[1];    f1r = ioptr[8];    f1i = ioptr[9];    f2r = ioptr[4];    f2i = ioptr[5];    f3r = ioptr[12];    f3i = ioptr[13];    f4r = ioptr[2];    f4i = ioptr[3];    f5r = ioptr[10];    f5i = ioptr[11];    f6r = ioptr[6];    f6i = ioptr[7];    f7r = ioptr[14];    f7i = ioptr[15];    /* Butterflys           */    /*       f0   -       -       t0      -       -       f0      -       -       f0       f1   -  1 -  f1      -       -       f1      -       -       f1       f2   -       -       f2      -  1 -  f2      -       -       f2       f3   -  1 -  t1      - -i -  f3      -       -       f3       f4   -       -       t0      -       -       f4      -  1 -  t0       f5   -  1 -  f5      -       -       f5      - w3 -  f4       f6   -       -       f6      -  1 -  f6      - -i -  t1       f7   -  1 -  t1      - -i -  f7      - iw3-  f6     */     t0r = f0r + f1r;    t0i = f0i + f1i;    f1r = f0r - f1r;    f1i = f0i - f1i;     t1r = f2r - f3r;    t1i = f2i - f3i;    f2r = f2r + f3r;    f2i = f2i + f3i;     f0r = t0r + f2r;    f0i = t0i + f2i;    f2r = t0r - f2r;    f2i = t0i - f2i;     f3r = f1r - t1i;    f3i = f1i + t1r;    f1r = f1r + t1i;    f1i = f1i - t1r;     t0r = f4r + f5r;    t0i = f4i + f5i;    f5r = f4r - f5r;    f5i = f4i - f5i;     t1r = f6r - f7r;    t1i = f6i - f7i;    f6r = f6r + f7r;    f6i = f6i + f7i;     f4r = t0r + f6r;    f4i = t0i + f6i;    f6r = t0r - f6r;    f6i = t0i - f6i;     f7r = f5r - t1i;    f7i = f5i + t1r;    f5r = f5r + t1i;    f5i = f5i - t1r;     t0r = f0r - f4r;    t0i = f0i - f4i;    f0r = f0r + f4r;    f0i = f0i + f4i;     t1r = f2r - f6i;    t1i = f2i + f6r;    f2r = f2r + f6i;    f2i = f2i - f6r;     f4r = f1r - f5r * w0r - f5i * w0r;    f4i = f1i + f5r * w0r - f5i * w0r;    f1r = f1r * Two - f4r;    f1i = f1i * Two - f4i;     f6r = f3r + f7r * w0r - f7i * w0r;    f6i = f3i + f7r * w0r + f7i * w0r;    f3r = f3r * Two - f6r;    f3i = f3i * Two - f6i;     /* store result */    ioptr[0] = f0r;    ioptr[1] = f0i;    ioptr[2] = f1r;    ioptr[3] = f1i;    ioptr[4] = f2r;    ioptr[5] = f2i;    ioptr[6] = f3r;    ioptr[7] = f3i;    ioptr[8] = t0r;    ioptr[9] = t0i;    ioptr[10] = f4r;    ioptr[11] = f4i;    ioptr[12] = t1r;    ioptr[13] = t1i;    ioptr[14] = f6r;    ioptr[15] = f6i;} static void bfR2(SPFLOAT *ioptr, int M, int NDiffU){    /*** 2nd radix 2 stage ***/    unsigned int pos;    unsigned int posi;    unsigned int pinc;    unsigned int pnext;    unsigned int NSameU;    unsigned int SameUCnt;     SPFLOAT *pstrt;    SPFLOAT *p0r, *p1r, *p2r, *p3r;     SPFLOAT f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i;    SPFLOAT f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i;     pinc = NDiffU * 2;            /* 2 floats per complex */    pnext = pinc * 4;    pos = 2;    posi = pos + 1;    NSameU = POW2(M) / 4 / NDiffU;        /* 4 Us at a time */    pstrt = ioptr;    p0r = pstrt;    p1r = pstrt + pinc;    p2r = p1r + pinc;    p3r = p2r + pinc;     /* Butterflys           */    /*       f0   -       -       f4       f1   -  1 -  f5       f2   -       -       f6       f3   -  1 -  f7     */    /* Butterflys           */    /*       f0   -       -       f4       f1   -  1 -  f5       f2   -       -       f6       f3   -  1 -  f7     */     for (SameUCnt = NSameU; SameUCnt > 0; SameUCnt--) {       f0r = *p0r;      f1r = *p1r;      f0i = *(p0r + 1);      f1i = *(p1r + 1);      f2r = *p2r;      f3r = *p3r;      f2i = *(p2r + 1);      f3i = *(p3r + 1);       f4r = f0r + f1r;      f4i = f0i + f1i;      f5r = f0r - f1r;      f5i = f0i - f1i;       f6r = f2r + f3r;      f6i = f2i + f3i;      f7r = f2r - f3r;      f7i = f2i - f3i;       *p0r = f4r;      *(p0r + 1) = f4i;      *p1r = f5r;      *(p1r + 1) = f5i;      *p2r = f6r;      *(p2r + 1) = f6i;      *p3r = f7r;      *(p3r + 1) = f7i;       f0r = *(p0r + pos);      f1i = *(p1r + posi);      f0i = *(p0r + posi);      f1r = *(p1r + pos);      f2r = *(p2r + pos);      f3i = *(p3r + posi);      f2i = *(p2r + posi);      f3r = *(p3r + pos);       f4r = f0r + f1i;      f4i = f0i - f1r;      f5r = f0r - f1i;      f5i = f0i + f1r; 

Lines 1–500 of 3083.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t