/* (1) *********** cfour(data,n,isign) ************** (cifour is a version for integer data) input to cfour is an array of complex values either defined as a complex structure or a real array with real and imaginary parts alternating. cfour makes no assumptions about the data. isign is either + or - 1 depending on whether you are taking a transform or inverse transform. To get the correct amplitudes back from cfour after inverse transforming divide all values by the number of data points n. discrete Fourier transform functions based on the fast Fourier transform algorithm which computes the quantity : n-1 x(j)=sum x(k) exp( 2*pi*i*isign*k*j/n ) k=0 n must be a integral power of 2. beware of roundoff and overflow error if you use cifour. (2) ************cfftr(data,n)************ (cifftr is a version for integer data) ***********cfftri(data,m)************ (cifftri is a version for integer data) cfftr assumes the input data is pure real. To get the correct amplitudes back from cfftri divide all values by (n/2). computing discrete Fourier transform. and the transform has n/2+1 complex values starting with frequency zero and ending at the Nyquist frequency. parameters: n ... the number of samples, an integral power of 2 cfftri computes the inverse fast Fourier transform of a real time series. m/2 + 1 complex frequency values are input and m real timeseries are returned, where m is a power of two. the complex frequencies are stores in the array x, with real and imaginary parts alternating. To get correct amplitude, divide the output by n/2 (where n has been used in cfftr). (3) **********discrete_fft(data,n,isign)********* (real_dis_fft takes a array of real data) subroutine discrete_fft constructs the discrete fast Fourier transform of a time series using the Cooley-Tukey mixed Radix method. Algorithum is modified from Conte and de Boor, Elementary Numerical Analysis, page 281. Input: z1=pointer to complex array of data to be Fourier transformed Length of array should be n+1 n=number of data points in data isign=sign of transform; 1 for fft, -1 for inverse fft Output: z1=pointer to complex array Fourier transformed data note: input data array is over written Also if a data set is transformed and then inverse transformed, output amplitudes should be divided by the n ---------------------------------------- real_dis_fft(data,npts,isign) computes the discrete Fourier transform of a real input data array. Inputs: data=real array of data Note: must be dimensioned to 2*(npts+1) npts=number of data points in data isign=sign of Fourier transform 1 for transform -1 for inverse Outputs: data=array of transformed data */ #include #include #include "cmplx.h" cfour( data, n, isign ) int n, isign; float data[]; { int ip0, ip1, ip2, ip3, i3rev; int i1, i2a, i2b, i3; float sinth, wstpr, wstpi, wr, wi, tempr, tempi, theta; double sin(); ip0=2; ip3=ip0*n; i3rev=1; for( i3=1; i3<=ip3; i3+=ip0 ) { if( i3 < i3rev ) { tempr = data[i3-1]; tempi = data[i3]; data[i3-1] = data[i3rev-1]; data[i3] = data[i3rev]; data[i3rev-1] = tempr; data[i3rev] = tempi; } ip1 = ip3 / 2; do { if( i3rev <= ip1 ) break; i3rev -= ip1; ip1 /= 2; } while ( ip1 >= ip0 ); i3rev += ip1; } ip1 = ip0; while ( ip1 < ip3 ) { ip2 = ip1 * 2; theta = 6.283185/( (float) (isign*ip2/ip0) ); sinth = (float) sin( (double) (theta/2.) ); wstpr = -2.*sinth*sinth; wstpi = (float) sin( (double) theta ); wr = 1.; wi = 0.; for ( i1=1; i1<=ip1; i1+=ip0 ) { for ( i3=i1; i3= ip0 ); i3rev += ip1; } ip1 = ip0; while ( ip1 < ip3 ) { ip2 = ip1 * 2; theta = 6.283185/( (float) (isign*ip2/ip0) ); sinth = (float) sin( (double) (theta/2.) ); wstpr = -2.*sinth*sinth; wstpi = (float) sin( (double) theta ); wr = 1.; wi = 0.; for ( i1=1; i1<=ip1; i1+=ip0 ) { for ( i3=i1; i3 zin ; pointer3 -> zout */ angle=twopi/(float)(isign*now*after); omega.real=cos(angle); omega.imag=(-1.0*sin(angle)); arg.real=1.0; arg.imag=0.0; inter_fact2=after*before; /* array increment for zin */ inter_fact3=now*after; /* array increment for zout */ for(j=1;j<=now;j++) { for(ia=1;ia<=after;ia++) { array_end1=zin+(ia-1+after*(before-1+before*(now-1))); /* loop end criteria for zin */ for(ib=1,pointer3=zout+ia-1+after*(j-1),pointer1=zin+ia-1+after*before*(now-1);pointer1<=array_end1;ib++,pointer3+=inter_fact3,pointer1+=after) { value.real=pointer1->real; value.imag=pointer1->imag; array_end2=zin+(ia-1+after*(ib-1)); /* loop end criteria for zin */ for(pointer2=zin+(ia-1+after*(ib-1+before*(now-2)));pointer2>=array_end2;pointer2-=inter_fact2) { temp.real=value.real*arg.real-value.imag*arg.imag; temp.imag=value.real*arg.imag+value.imag*arg.real; value.real=temp.real+pointer2->real; value.imag=temp.imag+pointer2->imag; } pointer3->real=value.real; pointer3->imag=value.imag; } temp.real=arg.real*omega.real-arg.imag*omega.imag; arg.imag=arg.real*omega.imag+arg.imag*omega.real; arg.real=temp.real; } } } int real_dis_fft(data,npts,isign) float *data; int npts,isign; { int i; if(isign == 1) /* convert real array to complex array with zero imag */ { for(i=npts;i>=0;--i) { data[i*2]=data[i]; data[i*2+1]=0.0; } } else /* complete complex array using inherent symmetry */ { for(i=0;i