2
Interface to various FFT libraries.
3
Double complex FFT and IFFT.
4
Author: Pearu Peterson, August 2002
9
/**************** FFTWORK *****************************/
12
GEN_CACHE(zfftwork,(int n)
14
,caches_zfftwork[i].n==n
15
,caches_zfftwork[id].coef = (coef_dbl*)malloc(sizeof(coef_dbl)*(n));
16
fft_coef_dbl(caches_zfftwork[id].coef,n);
17
,free(caches_zfftwork[id].coef);
21
/**************** DJBFFT *****************************/
23
GEN_CACHE(zdjbfft,(int n)
26
,caches_zdjbfft[i].n==n
27
,caches_zdjbfft[id].f = (unsigned int*)malloc(sizeof(unsigned int)*(n));
28
caches_zdjbfft[id].ptr = (double*)malloc(sizeof(double)*(2*n));
29
fftfreq_ctable(caches_zdjbfft[id].f,n);
31
caches_zdjbfft[id].f[i] = (n-caches_zdjbfft[id].f[i])%n;
32
,free(caches_zdjbfft[id].f);
33
free(caches_zdjbfft[id].ptr);
37
/**************** FFTW *****************************/
39
GEN_CACHE(zfftw,(int n,int d)
42
,((caches_zfftw[i].n==n) &&
43
(caches_zfftw[i].direction==d))
44
,caches_zfftw[id].direction = d;
45
caches_zfftw[id].plan = fftw_create_plan(n,
46
(d>0?FFTW_FORWARD:FFTW_BACKWARD),
47
FFTW_IN_PLACE|FFTW_ESTIMATE);
48
,fftw_destroy_plan(caches_zfftw[id].plan);
51
/**************** FFTPACK ZFFT **********************/
52
extern void F_FUNC(zfftf,ZFFTF)(int*,double*,double*);
53
extern void F_FUNC(zfftb,ZFFTB)(int*,double*,double*);
54
extern void F_FUNC(zffti,ZFFTI)(int*,double*);
55
GEN_CACHE(zfftpack,(int n)
57
,(caches_zfftpack[i].n==n)
58
,caches_zfftpack[id].wsave = (double*)malloc(sizeof(double)*(4*n+15));
59
F_FUNC(zffti,ZFFTI)(&n,caches_zfftpack[id].wsave);
60
,free(caches_zfftpack[id].wsave);
64
extern void destroy_zfft_cache(void) {
66
destroy_zfftwork_caches();
69
destroy_zdjbfft_caches();
72
destroy_zfftw_caches();
74
destroy_zfftpack_caches();
78
/**************** ZFFT function **********************/
79
extern void zfft(complex_double *inout,
80
int n,int direction,int howmany,int normalize) {
82
complex_double *ptr = inout;
84
fftw_plan plan = NULL;
89
coef_dbl* coef = NULL;
93
complex_double *ptrc = NULL;
94
unsigned int *f = NULL;
97
if (ispow2le2e30(n)) {
98
i = get_cache_id_zfftwork(n);
99
coef = caches_zfftwork[i].coef;
104
case 2:;case 4:;case 8:;case 16:;case 32:;case 64:;case 128:;case 256:;
105
case 512:;case 1024:;case 2048:;case 4096:;case 8192:
106
i = get_cache_id_zdjbfft(n);
107
f = caches_zdjbfft[i].f;
108
ptrc = (complex_double*)caches_zdjbfft[i].ptr;
113
plan = caches_zfftw[get_cache_id_zfftw(n,direction)].plan;
115
wsave = caches_zfftpack[get_cache_id_zfftpack(n)].wsave;
121
for (i=0;i<howmany;++i,ptr+=n) {
124
fft_for_cplx_flt((cplx_dbl*)ptr,coef,n);
129
memcpy(ptrc,ptr,2*n*sizeof(double));
131
#define TMPCASE(N) case N: fftc8_##N(ptrc); break
132
TMPCASE(2);TMPCASE(4);TMPCASE(8);TMPCASE(16);TMPCASE(32);
133
TMPCASE(64);TMPCASE(128);TMPCASE(256);TMPCASE(512);
134
TMPCASE(1024);TMPCASE(2048);TMPCASE(4096);TMPCASE(8192);
137
for (j=0;j<n;++j) *(ptr+f[j]) = *(ptrc+j);
141
fftw_one(plan,(fftw_complex*)ptr,NULL);
143
F_FUNC(zfftf,ZFFTF)(&n,(double*)(ptr),wsave);
149
for (i=0;i<howmany;++i,ptr+=n) {
152
fft_bak_cplx_flt((cplx_dbl*)ptr,coef,n);
157
for (j=0;j<n;++j) *(ptrc+j) = *(ptr+f[j]);
159
#define TMPCASE(N) case N: fftc8_un##N(ptrc); break
160
TMPCASE(2);TMPCASE(4);TMPCASE(8);TMPCASE(16);TMPCASE(32);
161
TMPCASE(64);TMPCASE(128);TMPCASE(256);TMPCASE(512);
162
TMPCASE(1024);TMPCASE(2048);TMPCASE(4096);TMPCASE(8192);
165
memcpy(ptr,ptrc,2*n*sizeof(double));
169
fftw_one(plan,(fftw_complex*)ptr,NULL);
171
F_FUNC(zfftb,ZFFTB)(&n,(double*)(ptr),wsave);
177
fprintf(stderr,"zfft: invalid direction=%d\n",direction);
184
for (i=0;i<howmany;++i,ptr+=n) {
186
#define TMPCASE(N) case N: fftc8_scale##N(ptr); break
187
TMPCASE(2);TMPCASE(4);TMPCASE(8);TMPCASE(16);TMPCASE(32);
188
TMPCASE(64);TMPCASE(128);TMPCASE(256);TMPCASE(512);
189
TMPCASE(1024);TMPCASE(2048);TMPCASE(4096);TMPCASE(8192);
195
for (i=n*howmany-1;i>=0;--i) {
196
*((double*)(ptr)) /= n;
197
*((double*)(ptr++)+1) /= n;