/* fftr.c * * FFT of Real Valued Sequence * * * * SYNOPSIS: * * double x[], sine[]; * int m; * * fftr( x, m, sine ); * * * * DESCRIPTION: * * Computes the (complex valued) discrete Fourier transform of * the real valued sequence x[]. The input sequence x[] contains * n = 2**m samples. The program fills array sine[k] with * n/4 + 1 values of sin( 2 PI k / n ). * * Data format for complex valued output is real part followed * by imaginary part. The output is developed in the input * array x[]. * * The algorithm takes advantage of the fact that the FFT of an * n point real sequence can be obtained from an n/2 point * complex FFT. * * A radix 2 FFT algorithm is used. * * Execution time on an LSI-11/23 with floating point chip * is 1.0 sec for n = 256. * * * * REFERENCE: * * E. Oran Brigham, The Fast Fourier Transform; * Prentice-Hall, Inc., 1974 * */ #include static short n0 = 0; static short n4 = 0; static short msav = 0; extern double PI; #ifdef ANSIPROT extern double sin ( double ); static int bitrv(int, int); #else double sin(); static int bitrv(); #endif fftr( x, m0, sine ) double x[]; int m0; double sine[]; { int th, nd, pth, nj, dth, m; int n, n2, j, k, l, r; double xr, xi, tr, ti, co, si; double a, b, c, d, bc, cs, bs, cc; double *p, *q; /* Array x assumed filled with real-valued data */ /* m0 = log2(n0) */ /* n0 is the number of real data samples */ if( m0 != msav ) { msav = m0; /* Find n0 = 2**m0 */ n0 = 1; for( j=0; j> 2; /* Calculate array of sines */ xr = 2.0 * PI / n0; for( j=0; j<=n4; j++ ) sine[j] = sin( j * xr ); } n = n0 >> 1; /* doing half length transform */ m = m0 - 1; /* fftr.c */ /* Complex Fourier Transform of n Complex Data Points */ /* First, bit reverse the input data */ for( k=0; k k ) { /* executed approx. n/2 times */ p = &x[2*k]; tr = *p++; ti = *p; q = &x[2*j+1]; *p = *q; *(--p) = *(--q); *q++ = tr; *q = ti; } } /* fftr.c */ /* Radix 2 Complex FFT */ n2 = n/2; nj = 1; pth = 1; dth = 0; th = 0; for( l=0; l= pth ) { th -= dth; co = -co; } else th += dth; nd = j; do { /* executed n/2 log2(n) times, total */ r = (nd << 1) + (nj << 1); p = &x[ r ]; xr = *p++; xi = *p; tr = xr * co + xi * si; ti = xi * co - xr * si; r = nd << 1; q = &x[ r ]; xr = *q++; xi = *q; *p = xi - ti; *(--p) = xr - tr; *q = xi + ti; *(--q) = xr + tr; nd += nj << 1; } while( nd < n ); } while( ++j < nj ); n2 >>= 1; dth = n2; pth = nj; nj <<= 1; } /* fftr.c */ /* Special trick algorithm */ /* converts to spectrum of real series */ /* Highest frequency term; add space to input array if wanted */ /* x[2*n] = x[0] - x[1]; x[2*n+1] = 0.0; */ /* Zero frequency term */ x[0] = x[0] + x[1]; x[1] = 0.0; n2 = n/2; for( j=1; j<=n2; j++ ) { /* executed n/2 times */ si = sine[j]; co = sine[ n4 - j ]; p = &x[ 2*j ]; xr = *p++; xi = *p; q = &x[ 2*(n-j) ]; tr = *q++; ti = *q; a = xr + tr; b = xi + ti; c = xr - tr; d = xi - ti; bc = b * co; cs = c * si; bs = b * si; cc = c * co; *p = ( d - bs - cc )/2.0; *(--p) = ( a + bc - cs )/2.0; *q = -( d + bs + cc )/2.0; *(--q) = ( a - bc + cs )/2.0; } return(0); } /* fftr.c */ /* Bit reverser */ int bitrv( j, m ) int j, m; { register int j1, ans; short k; ans = 0; j1 = j; for( k=0; k>= 1; } return( ans ); }