Files
micro_servers/bot4cj/src/cpp/fft1.c
T
2026-07-28 12:44:07 +08:00

232 lines
6.2 KiB
C

/* fft1.c: fast Fourier transform base on 2 for one dimensional
complex array, direct and inverse,
This program is contributed by Jiang Yong, 2003. 1. */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "fft.h"
static int ifirst=0, sign=-1;
static unsigned M, jup[64], kup[64];
static float pi, wr[N], wi[N];
/********* initial **************/
void initial(void)
{
unsigned long int i, j, ni;
float unit, tt;
ni = N;
M = 0;
while (ni > 1) { ni=ni/2; M=M+1; }
ni = 1;
for(j=0; j<M; j++) ni = ni * 2;
if ((ni-N) != 0)
{
printf("N isn't compatible! (N => %i, ni -> %lu)\n", N, ni);
exit(1);
}
kup[0] = N/2; /* kup[l] = 2 ^ (M - l - 1) */
jup[0] =1;
for (j=1;j<M;j++)
{
kup[j]=kup[j-1]/2;
jup[j]=jup[j-1]*2;
}
pi=4.0*atan((float)1.0);
unit=2.0*pi/((float)N);
tt=0.0;
for(i=0;i<N;i++)
{
wr[i] = cos(tt);
wi[i] = sign * sin(tt);
tt = tt + unit;
}
}
/** ifft=1<-->FFT ** ifft=-1<-->IFFT **/
void fft1(float A[2][N], int ifft)
{
unsigned long int l, k, i, j, jl0, jl0k, jl1k, reseq, ij;
float wrc, wis, ar, ai, x[2][N];
if (ifirst == 0) { initial(), ifirst=1; }
if (ifft == -1)
for(i=0;i<N;i++) A[1][i] = -A[1][i];
for (l=0; l<M; l++)
{
for (j=0; j<jup[l]; j++)
{
reseq=inverseq(j, l);
ij=kup[l]*reseq;
jl0=2*kup[l]*j;
wrc = wr[ij];
wis = wi[ij];
for (k=0; k<kup[l]; k++)
{
jl0k = jl0 + k;
jl1k = jl0 + kup[l] + k;
ar = A[0][jl1k] * wrc - A[1][jl1k] * wis;
ai = A[0][jl1k] * wis + A[1][jl1k] * wrc;
A[0][jl1k] = A[0][jl0k] - ar;
A[1][jl1k] = A[1][jl0k] - ai;
A[0][jl0k] = A[0][jl0k] + ar;
A[1][jl0k] = A[1][jl0k] + ai;
}
}
}
for (i=0; i<N; i++)
{
j=inverseq(i, M);
x[0][i] = A[0][j];
x[1][i] = A[1][j];
}
for (i=0; i<N; i++)
{
A[0][i] = x[0][i];
A[1][i] = x[1][i];
}
if (ifft == -1)
for (i=0; i<N; i++)
{
A[0][i] = A[0][i]/((float)N);
A[1][i] = -A[1][i]/((float)N);
}
}
/*********************************/
unsigned long int inverseq(unsigned long int i1,
unsigned long int imax)
{
unsigned long int j, ii, i0, inv;
i0 = i1;
inv = 0;
for (j=0; j < imax; j++)
{
ii=i0%2;
inv=2*inv+ii;
i0=(i0-ii)/2;
}
return (inv);
}
/* ifft=1 <--> FFT ** ifft=-1 <--> IFFT */
void fft1r2(float A[2][N], float B[2][N], int ifft)
{
unsigned long int k, j;
float norm, c[2][N];
if (ifft != -1)
{
for (k=0; k<N; k++)
{
c[0][k]=A[0][k];
c[1][k]=B[0][k];
}
fft1(c, 1);
A[0][0] = c[0][0];
A[1][0] = 0.0;
B[0][0] = c[1][0];
B[1][0] = 0.0;
for (j=1; j<N; j++)
{
A[0][j] = 0.5 * (c[0][j] + c[0][N-j]);
A[1][j] = 0.5 * (c[1][j] - c[1][N-j]);
B[0][j] = 0.5 * (c[1][j] + c[1][N-j]);
B[1][j] = -0.5 * (c[0][j] - c[0][N-j]);
}
} /* end if*/
else
{
for (j=0; j<N/2; j++)
/* check {xj}, {yj} is to real {Ak}, {Bk} */
{
if (j == 0) norm = 2.0 * fabs(A[1][0])
+ 2.0 * fabs(B[1][0]);
else norm = fabs(A[1][j]+A[1][N-j])
+ fabs(A[0][j]-A[0][N-j])
+ fabs(B[1][j]+B[1][N-j])
+ fabs(B[0][j]-B[0][N-j]);
if (norm > eps)
{
printf("The IDFT of the series isn't real!\n");
exit(0);
}
}
for (j=0; j<N; j++)
{
c[0][j]=A[0][j] -B[1][j];
c[1][j]=A[1][j] +B[0][j];
}
fft1(c, -1);
for (k=0; k<N; k++)
{
A[0][k] = c[0][k];
B[0][k] = c[1][k];
A[1][k] = 0.0;
B[1][k] = 0.0;
}
} /* end else */
}
/* ifft = 1 <--> FFT ** ifft = -1 <--> IFFT */
void fft1r1(float A[2][DN], int ifft)
{
unsigned long int j, k, dk;
float norm, c[2][N], d[2][N], tt, hunit, cosj, sinj;
hunit = 4.0 * atan(1.0) / (float)N;
if ( ifft != -1)
{
for (k=0; k<N; k++)
{
dk = k + k;
c[0][k] = A[0][dk];
d[0][k] = A[0][dk+1];
c[1][k] = 0.0;
d[1][k] = 0.0;
}
fft1r2(c, d, 1);
for (j = 0; j < N; j++)
{
tt = (float)j * hunit;
cosj = cos(tt);
sinj = sign * sin(tt);
A[0][j] = c[0][j] + cosj * d[0][j] - sinj * d[1][j];
A[1][j] = c[1][j] + cosj * d[1][j] + sinj * d[0][j];
}
A[0][N] = c[0][0] - d[0][0];
A[1][N] = c[1][0] - d[1][0];
for(j=1; j<N; j++)
{
A[0][DN-j] = A[0][j];
A[1][DN-j] = -A[1][j];
}
} // end if
else
{
for (j = 0; j <N; j++) // check {xj} is to real {Ak}
{
if (j ==0) norm = 2.0 * fabs(A[1][0]);
else norm = fabs(A[1][j]+A[1][DN-j])+
fabs(A[0][j]-A[0][DN-j]);
if (norm > eps)
{
printf("The IDFT of the series {xj} isn't real!\n");
exit(0);
}
}
for (j = 0; j <N; j++)
{
c[0][j]= 0.5 * (A[0][j]+A[0][N+j]);
c[1][j]= 0.5 * (A[1][j]+A[1][N+j]);
tt = (float) j * hunit;
cosj = cos(tt);
sinj = -sign*sin(tt);
d[0][j]= 0.5 * (cosj * (A[0][j]-A[0][N+j])
-sinj*(A[1][j] - A[1][N+j]));
}
fft1r2(c, d, -1);
for (k=0; k<N; k++)
{
dk = k+k;
A[0][dk]=c[0][k];
A[0][dk+1]=d[0][k];
A[1][dk]=0.0;
A[1][dk+1]=0.0;
}
} // end else
}