#include "mrilib.h"
/*--------------------------------------------------------------------
This is the older FFT routine by AJ and RWC,
from which the routines in csfft.c were derived.
----------------------------------------------------------------------*/
static complex * csplus = NULL , * csminus = NULL ; /* trig consts */
static int nold = -666 ;
#undef PI
#define PI (3.141592653589793238462643) /* should be close enough */
static void csfft_trigconsts( int idim )
{
register unsigned int m, n, i0, i1, i2, i3, k;
register complex *r0, *csp;
register float co, si, f0, f1, f2, f3, f4;
double al;
if( idim == nold ) return ;
if( idim > nold ){
if( csplus != NULL ){ free(csplus) ; free(csminus) ; }
csplus = (complex *) malloc( sizeof(complex) * idim ) ;
csminus = (complex *) malloc( sizeof(complex) * idim ) ;
if( csplus == NULL || csminus == NULL ){
fprintf(stderr,"\n*** fft cannot malloc space! ***\n"); exit(-1) ;
}
}
nold = n = idim ;
f1 = 1.0 ; /* csplus init */
m = 1;
k = 0;
while (n > m) {
i3 = m << 1;
f2 = m;
al = f1*PI/f2;
co = cos(al);
si = sin(al);
(csplus + k)->r = 1.;
(csplus + k)->i = 0.;
for (i0=0; i0 < m; i0++) {
k++;
csp = csplus + k;
r0 = csp - 1;
csp->r = r0->r * co - r0->i * si;
csp->i = r0->i * co + r0->r * si;
}
m = i3;
}
f1 = -1.0 ; /* csminus init */
m = 1;
k = 0;
while (n > m) {
i3 = m << 1;
f2 = m;
al = f1*PI/f2;
co = cos(al);
si = sin(al);
(csminus + k)->r = 1.;
(csminus + k)->i = 0.;
for (i0=0; i0 < m; i0++) {
k++;
csp = csminus + k;
r0 = csp - 1;
csp->r = r0->r * co - r0->i * si;
csp->i = r0->i * co + r0->r * si;
}
m = i3;
}
return ;
}
/*--------------------------------------------------------------------
Complex-to-complex FFT in place:
mode = -1 or +1 (NO SCALING ON INVERSE!)
idim = dimension (power of 2)
xc = input/output array
Automagically re-initializes itself when idim changes from
previous call. By AJJesmanowicz, modified by RWCox.
----------------------------------------------------------------------*/
void csfft( int mode , int idim , complex * xc )
{
register unsigned int m, n, i0, i1, i2, i3, k;
register complex *r0, *r1, *csp;
register float co, si, f0, f1, f2, f3, f4;
double al;
/** perhaps initialize **/
if( nold != idim ) csfft_trigconsts( idim ) ;
/** Main loop starts here **/
n = idim;
i2 = idim >> 1;
i1 = 0;
csp = (mode > 0) ? csplus : csminus ; /* choose const array */
for (i0=0; i0 < n; i0 ++) {
if ( i1 > i0 ) {
r0 = xc + i0;
r1 = xc + i1;
f1 = r0->r;
f2 = r0->i;
r0->r = r1->r;
r0->i = r1->i;
r1->r = f1;
r1->i = f2;
}
m = i2;
while ( m && !(i1 < m) ) {
i1 -= m;
m >>= 1;
}
i1 += m;
}
m = 1;
k = 0;
while (n > m) {
i3 = m << 1;
for (i0=0; i0 < m; i0 ++) {
co = (csp + k)->r;
si = (csp + k)->i;
for (i1=i0; i1 < n; i1 += i3) {
r0 = xc + i1;
r1 = r0 + m;
f1 = r1->r * co;
f2 = r1->i * si;
f3 = r1->r * si;
f4 = r1->i * co;
f1 -= f2;
f3 += f4;
f2 = r0->r;
f4 = r0->i;
r1->r = f2 - f1;
r1->i = f4 - f3;
r0->r = f2 + f1;
r0->i = f4 + f3;
}
k++;
}
m = i3;
}
#ifdef SCALE_INVERSE
if (mode > 0) {
f0 = 1.0 / idim ;
i0 = 0;
i1 = 1;
while (i0 < n) {
r0 = xc + i0;
r1 = xc + i1;
f1 = r0->r;
f2 = r0->i;
f3 = r1->r;
f4 = r1->i;
f1 *= f0;
f2 *= f0;
f3 *= f0;
f4 *= f0;
r0->r = f1;
r0->i = f2;
r1->r = f3;
r1->i = f4;
i0 += 2;
i1 += 2;
}
}
#endif
return ;
}
syntax highlighted by Code2HTML, v. 0.9.1