Remove all unnecessary HAVE_CONFIG_H
[gromacs.git] / src / gromacs / fft / fft.c
blob27b409cfb441a303cc09ecc64af32fddfb23723c
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2003 Erik Lindahl, David van der Spoel, University of Groningen.
5 * Copyright (c) 2013,2014, by the GROMACS development team, led by
6 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
7 * and including many others, as listed in the AUTHORS file in the
8 * top-level source directory and at http://www.gromacs.org.
10 * GROMACS is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public License
12 * as published by the Free Software Foundation; either version 2.1
13 * of the License, or (at your option) any later version.
15 * GROMACS is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with GROMACS; if not, see
22 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 * If you want to redistribute modifications to GROMACS, please
26 * consider that scientific software is very special. Version
27 * control is crucial - bugs must be traceable. We will be happy to
28 * consider code for inclusion in the official distribution, but
29 * derived work must not be called official GROMACS. Details are found
30 * in the README & COPYING files - if they are missing, get the
31 * official version at http://www.gromacs.org.
33 * To help us fund GROMACS development, we humbly ask that you cite
34 * the research papers on the package. Check out http://www.gromacs.org.
36 #include "gromacs/fft/fft.h"
38 #include "config.h"
40 #include <errno.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
45 #include "gromacs/math/gmxcomplex.h"
46 #include "gromacs/utility/fatalerror.h"
47 #include "gromacs/utility/real.h"
49 /* This file contains common fft utility functions, but not
50 * the actual transform implementations. Check the
51 * files like fft_fftw3.c or fft_mkl.c for that.
54 #ifndef GMX_FFT_FFTW3
56 struct gmx_many_fft {
57 int howmany;
58 int dist;
59 gmx_fft_t fft;
62 typedef struct gmx_many_fft* gmx_many_fft_t;
64 int
65 gmx_fft_init_many_1d(gmx_fft_t * pfft,
66 int nx,
67 int howmany,
68 gmx_fft_flag flags)
70 gmx_many_fft_t fft;
71 if (pfft == NULL)
73 gmx_fatal(FARGS, "Invalid opaque FFT datatype pointer.");
74 return EINVAL;
76 *pfft = NULL;
78 if ( (fft = (gmx_many_fft_t)malloc(sizeof(struct gmx_many_fft))) == NULL)
80 return ENOMEM;
83 gmx_fft_init_1d(&fft->fft, nx, flags);
84 fft->howmany = howmany;
85 fft->dist = 2*nx;
87 *pfft = (gmx_fft_t)fft;
88 return 0;
91 int
92 gmx_fft_init_many_1d_real(gmx_fft_t * pfft,
93 int nx,
94 int howmany,
95 gmx_fft_flag flags)
97 gmx_many_fft_t fft;
98 if (pfft == NULL)
100 gmx_fatal(FARGS, "Invalid opaque FFT datatype pointer.");
101 return EINVAL;
103 *pfft = NULL;
105 if ( (fft = (gmx_many_fft_t)malloc(sizeof(struct gmx_many_fft))) == NULL)
107 return ENOMEM;
110 gmx_fft_init_1d_real(&fft->fft, nx, flags);
111 fft->howmany = howmany;
112 fft->dist = 2*(nx/2+1);
114 *pfft = (gmx_fft_t)fft;
115 return 0;
119 gmx_fft_many_1d (gmx_fft_t fft,
120 enum gmx_fft_direction dir,
121 void * in_data,
122 void * out_data)
124 gmx_many_fft_t mfft = (gmx_many_fft_t)fft;
125 int i, ret;
126 for (i = 0; i < mfft->howmany; i++)
128 ret = gmx_fft_1d(mfft->fft, dir, in_data, out_data);
129 if (ret != 0)
131 return ret;
133 in_data = (real*)in_data+mfft->dist;
134 out_data = (real*)out_data+mfft->dist;
136 return 0;
140 gmx_fft_many_1d_real (gmx_fft_t fft,
141 enum gmx_fft_direction dir,
142 void * in_data,
143 void * out_data)
145 gmx_many_fft_t mfft = (gmx_many_fft_t)fft;
146 int i, ret;
147 for (i = 0; i < mfft->howmany; i++)
149 ret = gmx_fft_1d_real(mfft->fft, dir, in_data, out_data);
150 if (ret != 0)
152 return ret;
154 in_data = (real*)in_data+mfft->dist;
155 out_data = (real*)out_data+mfft->dist;
157 return 0;
161 void
162 gmx_many_fft_destroy(gmx_fft_t fft)
164 gmx_many_fft_t mfft = (gmx_many_fft_t)fft;
165 if (mfft != NULL)
167 if (mfft->fft != NULL)
169 gmx_fft_destroy(mfft->fft);
171 free(mfft);
175 #endif //not GMX_FFT_FFTW3
177 int gmx_fft_transpose_2d(t_complex * in_data,
178 t_complex * out_data,
179 int nx,
180 int ny)
182 int i, j, k, im, n, ncount, done1, done2;
183 int i1, i1c, i2, i2c, kmi, max;
185 t_complex tmp1, tmp2, tmp3;
186 t_complex *data;
188 /* Use 500 bytes on stack to indicate moves.
189 * This is just for optimization, it does not limit any dimensions.
191 char move[500];
192 int nmove = 500;
194 if (nx < 2 || ny < 2)
196 if (in_data != out_data)
198 memcpy(out_data, in_data, sizeof(t_complex)*nx*ny);
200 return 0;
203 /* Out-of-place transposes are easy */
204 if (in_data != out_data)
206 for (i = 0; i < nx; i++)
208 for (j = 0; j < ny; j++)
210 out_data[j*nx+i].re = in_data[i*ny+j].re;
211 out_data[j*nx+i].im = in_data[i*ny+j].im;
214 return 0;
217 /* In-place transform. in_data=out_data=data */
218 data = in_data;
220 if (nx == ny)
222 /* trivial case, just swap elements */
223 for (i = 0; i < nx; i++)
225 for (j = i+1; j < nx; j++)
227 tmp1.re = data[i*nx+j].re;
228 tmp1.im = data[i*nx+j].im;
229 data[i*nx+j].re = data[j*nx+i].re;
230 data[i*nx+j].im = data[j*nx+i].im;
231 data[j*nx+i].re = tmp1.re;
232 data[j*nx+i].im = tmp1.im;
235 return 0;
238 for (i = 0; i < nmove; i++)
240 move[i] = 0;
243 ncount = 2;
245 if (nx > 2 && ny > 2)
247 i = nx-1;
248 j = ny-1;
251 k = i % j;
252 i = j;
253 j = k;
255 while (k);
256 ncount += i-1;
259 n = nx*ny;
260 k = n - 1;
261 i = 1;
262 im = ny;
264 done1 = 0;
267 i1 = i;
268 kmi = k-i;
269 tmp1.re = data[i1].re;
270 tmp1.im = data[i1].im;
271 i1c = kmi;
272 tmp2.re = data[i1c].re;
273 tmp2.im = data[i1c].im;
275 done2 = 0;
278 i2 = ny*i1-k*(i1/nx);
279 i2c = k-i2;
280 if (i1 < nmove)
282 move[i1] = 1;
284 if (i1c < nmove)
286 move[i1c] = 1;
288 ncount += 2;
289 if (i2 == i)
291 done2 = 1;
293 else if (i2 == kmi)
295 tmp3.re = tmp1.re;
296 tmp3.im = tmp1.im;
297 tmp1.re = tmp2.re;
298 tmp1.im = tmp2.im;
299 tmp2.re = tmp3.re;
300 tmp2.im = tmp3.im;
301 done2 = 1;
303 else
305 data[i1].re = data[i2].re;
306 data[i1].im = data[i2].im;
307 data[i1c].re = data[i2c].re;
308 data[i1c].im = data[i2c].im;
309 i1 = i2;
310 i1c = i2c;
313 while (!done2);
315 data[i1].re = tmp1.re;
316 data[i1].im = tmp1.im;
317 data[i1c].re = tmp2.re;
318 data[i1c].im = tmp2.im;
320 if (ncount >= n)
322 done1 = 1;
324 else
326 done2 = 0;
329 max = k-i;
330 i++;
331 im += ny;
332 if (im > k)
334 im -= k;
336 i2 = im;
337 if (i != i2)
339 if (i >= nmove)
341 while (i2 > i && i2 < max)
343 i1 = i2;
344 i2 = ny*i1-k*(i1/nx);
346 if (i2 == i)
348 done2 = 1;
351 else if (!move[i])
353 done2 = 1;
357 while (!done2);
360 while (!done1);
362 return 0;