#include "fftease.h"

/* If forward is true, rfft replaces 2*N real data points in x with
   N complex values representing the positive frequency half of their
   Fourier spectrum, with x[1] replaced with the real part of the Nyquist
   frequency value.  If forward is false, rfft expects x to contain a
   positive frequency spectrum arranged as before, and replaces it with
   2*N real values.  N MUST be a power of 2. */

void fftease_rfft( t_float *x, int N, int forward )

{
  t_float 	c1,c2,
  		h1r,h1i,
		h2r,h2i,
		wr,wi,
		wpr,wpi,
  		temp,
		theta;
  t_float 	xr,xi;
  int 		i,
		i1,i2,i3,i4,
		N2p1;
  static int 	first = 1;
/*t_float PI, TWOPI;*/
void fftease_cfft();

    if ( first ) {

	first = 0;
    }
    theta = PI/N;
    wr = 1.;
    wi = 0.;
    c1 = 0.5;
    if ( forward ) {
	c2 = -0.5;
	fftease_cfft( x, N, forward );
	xr = x[0];
	xi = x[1];
    } else {
	c2 = 0.5;
	theta = -theta;
	xr = x[1];
	xi = 0.;
	x[1] = 0.;
    }
    wpr = -2.*pow( sin( 0.5*theta ), 2. );
    wpi = sin( theta );
    N2p1 = (N<<1) + 1;
    for ( i = 0; i <= N>>1; i++ ) {
	i1 = i<<1;
	i2 = i1 + 1;
	i3 = N2p1 - i2;
	i4 = i3 + 1;
	if ( i == 0 ) {
	    h1r =  c1*(x[i1] + xr );
	    h1i =  c1*(x[i2] - xi );
	    h2r = -c2*(x[i2] + xi );
	    h2i =  c2*(x[i1] - xr );
	    x[i1] =  h1r + wr*h2r - wi*h2i;
	    x[i2] =  h1i + wr*h2i + wi*h2r;
	    xr =  h1r - wr*h2r + wi*h2i;
	    xi = -h1i + wr*h2i + wi*h2r;
	} else {
	    h1r =  c1*(x[i1] + x[i3] );
	    h1i =  c1*(x[i2] - x[i4] );
	    h2r = -c2*(x[i2] + x[i4] );
	    h2i =  c2*(x[i1] - x[i3] );
	    x[i1] =  h1r + wr*h2r - wi*h2i;
	    x[i2] =  h1i + wr*h2i + wi*h2r;
	    x[i3] =  h1r - wr*h2r + wi*h2i;
	    x[i4] = -h1i + wr*h2i + wi*h2r;
	}
	wr = (temp = wr)*wpr - wi*wpi + wr;
	wi = wi*wpr + temp*wpi + wi;
    }
    if ( forward )
	x[1] = xr;
    else
	fftease_cfft( x, N, forward );
}

/* cfft replaces t_float array x containing NC complex values
   (2*NC t_float values alternating real, imagininary, etc.)
   by its Fourier transform if forward is true, or by its
   inverse Fourier transform if forward is false, using a
   recursive Fast Fourier transform method due to Danielson
   and Lanczos.  NC MUST be a power of 2. */

void fftease_cfft( t_float *x, int NC, int forward )

{
  t_float 	wr,wi,
		wpr,wpi,
		theta,
		scale;
  int 		mmax,
		ND,
		m,
		i,j,
		delta;

void fftease_bitreverse();

    ND = NC<<1;
    fftease_bitreverse( x, ND );
    for ( mmax = 2; mmax < ND; mmax = delta ) {
	delta = mmax<<1;
	theta = TWOPI/( forward? mmax : -mmax );
	wpr = -2.*pow( sin( 0.5*theta ), 2. );
	wpi = sin( theta );
	wr = 1.;
	wi = 0.;
	for ( m = 0; m < mmax; m += 2 ) {
	 register t_float rtemp, itemp;
	    for ( i = m; i < ND; i += delta ) {
		j = i + mmax;
		rtemp = wr*x[j] - wi*x[j+1];
		itemp = wr*x[j+1] + wi*x[j];
		x[j] = x[i] - rtemp;
		x[j+1] = x[i+1] - itemp;
		x[i] += rtemp;
		x[i+1] += itemp;
	    }
	    wr = (rtemp = wr)*wpr - wi*wpi + wr;
	    wi = wi*wpr + rtemp*wpi + wi;
	}
    }

/* scale output */

    scale = forward ? 1./ND : 2.;
    { register t_float *xi=x, *xe=x+ND;
	while ( xi < xe )
	    *xi++ *= scale;
    }
}

/* bitreverse places t_float array x containing N/2 complex values
   into bit-reversed order */

void fftease_bitreverse( t_float *x, int N )

{
  t_float 	rtemp,itemp;
  int 		i,j,
		m;

    for ( i = j = 0; i < N; i += 2, j += m ) {
	if ( j > i ) {
	    rtemp = x[j]; itemp = x[j+1]; /* complex exchange */
	    x[j] = x[i]; x[j+1] = x[i+1];
	    x[i] = rtemp; x[i+1] = itemp;
	}
	for ( m = N>>1; m >= 2 && j >= m; m >>= 1 )
	    j -= m;
    }
}
