3 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or (at
8 * your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 FUNCTION(gsl_fft_complex,radix2_forward) (TYPE(gsl_complex_packed_array) data,
22 const size_t stride, const size_t n)
24 gsl_fft_direction sign = gsl_fft_forward;
25 int status = FUNCTION(gsl_fft_complex,radix2_transform) (data, stride, n, sign);
30 FUNCTION(gsl_fft_complex,radix2_backward) (TYPE(gsl_complex_packed_array) data,
31 const size_t stride, const size_t n)
33 gsl_fft_direction sign = gsl_fft_backward;
34 int status = FUNCTION(gsl_fft_complex,radix2_transform) (data, stride, n, sign);
39 FUNCTION(gsl_fft_complex,radix2_inverse) (TYPE(gsl_complex_packed_array) data,
40 const size_t stride, const size_t n)
42 gsl_fft_direction sign = gsl_fft_backward;
43 int status = FUNCTION(gsl_fft_complex,radix2_transform) (data, stride, n, sign);
50 /* normalize inverse fft with 1/n */
53 const ATOMIC norm = 1.0 / n;
55 for (i = 0; i < n; i++)
57 REAL(data,stride,i) *= norm;
58 IMAG(data,stride,i) *= norm;
68 FUNCTION(gsl_fft_complex,radix2_transform) (TYPE(gsl_complex_packed_array) data,
71 const gsl_fft_direction sign)
79 if (n == 1) /* identity operation */
84 /* make sure that n is a power of 2 */
86 result = fft_binary_logn(n) ;
90 GSL_ERROR ("n is not a power of 2", GSL_EINVAL);
97 /* bit reverse the ordering of input data for decimation in time algorithm */
99 status = FUNCTION(fft_complex,bitreverse_order) (data, stride, n, logn) ;
101 /* apply fft recursion */
105 for (bit = 0; bit < logn; bit++)
110 const double theta = 2.0 * ((int) sign) * M_PI / (2.0 * (double) dual);
112 const ATOMIC s = sin (theta);
113 const ATOMIC t = sin (theta / 2.0);
114 const ATOMIC s2 = 2.0 * t * t;
120 for (b = 0; b < n; b += 2 * dual)
123 const size_t j = b + dual;
125 const ATOMIC z1_real = REAL(data,stride,j) ;
126 const ATOMIC z1_imag = IMAG(data,stride,j) ;
128 const ATOMIC wd_real = z1_real ;
129 const ATOMIC wd_imag = z1_imag ;
131 REAL(data,stride,j) = REAL(data,stride,i) - wd_real;
132 IMAG(data,stride,j) = IMAG(data,stride,i) - wd_imag;
133 REAL(data,stride,i) += wd_real;
134 IMAG(data,stride,i) += wd_imag;
137 /* a = 1 .. (dual-1) */
139 for (a = 1; a < dual; a++)
142 /* trignometric recurrence for w-> exp(i theta) w */
145 const ATOMIC tmp_real = w_real - s * w_imag - s2 * w_real;
146 const ATOMIC tmp_imag = w_imag + s * w_real - s2 * w_imag;
151 for (b = 0; b < n; b += 2 * dual)
153 const size_t i = b + a;
154 const size_t j = b + a + dual;
156 const ATOMIC z1_real = REAL(data,stride,j) ;
157 const ATOMIC z1_imag = IMAG(data,stride,j) ;
159 const ATOMIC wd_real = w_real * z1_real - w_imag * z1_imag;
160 const ATOMIC wd_imag = w_real * z1_imag + w_imag * z1_real;
162 REAL(data,stride,j) = REAL(data,stride,i) - wd_real;
163 IMAG(data,stride,j) = IMAG(data,stride,i) - wd_imag;
164 REAL(data,stride,i) += wd_real;
165 IMAG(data,stride,i) += wd_imag;
177 FUNCTION(gsl_fft_complex,radix2_dif_forward) (TYPE(gsl_complex_packed_array) data,
181 gsl_fft_direction sign = gsl_fft_forward;
182 int status = FUNCTION(gsl_fft_complex,radix2_dif_transform) (data, stride, n, sign);
187 FUNCTION(gsl_fft_complex,radix2_dif_backward) (TYPE(gsl_complex_packed_array) data,
191 gsl_fft_direction sign = gsl_fft_backward;
192 int status = FUNCTION(gsl_fft_complex,radix2_dif_transform) (data, stride, n, sign);
197 FUNCTION(gsl_fft_complex,radix2_dif_inverse) (TYPE(gsl_complex_packed_array) data,
201 gsl_fft_direction sign = gsl_fft_backward;
202 int status = FUNCTION(gsl_fft_complex,radix2_dif_transform) (data, stride, n, sign);
209 /* normalize inverse fft with 1/n */
212 const ATOMIC norm = 1.0 / n;
214 for (i = 0; i < n; i++)
216 REAL(data,stride,i) *= norm;
217 IMAG(data,stride,i) *= norm;
225 FUNCTION(gsl_fft_complex,radix2_dif_transform) (TYPE(gsl_complex_packed_array) data,
228 const gsl_fft_direction sign)
236 if (n == 1) /* identity operation */
241 /* make sure that n is a power of 2 */
243 result = fft_binary_logn(n) ;
247 GSL_ERROR ("n is not a power of 2", GSL_EINVAL);
254 /* apply fft recursion */
258 for (bit = 0; bit < logn; bit++)
263 const double theta = 2.0 * ((int) sign) * M_PI / ((double) (2 * dual));
265 const ATOMIC s = sin (theta);
266 const ATOMIC t = sin (theta / 2.0);
267 const ATOMIC s2 = 2.0 * t * t;
271 for (b = 0; b < dual; b++)
273 for (a = 0; a < n; a+= 2 * dual)
275 const size_t i = b + a;
276 const size_t j = b + a + dual;
278 const ATOMIC t1_real = REAL(data,stride,i) + REAL(data,stride,j);
279 const ATOMIC t1_imag = IMAG(data,stride,i) + IMAG(data,stride,j);
280 const ATOMIC t2_real = REAL(data,stride,i) - REAL(data,stride,j);
281 const ATOMIC t2_imag = IMAG(data,stride,i) - IMAG(data,stride,j);
283 REAL(data,stride,i) = t1_real;
284 IMAG(data,stride,i) = t1_imag;
285 REAL(data,stride,j) = w_real*t2_real - w_imag * t2_imag;
286 IMAG(data,stride,j) = w_real*t2_imag + w_imag * t2_real;
289 /* trignometric recurrence for w-> exp(i theta) w */
292 const ATOMIC tmp_real = w_real - s * w_imag - s2 * w_real;
293 const ATOMIC tmp_imag = w_imag + s * w_real - s2 * w_imag;
301 /* bit reverse the ordering of output data for decimation in
302 frequency algorithm */
304 status = FUNCTION(fft_complex,bitreverse_order)(data, stride, n, logn) ;