1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
4 * Gromacs 4.0 Copyright (c) 1991-2003
5 * Erik Lindahl, David van der Spoel, University of Groningen.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * To help us fund GROMACS development, we humbly ask that you cite
13 * the research papers on the package. Check out http://www.gromacs.org
16 * Gnomes, ROck Monsters And Chili Sauce
28 #include "types/simple.h"
29 #include "gmxcomplex.h"
32 #include "gmx_fatal.h"
35 /* This file contains common fft utility functions, but not
36 * the actual transform implementations. Check the
37 * files like gmx_fft_fftw3.c or gmx_fft_intel_mkl.c for that.
48 typedef struct gmx_many_fft* gmx_many_fft_t;
51 gmx_fft_init_many_1d(gmx_fft_t * pfft,
59 gmx_fatal(FARGS, "Invalid opaque FFT datatype pointer.");
64 if ( (fft = (gmx_many_fft_t)malloc(sizeof(struct gmx_many_fft))) == NULL)
69 gmx_fft_init_1d(&fft->fft, nx, flags);
70 fft->howmany = howmany;
73 *pfft = (gmx_fft_t)fft;
78 gmx_fft_init_many_1d_real(gmx_fft_t * pfft,
86 gmx_fatal(FARGS, "Invalid opaque FFT datatype pointer.");
91 if ( (fft = (gmx_many_fft_t)malloc(sizeof(struct gmx_many_fft))) == NULL)
96 gmx_fft_init_1d_real(&fft->fft, nx, flags);
97 fft->howmany = howmany;
98 fft->dist = 2*(nx/2+1);
100 *pfft = (gmx_fft_t)fft;
105 gmx_fft_many_1d (gmx_fft_t fft,
106 enum gmx_fft_direction dir,
110 gmx_many_fft_t mfft = (gmx_many_fft_t)fft;
112 for (i = 0; i < mfft->howmany; i++)
114 ret = gmx_fft_1d(mfft->fft, dir, in_data, out_data);
119 in_data = (real*)in_data+mfft->dist;
120 out_data = (real*)out_data+mfft->dist;
126 gmx_fft_many_1d_real (gmx_fft_t fft,
127 enum gmx_fft_direction dir,
131 gmx_many_fft_t mfft = (gmx_many_fft_t)fft;
133 for (i = 0; i < mfft->howmany; i++)
135 ret = gmx_fft_1d_real(mfft->fft, dir, in_data, out_data);
140 in_data = (real*)in_data+mfft->dist;
141 out_data = (real*)out_data+mfft->dist;
148 gmx_many_fft_destroy(gmx_fft_t fft)
150 gmx_many_fft_t mfft = (gmx_many_fft_t)fft;
153 if (mfft->fft != NULL)
155 gmx_fft_destroy(mfft->fft);
161 #endif //not GMX_FFT_FFTW3
163 int gmx_fft_transpose_2d(t_complex * in_data,
164 t_complex * out_data,
168 int i, j, k, im, n, ncount, done1, done2;
169 int i1, i1c, i2, i2c, kmi, max;
171 t_complex tmp1, tmp2, tmp3;
174 /* Use 500 bytes on stack to indicate moves.
175 * This is just for optimization, it does not limit any dimensions.
180 if (nx < 2 || ny < 2)
182 if (in_data != out_data)
184 memcpy(out_data, in_data, sizeof(t_complex)*nx*ny);
189 /* Out-of-place transposes are easy */
190 if (in_data != out_data)
192 for (i = 0; i < nx; i++)
194 for (j = 0; j < ny; j++)
196 out_data[j*nx+i].re = in_data[i*ny+j].re;
197 out_data[j*nx+i].im = in_data[i*ny+j].im;
203 /* In-place transform. in_data=out_data=data */
208 /* trivial case, just swap elements */
209 for (i = 0; i < nx; i++)
211 for (j = i+1; j < nx; j++)
213 tmp1.re = data[i*nx+j].re;
214 tmp1.im = data[i*nx+j].im;
215 data[i*nx+j].re = data[j*nx+i].re;
216 data[i*nx+j].im = data[j*nx+i].im;
217 data[j*nx+i].re = tmp1.re;
218 data[j*nx+i].im = tmp1.im;
224 for (i = 0; i < nmove; i++)
231 if (nx > 2 && ny > 2)
255 tmp1.re = data[i1].re;
256 tmp1.im = data[i1].im;
258 tmp2.re = data[i1c].re;
259 tmp2.im = data[i1c].im;
264 i2 = ny*i1-k*(i1/nx);
291 data[i1].re = data[i2].re;
292 data[i1].im = data[i2].im;
293 data[i1c].re = data[i2c].re;
294 data[i1c].im = data[i2c].im;
301 data[i1].re = tmp1.re;
302 data[i1].im = tmp1.im;
303 data[i1c].re = tmp2.re;
304 data[i1c].im = tmp2.im;
327 while (i2 > i && i2 < max)
330 i2 = ny*i1-k*(i1/nx);