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
27 #include "types/simple.h"
28 #include "gmxcomplex.h"
29 #include "gmx_fatal.h"
30 #include "gromacs/fft/fft.h"
33 /* This file contains common fft utility functions, but not
34 * the actual transform implementations. Check the
35 * files like fft_fftw3.c or fft_mkl.c for that.
46 typedef struct gmx_many_fft* gmx_many_fft_t;
49 gmx_fft_init_many_1d(gmx_fft_t * pfft,
57 gmx_fatal(FARGS, "Invalid opaque FFT datatype pointer.");
62 if ( (fft = (gmx_many_fft_t)malloc(sizeof(struct gmx_many_fft))) == NULL)
67 gmx_fft_init_1d(&fft->fft, nx, flags);
68 fft->howmany = howmany;
71 *pfft = (gmx_fft_t)fft;
76 gmx_fft_init_many_1d_real(gmx_fft_t * pfft,
84 gmx_fatal(FARGS, "Invalid opaque FFT datatype pointer.");
89 if ( (fft = (gmx_many_fft_t)malloc(sizeof(struct gmx_many_fft))) == NULL)
94 gmx_fft_init_1d_real(&fft->fft, nx, flags);
95 fft->howmany = howmany;
96 fft->dist = 2*(nx/2+1);
98 *pfft = (gmx_fft_t)fft;
103 gmx_fft_many_1d (gmx_fft_t fft,
104 enum gmx_fft_direction dir,
108 gmx_many_fft_t mfft = (gmx_many_fft_t)fft;
110 for (i = 0; i < mfft->howmany; i++)
112 ret = gmx_fft_1d(mfft->fft, dir, in_data, out_data);
117 in_data = (real*)in_data+mfft->dist;
118 out_data = (real*)out_data+mfft->dist;
124 gmx_fft_many_1d_real (gmx_fft_t fft,
125 enum gmx_fft_direction dir,
129 gmx_many_fft_t mfft = (gmx_many_fft_t)fft;
131 for (i = 0; i < mfft->howmany; i++)
133 ret = gmx_fft_1d_real(mfft->fft, dir, in_data, out_data);
138 in_data = (real*)in_data+mfft->dist;
139 out_data = (real*)out_data+mfft->dist;
146 gmx_many_fft_destroy(gmx_fft_t fft)
148 gmx_many_fft_t mfft = (gmx_many_fft_t)fft;
151 if (mfft->fft != NULL)
153 gmx_fft_destroy(mfft->fft);
159 #endif //not GMX_FFT_FFTW3
161 int gmx_fft_transpose_2d(t_complex * in_data,
162 t_complex * out_data,
166 int i, j, k, im, n, ncount, done1, done2;
167 int i1, i1c, i2, i2c, kmi, max;
169 t_complex tmp1, tmp2, tmp3;
172 /* Use 500 bytes on stack to indicate moves.
173 * This is just for optimization, it does not limit any dimensions.
178 if (nx < 2 || ny < 2)
180 if (in_data != out_data)
182 memcpy(out_data, in_data, sizeof(t_complex)*nx*ny);
187 /* Out-of-place transposes are easy */
188 if (in_data != out_data)
190 for (i = 0; i < nx; i++)
192 for (j = 0; j < ny; j++)
194 out_data[j*nx+i].re = in_data[i*ny+j].re;
195 out_data[j*nx+i].im = in_data[i*ny+j].im;
201 /* In-place transform. in_data=out_data=data */
206 /* trivial case, just swap elements */
207 for (i = 0; i < nx; i++)
209 for (j = i+1; j < nx; j++)
211 tmp1.re = data[i*nx+j].re;
212 tmp1.im = data[i*nx+j].im;
213 data[i*nx+j].re = data[j*nx+i].re;
214 data[i*nx+j].im = data[j*nx+i].im;
215 data[j*nx+i].re = tmp1.re;
216 data[j*nx+i].im = tmp1.im;
222 for (i = 0; i < nmove; i++)
229 if (nx > 2 && ny > 2)
253 tmp1.re = data[i1].re;
254 tmp1.im = data[i1].im;
256 tmp2.re = data[i1c].re;
257 tmp2.im = data[i1c].im;
262 i2 = ny*i1-k*(i1/nx);
289 data[i1].re = data[i2].re;
290 data[i1].im = data[i2].im;
291 data[i1c].re = data[i2c].re;
292 data[i1c].im = data[i2c].im;
299 data[i1].re = tmp1.re;
300 data[i1].im = tmp1.im;
301 data[i1c].re = tmp2.re;
302 data[i1c].im = tmp2.im;
325 while (i2 > i && i2 < max)
328 i2 = ny*i1-k*(i1/nx);