/*****************************************************************************
Major portions of this software are copyrighted by the Medical College
of Wisconsin, 1994-2000, and are released under the Gnu General Public
License, Version 2. See the file README.Copyright for details.
******************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#undef PI
#define PI (3.141592653589793238462643)
typedef struct complex { float r , i ; } complex ;
static void csfft_print( int mode , int idim , complex * xc ) ;
static void csfft_trigconsts( int idim ) ;
int main( int argc , char * argv[] )
{
int len , ii ;
complex * cx ;
if( argc < 2 ){printf("Usage: fftprint len\n");exit(0);}
len = strtol( argv[1] , NULL , 10 ) ;
if( len < 4 ){ fprintf(stderr,"Illegal length\n"); exit(1); }
ii = 2 ; do{ ii *= 2 ; } while( ii < len ) ;
if( ii != len ){ fprintf(stderr,"Illegal length\n"); exit(1); }
cx = (complex *) malloc( sizeof(complex) * len ) ;
csfft_print(-1,len,cx) ;
exit(0) ;
}
static complex * csplus = NULL , * csminus = NULL ; /* trig consts */
static int nold = -666 ;
static void csfft_trigconsts( int idim ) /* internal function */
{
register unsigned int m, n, i0, i1, i2, i3, k;
register complex *r0, *csp;
register float co, si, f0, f1, f2, f3, f4;
double al;
if( idim == nold ) return ;
if( idim > nold ){
if( csplus != NULL ){ free(csplus) ; free(csminus) ; }
csplus = (complex *) malloc( sizeof(complex) * idim ) ;
csminus = (complex *) malloc( sizeof(complex) * idim ) ;
if( csplus == NULL || csminus == NULL ){
fprintf(stderr,"\n*** csfft cannot malloc space! ***\n"); exit(1) ;
}
}
nold = n = idim ;
f1 = 1.0 ; /* csplus init */
m = 1; k = 0;
while (n > m) {
i3 = m << 1;
f2 = m; al = f1*PI/f2;
co = cos(al); si = sin(al);
(csplus + k)->r = 1.;
(csplus + k)->i = 0.;
for (i0=0; i0 < m; i0++) {
k++;
csp = csplus + k; r0 = csp - 1;
csp->r = r0->r * co - r0->i * si;
csp->i = r0->i * co + r0->r * si;
}
m = i3;
}
f1 = -1.0 ; /* csminus init */
m = 1; k = 0;
while (n > m) {
i3 = m << 1;
f2 = m; al = f1*PI/f2;
co = cos(al); si = sin(al);
(csminus + k)->r = 1.;
(csminus + k)->i = 0.;
for (i0=0; i0 < m; i0++) {
k++;
csp = csminus + k; r0 = csp - 1;
csp->r = r0->r * co - r0->i * si;
csp->i = r0->i * co + r0->r * si;
}
m = i3;
}
return ;
}
/*****************************************************************************
The routine that generates a C function for a completely unrolled FFT.
Basically the same as csfft_cox() with print statements replacing
the actual computations.
The resulting code also needs the csfft_trigconsts() function above.
******************************************************************************/
#define EPS 1.e-5 /* set EPS to 0 to disable this option */
void csfft_print( int mode , int idim , complex * xc )
{
register unsigned int m, n, i0, i1, i2, i3, k;
register complex *r0, *r1, *csp;
register float co, si, f0, f1, f2, f3, f4;
double al;
csfft_trigconsts( idim ) ;
csp = csplus ;
n = idim;
i2 = idim >> 1;
i1 = 0;
/*-- function header --*/
printf( "/**************************************/\n"
"/* FFT routine unrolled of length %3d */\n"
"\n"
"void fft%d( int mode , complex * xc )\n"
"{\n"
" register complex * csp , * xcx=xc;\n"
" register float f1,f2,f3,f4 ;\n"
"\n"
" /** perhaps initialize **/\n"
"\n"
" if( nold != %d ) csfft_trigconsts( %d ) ;\n"
"\n"
" csp = (mode > 0) ? csplus : csminus ; /* choose const array */\n"
"\n"
" /** data swapping part **/\n" ,
idim,idim,idim,idim ) ;
/*-- swap some data elements --*/
for (i0=0; i0 < n; i0 ++) {
if ( i1 > i0 ) {
printf("\n") ;
printf(" f1 = xcx[%d].r ; f2 = xcx[%d].i ;\n",i0,i0) ;
printf(" xcx[%d].r = xcx[%d].r ; xcx[%d].i = xcx[%d].i ;\n" , i0,i1,i0,i1) ;
printf(" xcx[%d].r = f1 ; xcx[%d].i = f2 ;\n" , i1,i1) ;
}
m = i2;
while ( m && !(i1 < m) ) {
i1 -= m;
m >>= 1;
}
i1 += m;
}
/*-- the actual computations --*/
printf("\n /** butterflying part **/\n") ;
m = 1;
k = 0;
while (n > m) {
i3 = m << 1;
for (i0=0; i0 < m; i0 ++) {
for (i1=i0; i1 < n; i1 += i3) {
printf("\n") ;
if( csp[k].r == 1.0 ){
printf(" f1 = xcx[%d].r ; f3 = xcx[%d].i ; /* cos=1 sin=0 */\n", i1+m,i1+m ) ;
} else if( fabs(csp[k].r) < EPS ){
printf(" f1 = - xcx[%d].i * csp[%d].i ; /* cos=0 twiddles */\n", i1+m,k ) ;
printf(" f3 = xcx[%d].r * csp[%d].i ;\n", i1+m,k ) ;
} else {
printf(" f1 = xcx[%d].r * csp[%d].r - xcx[%d].i * csp[%d].i ; /* twiddles */\n",
i1+m,k , i1+m,k ) ;
printf(" f3 = xcx[%d].r * csp[%d].i + xcx[%d].i * csp[%d].r ;\n",
i1+m,k , i1+m,k ) ;
}
printf(" f2 = xcx[%d].r ; f4 = xcx[%d].i ;\n" , i1,i1 ) ;
printf(" xcx[%d].r = f2-f1 ; xcx[%d].i = f4-f3 ;\n",i1+m,i1+m) ;
printf(" xcx[%d].r = f2+f1 ; xcx[%d].i = f4+f3 ;\n",i1,i1) ;
}
k++;
}
m = i3;
}
printf("\n return ;\n}\n") ;
return ;
}
syntax highlighted by Code2HTML, v. 0.9.1