00001 #if !defined( _CFFT_H_INC__ )
00002 #define _CFFT_H_INC__ 1
00003 #include <math.h>
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,
00032 double scalef1 = 0.5, double scalef2 = 1.0,
00033 double scalei1 = 1.0, double scalei2 = 1.0
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 };
00051
00052
00053
00054
00055
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
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
00099
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);
00108
00109 }
00110 }
00111 }
00112
00113
00114
00115
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
00128
00129
00130
00131 template <class CPLX>
00132 void
00133 cfft<CPLX>::hermitian(CPLX *buf)
00134 {
00135 int i,j;
00136 if( N <= 2 ) return;
00137 i = (N>>1)-1;
00138 j = i+2;
00139 while( i > 0 ){
00140 buf[j] = conj(buf[i]);
00141 --i;
00142 ++j;
00143 }
00144 }
00145
00146
00147
00148
00149
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];
00162
00163 if( log2N == 0 ){
00164 s = sp[1];
00165 buf[0] = buf[0] * s;
00166 return;
00167 }
00168
00169
00170
00171
00172
00173 k = N>>1;
00174
00175 if( log2N == 1 )
00176 s *= sp[1];
00177
00178 buf2 = buf + k;
00179 for( i = 0; i < k; ++i ){
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;
00186
00187 k>>=1;
00188 bufe = buf+N;
00189 for( ; k; k>>=1 ){
00190 if( k == 1 ){
00191 s *= sp[1];
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];
00199 }
00200 buf2 = buf0+k;
00201 for( i = 0; i < k; ++i ){
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
00211 for( i = 0; i < N; ++i ){
00212 j = bitrev[i];
00213 if( i <= j ) continue;
00214 z1 = buf[i];
00215 buf[i] = buf[j];
00216 buf[j] = z1;
00217 }
00218 }
00220 }
00221 #endif