fft.c 5 KB
Newer Older
Emmanuel Bertin's avatar
Emmanuel Bertin committed
1
2
3
4
5
6
7
8
9
/*
                                  fft.c

*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
*       Part of:        A program that uses FFTs
*
*       Author:         E.BERTIN (IAP)
*
10
*       Contents:       Routines dealing with float precision FFT.
Emmanuel Bertin's avatar
Emmanuel Bertin committed
11
*
12
*       Last modify:    26/06/2009
Emmanuel Bertin's avatar
Emmanuel Bertin committed
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#include <fftw3.h>

#include "define.h"
#include "globals.h"
#include "fft.h"
#include "prefs.h"
#ifdef USE_THREADS
#include "threads.h"
#endif

 int    firsttimeflag;
#ifdef USE_THREADS
 pthread_mutex_t	fftmutex;
#endif

#define SWAP(a,b)       tempr=(a);(a)=(b);(b)=tempr

/****** fft_init ************************************************************
PROTO	void fft_init(void)
PURPOSE	Initialize the FFT routines
INPUT	-.
OUTPUT	-.
NOTES	Global preferences are used for multhreading.
AUTHOR	E. Bertin (IAP)
49
VERSION	26/06/2009
Emmanuel Bertin's avatar
Emmanuel Bertin committed
50
 ***/
51
void    fft_init(int nthreads)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
52
53
54
55
56
 {
  if (!firsttimeflag)
    {
#ifdef USE_THREADS
    QPTHREAD_MUTEX_INIT(&fftmutex, NULL);
57
#ifdef HAVE_FFTW_MP
58
59
60
61
    if (nthreads > 1)
      {
      if (!fftw_init_threads())
        error(EXIT_FAILURE, "*Error*: thread initialization failed in ", "FFTW");
62
      fftwf_plan_with_nthreads(prefs.nthreads);
63
      }
64
#endif
Emmanuel Bertin's avatar
Emmanuel Bertin committed
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#endif
    firsttimeflag = 1;
    }

  return;
  }


/****** fft_end ************************************************************
PROTO	void fft_init(void)
PURPOSE	Clear up stuff set by FFT routines
INPUT	-.
OUTPUT	-.
NOTES	-.
AUTHOR	E. Bertin (IAP)
80
VERSION	26/06/2009
Emmanuel Bertin's avatar
Emmanuel Bertin committed
81
82
83
84
85
86
87
88
 ***/
void    fft_end(void)
 {

  if (firsttimeflag)
    {
    firsttimeflag = 0;
#ifdef USE_THREADS
89
#ifdef HAVE_FFTW_MP
90
    fftwf_cleanup_threads();
91
#endif
Emmanuel Bertin's avatar
Emmanuel Bertin committed
92
93
    QPTHREAD_MUTEX_DESTROY(&fftmutex);
#endif
94
    fftwf_cleanup();
Emmanuel Bertin's avatar
Emmanuel Bertin committed
95
96
97
98
99
100
101
    }

  return;
  }


/****** fft_conv ************************************************************
102
PROTO	void fft_conv(float *data1, float *fdata2, int *size)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
103
104
105
106
107
108
PURPOSE	Optimized 2-dimensional FFT convolution using the FFTW library.
INPUT	ptr to the first image,
	ptr to the Fourier transform of the second image,
	image size vector.
OUTPUT	-.
NOTES	For data1 and fdata2, memory must be allocated for
109
	size[0]* ... * 2*(size[naxis-1]/2+1) floats (padding required).
Emmanuel Bertin's avatar
Emmanuel Bertin committed
110
111
112
AUTHOR	E. Bertin (IAP)
VERSION	26/03/2007
 ***/
113
void    fft_conv(float *data1, float *fdata2, int *size)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
114
  {
115
116
   fftwf_plan	plan;
   float	*fdata1,*fdata1p,*fdata2p,
Emmanuel Bertin's avatar
Emmanuel Bertin committed
117
118
119
120
121
122
123
124
125
126
127
		real,imag, fac;
   int		i, npix,npix2;

/* Convert axis indexing to that of FFTW */
  npix = size[0]*size[1];
  npix2 = (((size[0]/2) + 1)*2) * size[1];

/* Forward FFT "in place" for data1 */
#ifdef USE_THREADS
  QPTHREAD_MUTEX_LOCK(&fftmutex);
#endif
128
129
130
  QFFTWMALLOC(fdata1, float, npix2);
  plan = fftwf_plan_dft_r2c_2d(size[1], size[0], data1,
        (fftwf_complex *)fdata1, FFTW_ESTIMATE|FFTW_DESTROY_INPUT);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
131
132
133
#ifdef USE_THREADS
  QPTHREAD_MUTEX_UNLOCK(&fftmutex);
#endif
134
  fftwf_execute(plan);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
135
136
137
138

#ifdef USE_THREADS
  QPTHREAD_MUTEX_LOCK(&fftmutex);
#endif
139
  fftwf_destroy_plan(plan);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#ifdef USE_THREADS
  QPTHREAD_MUTEX_UNLOCK(&fftmutex);
#endif

/* Actual convolution (Fourier product) */
  fac = 1.0/npix;  
  fdata1p = fdata1;
  fdata2p = fdata2;
  for (i=npix2/2; i--; fdata2p+=2)
    {
    real = *fdata1p **fdata2p - *(fdata1p+1)**(fdata2p+1);
    imag = *(fdata1p+1)**fdata2p + *fdata1p**(fdata2p+1);
    *(fdata1p++) = fac*real;
    *(fdata1p++) = fac*imag;
    }

/* Reverse FFT */
#ifdef USE_THREADS
  QPTHREAD_MUTEX_LOCK(&fftmutex);
#endif
160
  plan = fftwf_plan_dft_c2r_2d(size[1], size[0], (fftwf_complex *)fdata1, 
Emmanuel Bertin's avatar
Emmanuel Bertin committed
161
162
163
164
165
        data1, FFTW_ESTIMATE|FFTW_DESTROY_INPUT);
#ifdef USE_THREADS
  QPTHREAD_MUTEX_UNLOCK(&fftmutex);
#endif

166
  fftwf_execute(plan);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
167
168
169
170

#ifdef USE_THREADS
  QPTHREAD_MUTEX_LOCK(&fftmutex);
#endif
171
  fftwf_destroy_plan(plan);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
172
173
174
175
176
177
178
179
180
181
182
/* Free the fdata1 scratch array */
  QFFTWFREE(fdata1);
#ifdef USE_THREADS
  QPTHREAD_MUTEX_UNLOCK(&fftmutex);
#endif

  return;
  }


/****** fft_rtf ************************************************************
183
PROTO	float *fft_rtf(float *data, int *size)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
184
185
186
187
188
189
190
191
PURPOSE	Optimized 2-dimensional FFT "in place" using the FFTW library.
INPUT	ptr to the image,
	ptr to image size vector.
OUTPUT	Pointer to the compressed, memory-allocated Fourier transform.
NOTES	Input data may end up corrupted.
AUTHOR	E. Bertin (IAP)
VERSION	26/03/2007
 ***/
192
float	*fft_rtf(float *data, int *size)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
193
  {
194
195
196
   fftwf_plan   	plan;
   fftwf_complex	*fdata;
   int			npix2;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
197
198
199
200
201
202
203
204

/* Convert axis indexing to that of FFTW */
  npix2 = ((size[0]/2) + 1) * size[1];

/* Forward FFT "in place" for data1 */
#ifdef USE_THREADS
  QPTHREAD_MUTEX_LOCK(&fftmutex);
#endif
205
206
  QFFTWMALLOC(fdata, fftwf_complex, npix2);
  plan = fftwf_plan_dft_r2c_2d(size[1], size[0], data,
Emmanuel Bertin's avatar
Emmanuel Bertin committed
207
208
209
210
        fdata, FFTW_ESTIMATE|FFTW_DESTROY_INPUT);
#ifdef USE_THREADS
  QPTHREAD_MUTEX_UNLOCK(&fftmutex);
#endif
211
  fftwf_execute(plan);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
212
213
214
#ifdef USE_THREADS
  QPTHREAD_MUTEX_LOCK(&fftmutex);
#endif
215
  fftwf_destroy_plan(plan);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
216
217
218
219
#ifdef USE_THREADS
  QPTHREAD_MUTEX_UNLOCK(&fftmutex);
#endif

220
  return (float *)fdata;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
221
222
223
  }