转载请标明是引用于 http://blog.csdn.net/chenyujing1234
例子代码:(编译工具:VS2005)
http://www.rayfile.com/zh-cn/files/76968e5e-7bde-11e1-8c13-0015c55db73d/
由于公司要做FFT算法,具体是做高尔夫球的弹道分析,至今还没把算法敲定。
今天网上看了算法,自己建立工程,进行了比较。
现在按算法速度从快到慢的顺序介绍:(先搭个框架,具体算法解释,请听下回分解)
1、
//*******************************************************************
// 将data[]中的元素进行快速傅立叶变换,当变换长度大于L2 cache,有较快的速度
BOOL FFT2(CMPL data[], size_t n)
//*******************************************************************
{
unsigned long i;
//------------------------------------
if (n<4)
{
printf("too small transpos length\n");
return FALSE;
}
Init_OMAGE_ARRAY(n);
if (g_w.arr==NULL)
{
printf("no enough memory\n");
return FALSE;
}
reverseOrder(data,n,Log2(n)); //反序
if (n<=MAX_IN_CACHE_TRANS_LEN)
{
fft_sub(data,n,2,n);
return TRUE;
}
for (i=0;i
//*******************************************************************
// 将data[]中的元素进行快速傅立叶变换
BOOL FFT1(CMPL data[], size_t n)
//*******************************************************************
{
unsigned long i,i1,i2,j1,j2,d;
unsigned long groupBase,groupLen,omageBase;
CMPL t,t1,t2;
double *pW=NULL;
char fileName[3209];
if (n<4)
{
printf("too small transpos length\n");
return FALSE;
}
Init_OMAGE_ARRAY(n);
if (g_w.arr==NULL)
{
printf("no enough memory\n");
return FALSE;
}
reverseOrder(data,n,Log2(n)); //反序
for (i=0;i=4, buffterfly group length >=8 ,group number =n/group length
for (groupLen=8;groupLen<=n;groupLen*=2 )
{
d=groupLen/2; //d: 翅间距
omageBase=g_w.tabIndex[Log2(groupLen)-2].offset;
pW= (double *)(g_w.arr)+omageBase; //omage array address
for ( groupBase = 0; groupBase
2、
void fft(int n, double xRe[], double xIm[],
double yRe[], double yIm[])
{
int sofarRadix[maxFactorCount],
actualRadix[maxFactorCount],
remainRadix[maxFactorCount];
int nFactor;
int count;
pi = 4*atan(1);
transTableSetup(sofarRadix, actualRadix, remainRadix, &nFactor, &n);
permute(n, nFactor, actualRadix, remainRadix, xRe, xIm, yRe, yIm);
for (count=1; count<=nFactor; count++)
twiddleTransf(sofarRadix[count], actualRadix[count], remainRadix[count],
yRe, yIm);
} /* fft */
3、
void four1(double data[], int nn, int isign)
{
int n,j,i,m,mmax,istep;
double tempr,tempi,theta,wpr,wpi,wr,wi,wtemp;
n = 2 * nn;
j = 1;
for (i = 1; i<=n; i=i+2)
{
if(j > i)
{
tempr = data[j];
tempi = data[j + 1];
data[j] = data[i];
data[j + 1] = data[i + 1];
data[i] = tempr;
data[i + 1] = tempi;
}
m = n / 2;
while (m >= 2 && j > m)
{
j = j - m;
m = m / 2;
}
j = j + m;
}
mmax = 2;
while(n > mmax)
{
istep = 2 * mmax;
theta = 6.28318530717959 / (isign * mmax);
wpr = -2.0 * sin(0.5 * theta)*sin(0.5 * theta);
wpi = sin(theta);
wr = 1.0;
wi = 0.0;
for(m = 1; m<=mmax; m=m+2)
{
for (i = m; i<=n; i=i+istep)
{
j = i + mmax;
tempr=double(wr)*data[j]-double(wi)*data[j+1];
tempi=double(wr)*data[j+1]+double(wi)*data[j];
data[j] = data[i] - tempr;
data[j + 1] = data[i + 1] - tempi;
data[i] = data[i] + tempr;
data[i + 1] = data[i + 1] + tempi;
}
wtemp = wr;
wr = wr * wpr - wi * wpi + wr;
wi = wi * wpr + wtemp * wpi + wi;
}
mmax = istep;
}
}
4、
void fft(COMPLEX in[],COMPLEX out[], COMPLEX omega[],int n)
{
int s,k,m,l,nv,t,j;
COMPLEX podd,ret;
k = (int)(log(n) / log(2) + 0.5);
nv = n;
m = 1;
for ( l = k-1 ; l >= 0 ; l-- )
{
for ( t = 0 ; t < m * nv ; t+=nv )
for ( j = 0 ; j < nv/2 ; j++ )
{
s = (t+j) / (int)pow(2,l);
s = reverse(s,k);
ret = omega[s];
mul(&ret,&in[t+j+nv/2],&podd);
sub(&in[t+j],&podd,&in[t+j+nv/2]);
add(&in[t+j],&podd,&in[t+j]);
}
m *= 2;
nv /= 2;
}
for ( t = 0 ; t < n ; t++ )
{
s = reverse(t,k);
out[t] = in[s];
}
}
5、
void cdft(int n, int isgn, double *a)
{
void cftfsub(int n, double *a);
void cftbsub(int n, double *a);
if (isgn >= 0) {
cftfsub(n, a);
} else {
cftbsub(n, a);
}
}
void cftfsub(int n, double *a)
{
void bitrv2(int n, double *a);
void bitrv216(double *a);
void bitrv208(double *a);
void cftmdl1(int n, double *a);
void cftrec4(int n, double *a);
void cftleaf(int n, int isplt, double *a);
void cftfx41(int n, double *a);
void cftf161(double *a);
void cftf081(double *a);
void cftf040(double *a);
void cftx020(double *a);
#ifdef USE_CDFT_THREADS
void cftrec4_th(int n, double *a);
#endif /* USE_CDFT_THREADS */
if (n > 8) {
if (n > 32) {
cftmdl1(n, a);
#ifdef USE_CDFT_THREADS
if (n > CDFT_THREADS_BEGIN_N) {
cftrec4_th(n, a);
} else
#endif /* USE_CDFT_THREADS */
if (n > 512) {
cftrec4(n, a);
} else if (n > 128) {
cftleaf(n, 1, a);
} else {
cftfx41(n, a);
}
bitrv2(n, a);
} else if (n == 32) {
cftf161(a);
bitrv216(a);
} else {
cftf081(a);
bitrv208(a);
}
} else if (n == 8) {
cftf040(a);
} else if (n == 4) {
cftx020(a);
}
}
void cftbsub(int n, double *a)
{
void bitrv2conj(int n, double *a);
void bitrv216neg(double *a);
void bitrv208neg(double *a);
void cftb1st(int n, double *a);
void cftrec4(int n, double *a);
void cftleaf(int n, int isplt, double *a);
void cftfx41(int n, double *a);
void cftf161(double *a);
void cftf081(double *a);
void cftb040(double *a);
void cftx020(double *a);
#ifdef USE_CDFT_THREADS
void cftrec4_th(int n, double *a);
#endif /* USE_CDFT_THREADS */
if (n > 8) {
if (n > 32) {
cftb1st(n, a);
#ifdef USE_CDFT_THREADS
if (n > CDFT_THREADS_BEGIN_N) {
cftrec4_th(n, a);
} else
#endif /* USE_CDFT_THREADS */
if (n > 512) {
cftrec4(n, a);
} else if (n > 128) {
cftleaf(n, 1, a);
} else {
cftfx41(n, a);
}
bitrv2conj(n, a);
} else if (n == 32) {
cftf161(a);
bitrv216neg(a);
} else {
cftf081(a);
bitrv208neg(a);
}
} else if (n == 8) {
cftb040(a);
} else if (n == 4) {
cftx020(a);
}
}
6、
//*************************************************************************
// *
// * 函数名称:
// * FFT()
// *
// * 参数:
// * complex * TD- 指向时域数组的指针
// * complex * FD- 指向频域数组的指针
// * r-2的幂数,即迭代次数
// *
// * 返回值:
// * 无。
// *
// * 说明:
// * 该函数用来实现快速付立叶变换。
// *
// ************************************************************************/
void FFT( complex *TD, complex *FD,
complex *X1, complex *X2,
complex *Omega, int r)
{
// 付立叶变换点数
long count;
// 循环变量
int i,j,k;
// 中间变量
int bfsize,p;
// 角度
double angle;
complex *X;
// 计算付立叶变换点数
count = 1 << r;
// 分配运算所需存储器
//Omega = new complex[count / 2];
//X1 = new complex[count];
//X2 = new complex[count];
// 计算加权系数
for(i = 0; i < count / 2; i++)
{
angle = -i * 3.1415926 * 2 / count;
Omega[i] = complex(cos(angle), sin(angle));
}
// 将时域点写入X1
memcpy(X1, TD, sizeof(complex) * count);
// 采用蝶形算法进行快速付立叶变换
for(k = 0; k < r; k++)
{
for(j = 0; j < 1 << k; j++)
{
bfsize = 1 << (r-k);
for(i = 0; i < bfsize / 2; i++)
{
p = j * bfsize;
X2[i + p] = X1[i + p] + X1[i + p + bfsize / 2];
X2[i + p + bfsize / 2] = (X1[i + p] - X1[i + p + bfsize / 2]) * Omega[i * (1<