Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

cplxfft.h

Go to the documentation of this file.
00001 #if !defined( _CFFT_H_INC__ )
00002 #define _CFFT_H_INC__ 1
00003 #include <math.h>  // for sin and cos
00004 namespace SPUC {
00007 //
00022 template <class CPLX> class cfft {
00023     int N, log2N;               
00024     CPLX *w;                    
00025     int *bitrev;                
00026     double fscales[2];  
00027     double iscales[2];  
00028     void fft_func( CPLX *buf, int iflag );
00029         
00030 public:
00031     cfft( int size,             // size is power of 2
00032                   double scalef1 = 0.5, double scalef2 = 1.0,   // fwd transform scalings
00033                   double scalei1 = 1.0, double scalei2 = 1.0    // rev xform
00034                   );
00035     ~cfft();
00036     inline void fft(CPLX *buf)          
00037                 {
00038                         fft_func( buf, 0 );
00039                 }
00040     inline void ifft(CPLX *buf)         
00041                 {
00042                         fft_func( buf, 1 );
00043                 }
00044     inline int length() const { return N; }
00047     void hermitian( CPLX *buf );
00048 
00049 }; // class cfft
00051 /*
00052  * constructor takes an int, power-of-2.
00053  * scalef1,scalef2, are the post-pass and post-transform
00054  * scalings for the forward transform; scalei1 and scalei2 are
00055  * the same for the inverse transform.
00056  */
00057 template <class CPLX>
00058 cfft<CPLX>::cfft( int size, double scalef1, double scalef2,
00059                   double scalei1, double scalei2 )
00060 {
00061     int i,j,k;
00062     double t;
00063 
00064     fscales[0] = scalef1;
00065     fscales[1] = scalef2;
00066     iscales[0] = scalei1;
00067     iscales[1] = scalei2;
00068 
00069     for( k = 0; ; ++k ){
00070         if( (1<<k) == size) break;
00071         if( k==18 || (1<<k) >size )
00072             throw "cfft: size not power of 2";
00073     }
00074     N = 1<<k;
00075     log2N = k;
00076 
00077     bitrev = new int [N];
00078 
00079     if( k > 0 )
00080         w = new CPLX[ N>>1 ];
00081     else
00082         w = NULL;
00083     if( bitrev == NULL || ((k>0) && w == NULL) )
00084         throw "cfft: out of memory";
00085         
00086     //
00087     // do bit-rev table
00088     //
00089     bitrev[0] = 0;
00090 
00091     for( j = 1; j < N; j<<=1 ){
00092         for( i = 0; i < j ; ++i ){
00093             bitrev[i] <<= 1;
00094             bitrev[i+j] = bitrev[i]+1;
00095         }
00096     }
00097     //
00098     // prepare the cos/sin table. This is bit-reversed, and goes
00099     // like this: 0, 90, 45, 135, 22.5 ...  for N/2 entries.
00100     //
00101     if( k > 0 ){
00102         CPLX ww;
00103         k = (1<<(k-1));
00104         for( i = 0; i < k; ++i ){
00105             t = double(bitrev[i<<1]) * PI /double(k);
00106             ww = CPLX( cos(t), sin(t));
00107             w[i] = conj(ww);            // force limiting of imag part if applic.
00108             //cout << w[i] << "\n";
00109         }
00110     }
00111 }
00112 
00113 
00114 /*
00115  * destructor frees the memory
00116  */
00117 template <class CPLX>
00118 cfft<CPLX>::~cfft()
00119 {
00120     delete [] bitrev;
00121     if( w!= NULL )
00122         delete [] w;
00123 }
00124 
00125 
00126 /*
00127  * hermitian() assumes the array has been filled in with values
00128  * up to the center and including the center point. It reflects these
00129  * conjugate-wise into the last half.
00130  */
00131 template <class CPLX>
00132 void
00133 cfft<CPLX>::hermitian(CPLX *buf)
00134 {
00135     int i,j;
00136     if( N <= 2 ) return;        // nothing to do
00137     i = (N>>1)-1;                       // input
00138     j = i+2;                            // output
00139     while( i > 0 ){
00140         buf[j] = conj(buf[i]);
00141         --i;
00142         ++j;
00143     }
00144 }
00145 
00146         
00147 /*
00148  * cfft::fft_func(buf,0) performs a forward fft on the data in the buffer specified.
00149  * cfft::fft_func(buf,1) performs an inverse fft on the data in the buffer specified.
00150  */
00151 template <class CPLX>
00152 void
00153 cfft<CPLX>::fft_func( CPLX *buf, int iflag )
00154 {
00155     int i,j,k;
00156     CPLX *buf0,*buf2,*bufe;
00157     CPLX z1,z2,zw;
00158     double *sp,s;
00159 
00160     sp = iflag ? iscales : fscales;
00161     s = sp[0];          // per-pass scale
00162 
00163     if( log2N == 0 ){           // only 1 element !
00164         s = sp[1];
00165         buf[0] = buf[0] * s;    // final scale only
00166         return;
00167     }
00168     //
00169     // first pass:
00170     //  1st element  = sum of 1st & middle, middle element = diff.
00171     // repeat N/2 times.
00172 
00173     k = N>>1;
00174 
00175     if( log2N == 1 )
00176         s *= sp[1];     // final scale
00177         
00178     buf2 = buf + k;
00179     for( i = 0; i < k; ++i ){           // first pass is faster
00180         z1 = buf[i] + buf2[i];
00181         z2 = buf[i] - buf2[i];
00182         buf[i] = z1 * s;
00183         buf2[i] = z2 * s;
00184     }
00185     if( log2N == 1 ) return;    // only 2!
00186 
00187     k>>=1;                              // k is N/4 now
00188     bufe = buf+N;               // past end
00189     for( ; k; k>>=1 ){
00190         if( k == 1 ){   // last pass - include final scale 
00191             s *= sp[1]; // final scale
00192         }
00193         buf0=buf;
00194         for( j = 0; buf0<bufe; ++j ){
00195             if( iflag ){
00196                 zw = conj(w[j]);
00197             }else{
00198                 zw = w[j];              /* get w-factor */
00199             }
00200             buf2 = buf0+k;
00201             for( i = 0; i < k; ++i ){   // a butterfly
00202                 z1 = zw * buf2[i];
00203                 z2 = buf0[i] + z1;
00204                 buf2[i] = (buf0[i] - z1)*s;
00205                 buf0[i] = z2 * s;
00206             }
00207             buf0 += (k<<1);
00208         }
00209     }
00210     // bitrev the sucker 
00211     for( i = 0; i < N; ++i ){
00212         j = bitrev[i];
00213         if( i <= j ) continue;          // don't do these
00214         z1 = buf[i];
00215         buf[i] = buf[j];
00216         buf[j] = z1;
00217     }
00218 }
00220 }
00221 #endif

Generated on Fri Sep 16 11:02:26 2005 for spuc by  doxygen 1.4.4