/***************************************************************************** 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 #include #include #include #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 ; }