// Author: 围城
typedef struct complex
{
ElementType real;
ElementType imagin;
} COMPLEX;
void AddComplex(COMPLEX *src1, COMPLEX *src2, COMPLEX *dst)
{
dst->imagin = src1->imagin+src2->imagin;
dst->real = src1->real+src2->real;
}
void SubComplex(COMPLEX *src1, COMPLEX *src2, COMPLEX *dst)
{
dst->imagin = src1->imagin-src2->imagin;
dst->real = src1->real-src2->real;
}
void MultyComplex(COMPLEX *src1, COMPLEX *src2, COMPLEX *dst)
{
ElementType r1,r2;
ElementType i1,i2;
r1=src1->real;
r2=src2->real;
i1=src1->imagin;
i2=src2->imagin;
// dst->imagin = src1->real * src2->imagin + src2->real * src1->imagin;
// dst->real = src1->real * src2->real - src1->imagin * src2->imagin;
dst->imagin=r1*i2+r2*i1;
dst->real=r1*r2-i1*i2;
}
void CopyComplex(COMPLEX *src, COMPLEX *dst)
{
dst->real = src->real;
dst->imagin = src->imagin;
}
void getWN(Int n, Int fftSize, COMPLEX *dst)
{
ElementType x = 2.0 * Pi * (ElementType)n / (ElementType)fftSize;
dst->imagin = -sin(x);
dst->real = cos(x);
}
int isBase2(int size)
{
int k = size;
int z = 0;
while (k /= 2) {
z++;
}
if (size != (1<<z)) {
return -1;
}
else {
return z;
}
}
void fftRemap(COMPLEX *src,int size)
{
if (1 == size) {
return;
}
COMPLEX *temp = (COMPLEX*)malloc(sizeof(COMPLEX)*size);
for (int i = 0;i < size;i++)
{
if(!(i%2)) {
CopyComplex(src+i, temp+i/2);
}
else {
CopyComplex(src+i, temp+(size+i)/2);
}
}
for (int i = 0;i < size;i++) {
CopyComplex(temp+i, src+i);
}
free(temp);
fftRemap(src, size/2);
fftRemap(src+size/2, size/2);
return;
}
void RealFFT(ElementType *src, COMPLEX *dst, int size)
{
int k = size;
int z = 0;
while (k /= 2) {
z++;
}
k = z;
if (size != (1<<k)) {
exit(0);
}
COMPLEX *srcCpy = (COMPLEX*)malloc(sizeof(COMPLEX)*size);
if (NULL == srcCpy) {
exit(0);
}
for (int i = 0;i < size;i++)
{
(srcCpy+i)->real = *(src+i);
(srcCpy+i)->imagin = 0;
}
fftRemap(srcCpy, size);
for (int i = 0;i < k;i++)
{
z = 0;
for (int j = 0;j < size;j++)
{
if (1 == (j/(1<<i))%2)
{
COMPLEX wn;
getWN(z, size, &wn);
z += 1 << (k-i-1);
int neighbour = j - (1<<i);
COMPLEX temp;
temp.real = (srcCpy+neighbour)->real;
temp.imagin = (srcCpy+neighbour)->imagin;
MultyComplex(srcCpy+j, &wn, srcCpy+j);
AddComplex(&temp, srcCpy+j, srcCpy+neighbour);
SubComplex(&temp, srcCpy+j, srcCpy+j);
}
else {
z = 0;
}
}
}
for (int i = 0;i < size;i++) {
CopyComplex(srcCpy+i, dst+i);
}
free(srcCpy);
}
void ColumnVector(COMPLEX *src, COMPLEX *dst, int fftWidthSize, int fftHeightSize)
{
for (int row = 0;row < fftHeightSize;row++) {
CopyComplex(src+fftWidthSize*row, dst+row);
}
}
void FFT(COMPLEX *src, COMPLEX *dst, int size)
{
int k = size;
int z = 0;
while (k /= 2) {
z++;
}
k = z;
if (size != (1<<k)) {
exit(0);
}
COMPLEX *srcCpy=(COMPLEX*)malloc(sizeof(COMPLEX)*size);
if (NULL == srcCpy) {
exit(0);
}
for (int i = 0;i < size;i++) {
CopyComplex(src+i, srcCpy+i);
}
fftRemap(srcCpy, size);
for (int i = 0;i < k;i++)
{
z = 0;
for (int j = 0;j < size;j++)
{
if (1 == (j/(1<<i))%2)
{
COMPLEX wn;
getWN(z, size, &wn);
z += 1 << (k-i-1);
int neighbour = j - (1<<i);
COMPLEX temp;
temp.real = (srcCpy+neighbour)->real;
temp.imagin = (srcCpy+neighbour)->imagin;
MultyComplex(srcCpy+j, &wn,srcCpy+j);
AddComplex(&temp, srcCpy+j, srcCpy+neighbour);
SubComplex(&temp, srcCpy+j, srcCpy+j);
}
else {
z = 0;
}
}
}
for (int i = 0;i < size;i++) {
CopyComplex(srcCpy+i, dst+i);
}
free(srcCpy);
}
void IColumnVector(COMPLEX *src, COMPLEX *dst, int fftWidthSize, int fftHeightSize)
{
for (int row = 0;row < fftHeightSize;row++) {
CopyComplex(src+row, dst+fftWidthSize*row);
}
}
int FFT2D(ElementType *src, COMPLEX *dst, int fftWidthSize, int fftHeightSize)
{
if (-1 == isBase2(fftWidthSize) || -1 == isBase2(fftHeightSize)) {
exit(0);
}
COMPLEX *row = (COMPLEX*)malloc(sizeof(COMPLEX)*fftHeightSize*fftWidthSize);
if (NULL == row) {
return -1;
}
for (int i = 0;i < fftHeightSize;i++) {
RealFFT(src+fftWidthSize*i, row+fftWidthSize*i, fftWidthSize);
}
COMPLEX *column = (COMPLEX*)malloc(sizeof(COMPLEX)*fftHeightSize);
if (NULL == column) {
return -1;
}
for (int i = 0;i < fftWidthSize;i++)
{
ColumnVector(row+i, column, fftWidthSize, fftHeightSize);
FFT(column, column, fftHeightSize);
IColumnVector(column, row+i, fftWidthSize, fftHeightSize);
}
for (int i = 0;i < fftHeightSize*fftWidthSize;i++) {
CopyComplex(row+i, dst+i);
}
free(row);
free(column);
return 0;
}
近期评论