/////////// CZT Chirp Z-transform Source Code //////////////////////////////// /// /// gcc -O3 -Wall -W -Wextra -o czt czt.c -lm // // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #undef PI #define PI 3.1415926535897932384626433832795L // 円周率(π) #define Rotor(a) (double complex)( cos(a) + I*sin(a) ) #define COMPLEX(a,b) (double complex)( (a) + I*(b) ) enum { DFT, IDFT }; enum { FFT=DFT, IFFT=IDFT }; enum { CZT=DFT, ICZT=IDFT }; //////////////////////////////////////////////////////////////////////////////// //// //// CZT Chirp Z-transform, Bluestein's algorithm //// //// Structure to store data for CZT Chirp Z-transform //// samples : number of actual data //// samples_out: Actual data count (for output, same as input one) //// samples_fft: Number of data used in CZT conversion (power of 2) //// flag_fft : flag indicating if "samples" is a power of 2 //// w : The number of weight data elements is (samples) //// v : The number of impulse response data elements is (samples_fft) //// typedef struct CZT_CONTROL { int samples; // 標本点の数 int samples_out; // 出力する標本点の数 int samples_fft; // 2の整数乗値:flag_fft?samples:2*get_czt_size(samples) int flag_fft; // 直接FFTを実行できるサイズかの判定 double complex *w; // 重みデータ 要素数は(samples) double complex *v; // インパルス応答データ 要素数は(samples_fft) } CZT_CONTROL; //////////////////////////////////////////////////////////////////////////////// //// checks if the argument is a power of 2 ( Returns 1 if it is a power of 2 ) //// int ft_size_check( int n ){ if( n<4 ) return 0; for(int e=n;e>1;e>>=1 ) if( e&1 ) return 0; return 1; } //////////////////////////////////////////////////////////////////////////////// //// A function that returns the smallest power of 2 that is greater than or //// equal to twice its argument //// int get_czt_size( int n ){ if( ft_size_check(n) ) return n; int a=1, b= n<<1; for( a=1; a>1; k>(i^=k); k>>=1 ); if( j>2; k>(ir^=k); k>>=1 ); for(int j=i; j- (a + b) ->- a c[b] = temp * W; // b ->- (a-b)*W ->- b } } } double reciprocal = 1./elements; if(flag==IFFT)for(int i=0; iw, *v=a->v; // as alias for(int i=n;i v[i] } < n v[i] = COMPLEX( c, s ); v[tail-i] = COMPLEX( c, s );// v[tail] was keeded as dummy area } fft( v, samples_fft, FFT ); return a; } //////////////////////////////////////////////////////////////////////////////// //// Chirp Z-transform routine for fast Fourier transform of arbitrary size data //// Argument structure is the same as the FFT routine //// void czt( double complex *c, int n, int flag ){ if( ft_size_check(n) ) return fft( c, n, flag ); CZT_CONTROL *czt = NULL; double complex *tmp = NULL; // Temporary work area used by CZT if( !(czt = GenerateCZT_CONTROL( n ) ) ) goto GOOD_BY; int nx = czt->samples_fft, dc_size = sizeof(double complex); double complex *w = czt->w; double complex *v = czt->v; if( !(tmp = (double complex*)calloc( nx, dc_size )) ) goto GOOD_BY; // Division is slow, so we replace it with multiplication using the reciprocal. double m = 1.0/n; // a*m, same as a/n. if m is m = 1.0/n; //for(int i=n;i void argumentAnalysis(int argc, char *argv[]){ //, char **iname, char **oname){ int i, st=1; for( i=1; i0 && p[i]!='\\' && p[i]!='/'; i-- );; if(i) i++; fprintf( stderr, "\nusage: %s %s\n\n", &p[i], op ); fprintf( stderr, "\t-N: The number of data.\n" ); fprintf( stderr, "\t-v: verbose mode.\n" ); fprintf( stderr, "\t-q: quiet mode.\n" ); fprintf( stderr, "\t-h: This option shows only this message.\n" ); exit(st); } int main(int argc, char *argv[]){ argumentAnalysis( argc, argv ); int data = NumberOfData; double complex *base= (double complex*)malloc( (3*data)*sizeof(double complex) ); if( !base ) return 1; double complex *c1 = &base[0]; double complex *c2 = &base[data]; double complex *c3 = &base[data+data]; for(int i=0;i 0.0000001 ) is_same = 0; if( fabs(cimag(c1[i]) - cimag(c3[i])) > 0.0000001 ) is_same = 0; } char *msg = "The result of comparing the original data and"; printf( "\n\n %s the inverse transformed data\n is %s.", msg, is_same ? "Matched" : "there was a difference" ); if(verbose) printf("\t\t\t ( % 6d % 6d )", data, get_czt_size(data) ); printf("\n\n"); free(base); return EXIT_SUCCESS; }