转载请标明是引用于 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<n;i+=MAX_IN_CACHE_TRANS_LEN)
{
fft_sub(data+i,MAX_IN_CACHE_TRANS_LEN,2,MAX_IN_CACHE_TRANS_LEN);
}
fft_sub(data,n,MAX_IN_CACHE_TRANS_LEN*2,n);
return TRUE;
}
//*******************************************************************
// 将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<n;i+=2) // d: 翅间距=1, buffterfly group length =2, group number =n/2
{
t=data[i+1];
CMPL_SUB(data[i+1],data[i],t);
CMPL_ADD(data[i], data[i],t);
}
#ifdef OUT_INTER_RESULT
sprintf(fileName,"../test result/data1_%08d_FFT1.bin",2);
dumpData(data,n,fileName);
#endif
for (i=0;i<n;i+=4) // 翅间距=2, buffterfly group length =4 ,group number =n/4
{
t1=data[i+2];
t2.Re= data[i+3].Im; //t2=(0,-1)*(data[i+3].Re,data[i+3].Im)
t2.Im= -data[i+3].Re;
CMPL_SUB(data[i+2],data[i],t1);
CMPL_ADD(data[i], data[i],t1);
CMPL_SUB(data[i+3],data[i+1],t2);
CMPL_ADD(data[i+1],data[i+1],t2);
}
#ifdef OUT_INTER_RESULT
sprintf(fileName,"../test result/data1_%08d__FFT1.bin",4);
dumpData(data,n,fileName);
#endif
// 翅间距>=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<n; groupBase+=groupLen)
{
DWORD r,t;
i1=groupBase; // butterfly 1 left-up index
i2=groupBase+d/2;
j1=i1+d; // butterfly 1 left-down index
j2=i2+d;
t1 = data[j1]; //t1= e^(-2*PI*0 i) * data[j1]
t2.Re= data[j2].Im; //t2= e^(-2*PI/4 i) * data[j2]
t2.Im= -data[j2].Re; // complex:(0,-1) * data[j2]
CMPL_SUB(data[j1],data[i1],t1);
CMPL_ADD(data[i1],data[i1],t1);
//-------------------------------
CMPL_SUB(data[j2],data[i2],t2);
CMPL_ADD(data[i2],data[i2],t2);
i1++; i2++;
j1++; j2++;
for (r=1; r<d/2; i1++,i2++,j1++,j2++,r++)
{
t=groupLen/4-r;
//w1.Re= pW[r];
//w1.Im= -pW[t];
//w2.Re= -pw[t];
//w2.Im= -pw[r];
t1.Re = ( pW[r] * data[j1].Re + pW[t] * data[j1].Im);
t1.Im = ( -pW[t] * data[j1].Re + pW[r] * data[j1].Im);
t2.Re = ( -pW[t] * data[j2].Re + pW[r] * data[j2].Im);
t2.Im = ( -pW[r] * data[j2].Re - pW[t] * data[j2].Im);
CMPL_SUB(data[j1], data[i1], t1);
CMPL_ADD(data[i1], data[i1], t1);
CMPL_SUB(data[j2], data[i2], t2);
CMPL_ADD(data[i2], data[i2], t2);
}
}
#ifdef OUT_INTER_RESULT
sprintf(fileName,"../test result/data1_%08d_FFT1.bin",groupLen);
dumpData(data,n,fileName);
#endif
}
return TRUE;
}
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<double> * TD- 指向时域数组的指针
// * complex<double> * FD- 指向频域数组的指针
// * r-2的幂数,即迭代次数
// *
// * 返回值:
// * 无。
// *
// * 说明:
// * 该函数用来实现快速付立叶变换。
// *
// ************************************************************************/
void FFT( complex<double> *TD, complex<double> *FD,
complex<double> *X1, complex<double> *X2,
complex<double> *Omega, int r)
{
// 付立叶变换点数
long count;
// 循环变量
int i,j,k;
// 中间变量
int bfsize,p;
// 角度
double angle;
complex<double> *X;
// 计算付立叶变换点数
count = 1 << r;
// 分配运算所需存储器
//Omega = new complex<double>[count / 2];
//X1 = new complex<double>[count];
//X2 = new complex<double>[count];
// 计算加权系数
for(i = 0; i < count / 2; i++)
{
angle = -i * 3.1415926 * 2 / count;
Omega[i] = complex<double>(cos(angle), sin(angle));
}
// 将时域点写入X1
memcpy(X1, TD, sizeof(complex<double>) * 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<<k)];
}
}
X = X1;
X1 = X2;
X2 = X;
}
// 重新排序
for(j = 0; j < count; j++)
{
p = 0;
for(i = 0; i < r; i++)
{
if (j&(1<<i))
{
p+=1<<(r-i-1);
}
}
FD[j]=X1[p];
}
// 释放内存
//delete Omega;
//delete X1;
//delete X2;
}