C code for FFT (2)
Joseph Yip
ycy at walt.cc.utexas.edu
Fri Jun 15 02:09:26 AEST 1990
Here is the second program I got.
>From tpf at jdyx.atlanta.ga.us Wed Jun 13 21:44:53 1990
Received: from emory.mathcs.emory.edu by walt.cc.utexas.edu (5.61/1.34/CCWF 1.5)
id AA01107; Wed, 13 Jun 90 21:44:40 -0500
Received: from jdyx.UUCP by emory.mathcs.emory.edu (5.59/1.17.EUCC) via UUCP
id AA00433 ; Wed, 13 Jun 90 22:44:37 EDT
Return-Path: tpf at jdyx.atlanta.ga.us
Received: by jdyx.UUCP (5.51/smail2.2/06-30-87)
id AA12786; Wed, 13 Jun 90 21:47:09 EDT
Date: Wed, 13 Jun 90 21:47:09 EDT
From: tpf at jdyx.atlanta.ga.us (Tom Friedel)
Message-Id: <9006140147.AA12786 at jdyx.UUCP>
To: ycy at ccwf.cc.utexas.edu
Subject: Re: C code for FFT
Newsgroups: sci.math,comp.sources.wanted,comp.lang.c
References: <31567 at ut-emx.UUCP>
Status: R
In comp.sources.wanted you write:
>Hi,
>I am looking for C source for Fast Fourier Transform (any dimensions and
>power of 2). The netlib only has the Fortran version and I do not want
>to use f2c.
>If you have a good FFT program (fast!), that is excellent.
>Thank you.
>Joseph Yip
Maybe this will help.
tom
Tom Friedel JDyx Enterprises (404) 320-7624 tpf at jdyx.UUCP
Unix BBS: (404) 325-1719 <= 2400 ; (404) 321-5020 >= 2400
"Live simply, so that others may simply live."
Well, according to the amount of E-mail I received, and as I cannot
answer to all of them, I am posting the 2D FFT program I have written in C.
How to use it : first, it can be used only on matrix of the type
complexe, as defined at the begining of the program, with a size in
2^maxlevel (2 power maxlevel). One just have to call the program as following :
InvFFT(matrix,maxlevel);
As you have noticed, it is in fact an Inverse Fourier Transform
(sampling matrix in the frequency space -> matrix of heights) which
is performed, but just an initialisation line at the begining of the
procedure InvFFT has to be change to obtain the FFT :
Omega = 2 * M_PI / dimension; must be change into
Omega = - 2 * M_PI / dimension;
I am clearly aware that this program has not been optimised as it
could be, mainly in order to keep the the clarity of the algorithm, but I am
open to any suggestion that you could make in order to improve the process.
I have tested it in a fractal landscape project and it seems to work
correctly (when there were bugs in it such as forgetting the multiplication
of omega by two at the recursive calls, I had funny landscapes looking like
a micro-chip seen through an electronic microscop).
Well, I think that is all, for the moment. Here comes the program.
Note : you will have probably to cut the signature at the end of the
file as well.
Jean-Marc
----cut here -----cut here -----cut here -----cut here -----cut here -----
/* It is a pity I have to add this notice, but it must be done. */
/* NOTICE *
* Copyright (c) 1990, Jean-Marc de Lauwereyns *
* for the procedures mirror, RecFFT, InvFFT. *
* These procedures can be used and given freely to anybody but can not *
* be sold or used in any commercial program or in any book without the *
* permission of the original author. *
* These procedures can be modified at the condition that the nature of *
* modification is mentioned in comments at the place of the modification *
* with the original lines accompanied by the name of the original author.*
* This notice itself can not be removed or modified except by the *
* original author himself. */
/* you must have included the file /usr/include/math.h at the begining of *
* your program */
typedef struct {
double a,b;
} complexe;
/****************************************************/
/* function mirror just transform the binary */
/* representation of an integer into its mirror */
/* binary representation on maxlevel bits */
/* eg : with maxlevel = 6, 000101 becomes 101000 */
/****************************************************/
int mirror(index,maxlevel)
int index;
int maxlevel;
{
register int i;
int res;
res = 0;
for (i=0;i<maxlevel;i++)
{
res = (res << 1) | (index & (int)1);
index = (index >> 1);
}
return(res);
}
/*****************************************************/
/* recursive procedure to calculate the FFT on 2^N */
/*****************************************************/
void RecFFT(A,k,l,p,q,Omega)
complexe **A;
int k,l; /* indexes for the begin and the end on the lines taken */
int p,q; /* indexes for the begin and the end of the columns taken */
double Omega;
{
int i,j,m;
complexe a,b,c,d;
double argument[3];
if (k != l)
{
m = (l-k)/2;
for (i = k;i < k + m;i++)
{
argument[0] = Omega * (double)(i-k);
for (j = p;j < p + m;j++)
{
argument[1] = Omega * (double)(j-p);
argument[2] = Omega * (double)(i-k + j-p);
a.a = A[i][j].a;a.b = A[i][j].b;
b.a = A[i+m][j].a;b.b = A[i+m][j].b;
c.a = A[i][j+m].a;c.b = A[i][j+m].b;
d.a = A[i+m][j+m].a;d.b = A[i+m][j+m].b;
A[i][j].a = a.a + b.a + c.a + d.a;
A[i][j].b = a.b + b.b + c.b + d.b;
A[i+m][j].a = (a.a - b.a + c.a - d.a)*cos(argument[0]) -
(a.b - b.b + c.b - d.b)*sin(argument[0]);
A[i+m][j].b = (a.a - b.a + c.a - d.a)*sin(argument[0]) +
(a.b - b.b + c.b - d.b)*cos(argument[0]);
A[i][j+m].a = (a.a + b.a - c.a - d.a)*cos(argument[1]) -
(a.b + b.b - c.b - d.b)*sin(argument[1]);
A[i][j+m].b = (a.a + b.a - c.a - d.a)*sin(argument[1]) +
(a.b + b.b - c.b - d.b)*cos(argument[1]);
A[i+m][j+m].a = (a.a - b.a - c.a + d.a)*cos(argument[2]) -
(a.b - b.b - c.b + d.b)*sin(argument[2]);
B[i+m][j+m].b = (a.a - b.a - c.a + d.a)*sin(argument[2]) +
(a.b - b.b - c.b + d.b)*cos(argument[2]);
}
}
if (m != 0)
{
RecFFT(k,k+m,p,p+m,Omega*2);
RecFFT(k+m,l,p,p+m,Omega*2);
RecFFT(k,k+m,p+m,q,Omega*2);
RecFFT(k+m,l,p+m,q,Omega*2);
}
}
}
/********************************************************/
/* InvFFT is a procedure which produce the inverse of */
/* Fourier Transformation. */
/********************************************************/
void InvFFT(A,interlevel)
complexe **A;
int interlevel;
{
int dimension;
int i,j,i1,j1;
double coeff,Omega;
dimension = (1 << interlevel);
Omega = 2 * M_PI / dimension;
RecFFT(A,0,dimension,0,dimension,Omega);
for (i=0;i<=(dimension - 1);i++)
/* swap every rows i with its mirror image */
{
i1 = mirror(i,interlevel);
if (i1 > i) /* if i1 <= i, the swaaping have been already made */
for (j=0;j<dimension;j++)
{
coeff = A[i][j].a;
A[i][j].a = A[i1][j].a;
A[i1][j].a = coeff;
/* this may be remove if you are sure that the result is a *
* matrix of real which means that the original matrix must *
* verify the following conditions : *
* ______ ______ *
* A(N-i,N-j) = A(i,j) , A(0,N-j) = A(0,j) *
* ______ *
* A(N-i,0) = A(i,0) for i,j > 0 and A(0,0) is a pure *
* real */
coeff = A[i][j].b;
A[i][j].a = A[i1][j].a;
A[i1][j].a = coeff;
}
}
for (j=0;j<=(dimension - 1);j++) /* idem for the columns */
{
j1 = mirror(j,interlevel);
if (j1 >j)
for (i=0;i<dimension;i++)
{
coeff = A[i][j].a;
A[i][j].a = A[i][j1].a;
A[i][j1].a = coeff;
/* part which may be removed if (see above) */
coeff = A[i][j].b;
A[i][j].b = A[i][j1].b;
A[i][j1].b = coeff;
}
}
}
----cut here -----cut here -----cut here -----cut here -----cut here ----
Jean-Marc de Lauwereyns | ____ | e-mail addresses :
Heriot-Watt University | |\ /| | \ | JANET: lauwer at uk.ac.hw.cs
Computer Science Department | | \/ | |___/ | ARPA.: lauwer at cs.hw.ac.uk
Edinburgh | \___/ |___| \ |
More information about the Comp.lang.c
mailing list