shithub: asif

ref: f8a9a3fbf021dbc5f2aae0256bc1ab468b747438
dir: asif/fft.c

View raw version
#include <u.h>
#include <libc.h>
#include "asif.h"

/* numerical recipes 2e, pp. 510-514
 * numerical recipes 3e, pp. 617-620
 * argument n here is the number of complex values,
 * not real array size
 * isign is either 1 (forward) or -1 (inverse) */

#define SWAP(a,b)	{tempr=(a); (a)=(b); (b)=tempr;}
void
four1(double *d, int n, int isign)
{
	int nn, mmax, m, j, istep, i;
	double wtemp, wr, wpr, wpi, wi, θ, tempr, tempi;

	if(n < 2 || n & n - 1)
		sysfatal("non power of two");
	nn = n << 1;
	j = 1;
	for(i=1; i<nn; i+=2){
		if(j > i){
			SWAP(d[j-1], d[i-1]);
			SWAP(d[j], d[i]);
		}
		m = n;
		while(m >= 2 && j > m){
			j -= m;
			m >>= 1;
		}
		j += m;
	}
	mmax = 2;
	while(nn > mmax){
		istep = mmax << 1;
		θ = isign * (6.28318530717959 / mmax);
		wtemp = sin(0.5 * θ);
		wpr = -2.0 * wtemp * wtemp;
		wpi = sin(θ);
		wr = 1.0;
		wi = 0.0;
		for(m=1; m<mmax; m+=2){
			for(i=m; i<=nn; i+=istep){
				j = i + mmax;
				tempr = wr * d[j-1] - wi * d[j];
				tempi = wr * d[j] + wi * d[j-1];
				d[j-1] = d[i-1] - tempr;
				d[j] = d[i] - tempi;
				d[i-1] += tempr;
				d[i] += tempi;
			}
			wr = (wtemp = wr) * wpr - wi * wpi + wr;
			wi = wi * wpr + wtemp * wpi + wi;
		}
		mmax = istep;
	}
}

void
realft(double *d, int n, int isign)
{
	int i, i1, i2, i3, i4;
	double θ, c1, c2, h1r, h1i, h2r, h2i, wr, wi, wpr, wpi, wtemp;

	c1 = 0.5;
	θ = PI / (double)(n >> 1);
	if(isign == 1){
		c2 = -0.5;
		four1(d, n>>1, 1);
	}else{
		c2 = 0.5;
		θ = -θ;
	}
	wtemp = sin(0.5 * θ);
	wpr = -2.0 * wtemp * wtemp;
	wpi = sin(θ);
	wr = 1.0 + wpr;
	wi = wpi;
	h1r = 0;
	for(i=1; i<n>>2; i++){
		i2 = 1 + (i1 = i+i);
		i4 = 1 + (i3 = n - i1);
		h1r = c1 * (d[i1] + d[i3]);
		h1i = c1 * (d[i2] - d[i4]);
		h2r = -c2 * (d[i2] + d[i4]);
		h2i = c2 * (d[i1] - d[i3]);
		d[i1] = h1r + wr * h2r - wi * h2i;
		d[i2] = h1i + wr * h2i + wi * h2r;
		d[i3] = h1r - wr * h2r + wi * h2i;
		d[i4] = -h1i + wr * h2i + wi * h2r;
		wr = (wtemp = wr) * wpr - wi * wpi + wr;
		wi = wi * wpr + wtemp * wpi + wi;
	}
	if(isign == 1){
		d[0] = (h1r = d[0]) + d[1];
		d[1] = h1r - d[1];
	}else{
		d[0] = c1 * ((h1r == d[0]) + d[1]);
		d[1] = c1 * (h1r - d[1]);
		four1(d, n>>1, -1);
	}
}