| Bsoft 1.9 Bernard's software package

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

executor.c
Go to the documentation of this file.
1 /*
2 * Copyright (c) 1997-1999, 2003 Massachusetts Institute of Technology
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 */
19
20 /*
21 * executor.c -- execute the fft
22 */
23
24 /* $Id: executor.c,v 1.68 2003/03/16 23:43:46 stevenj Exp $ */
25 #include "fftw-int.h"
26 #include <stdio.h>
27 #include <stdlib.h>
28
29 const char *fftw_version = "FFTW V" FFTW_VERSION " ($Id: executor.c,v 1.68 2003/03/16 23:43:46 stevenj Exp $)";
30
31 /*
32 * This function is called in other files, so we cannot declare
33 * it static.
34 */
35 void fftw_strided_copy(int n, fftw_complex *in, int ostride,
36 fftw_complex *out)
37 {
38 int i;
39 fftw_real r0, r1, i0, i1;
40 fftw_real r2, r3, i2, i3;
41
42 i = 0;
43
44 for (; i < (n & 3); ++i) {
45 out[i * ostride] = in[i];
46 }
47
48 for (; i < n; i += 4) {
49 r0 = c_re(in[i]);
50 i0 = c_im(in[i]);
51 r1 = c_re(in[i + 1]);
52 i1 = c_im(in[i + 1]);
53 r2 = c_re(in[i + 2]);
54 i2 = c_im(in[i + 2]);
55 r3 = c_re(in[i + 3]);
56 i3 = c_im(in[i + 3]);
57 c_re(out[i * ostride]) = r0;
58 c_im(out[i * ostride]) = i0;
59 c_re(out[(i + 1) * ostride]) = r1;
60 c_im(out[(i + 1) * ostride]) = i1;
61 c_re(out[(i + 2) * ostride]) = r2;
62 c_im(out[(i + 2) * ostride]) = i2;
63 c_re(out[(i + 3) * ostride]) = r3;
64 c_im(out[(i + 3) * ostride]) = i3;
65 }
66 }
67
68 static void executor_many(int n, const fftw_complex *in,
69 fftw_complex *out,
70 fftw_plan_node *p,
71 int istride,
72 int ostride,
73 int howmany, int idist, int odist,
74 fftw_recurse_kind recurse_kind)
75 {
76 int s;
77
78 switch (p->type) {
79 case FFTW_NOTW:
80 {
81 fftw_notw_codelet *codelet = p->nodeu.notw.codelet;
82
83 HACK_ALIGN_STACK_ODD;
84 for (s = 0; s < howmany; ++s)
85 codelet(in + s * idist,
86 out + s * odist,
87 istride, ostride);
88 break;
89 }
90
91 default:
92 for (s = 0; s < howmany; ++s)
93 fftw_executor_simple(n, in + s * idist,
94 out + s * odist,
95 p, istride, ostride,
96 recurse_kind);
97 }
98 }
99
100 #ifdef FFTW_ENABLE_VECTOR_RECURSE
101
102 /* executor_many_vector is like executor_many, but it pushes the
103 howmany loop down to the leaves of the transform: */
104 static void executor_many_vector(int n, const fftw_complex *in,
105 fftw_complex *out,
106 fftw_plan_node *p,
107 int istride,
108 int ostride,
109 int howmany, int idist, int odist)
110 {
111 int s;
112
113 switch (p->type) {
114 case FFTW_NOTW:
115 {
116 fftw_notw_codelet *codelet = p->nodeu.notw.codelet;
117
118 HACK_ALIGN_STACK_ODD;
119 for (s = 0; s < howmany; ++s)
120 codelet(in + s * idist,
121 out + s * odist,
122 istride, ostride);
123 break;
124 }
125
126 case FFTW_TWIDDLE:
127 {
128 int r = p->nodeu.twiddle.size;
129 int m = n / r;
130 fftw_twiddle_codelet *codelet;
131 fftw_complex *W;
132
133 for (s = 0; s < r; ++s)
134 executor_many_vector(m, in + s * istride,
135 out + s * (m * ostride),
136 p->nodeu.twiddle.recurse,
137 istride * r, ostride,
138 howmany, idist, odist);
139
140 codelet = p->nodeu.twiddle.codelet;
141 W = p->nodeu.twiddle.tw->twarray;
142
143 /* This may not be the right thing. We maybe should have
144 the howmany loop for the twiddle codelets at the
145 topmost level of the recursion, since odist is big;
146 i.e. separate recursions for twiddle and notwiddle. */
147 HACK_ALIGN_STACK_EVEN;
148 for (s = 0; s < howmany; ++s)
149 codelet(out + s * odist, W, m * ostride, m, ostride);
150
151 break;
152 }
153
154 case FFTW_GENERIC:
155 {
156 int r = p->nodeu.generic.size;
157 int m = n / r;
158 fftw_generic_codelet *codelet;
159 fftw_complex *W;
160
161 for (s = 0; s < r; ++s)
162 executor_many_vector(m, in + s * istride,
163 out + s * (m * ostride),
164 p->nodeu.generic.recurse,
165 istride * r, ostride,
166 howmany, idist, odist);
167
168 codelet = p->nodeu.generic.codelet;
169 W = p->nodeu.generic.tw->twarray;
170 for (s = 0; s < howmany; ++s)
171 codelet(out + s * odist, W, m, r, n, ostride);
172
173 break;
174 }
175
176 case FFTW_RADER:
177 {
178 int r = p->nodeu.rader.size;
179 int m = n / r;
180 fftw_rader_codelet *codelet;
181 fftw_complex *W;
182
183 for (s = 0; s < r; ++s)
184 executor_many_vector(m, in + s * istride,
185 out + s * (m * ostride),
186 p->nodeu.rader.recurse,
187 istride * r, ostride,
188 howmany, idist, odist);
189
190 codelet = p->nodeu.rader.codelet;
191 W = p->nodeu.rader.tw->twarray;
192 for (s = 0; s < howmany; ++s)
193 codelet(out + s * odist, W, m, r, ostride,
194 p->nodeu.rader.rader_data);
195
196 break;
197 }
198
199 default:
200 fftw_die("BUG in executor: invalid plan\n");
201 break;
202 }
203 }
204
205 #endif /* FFTW_ENABLE_VECTOR_RECURSE */
206
207 /*
208 * Do *not* declare simple executor static--we need to call it
209 * from other files...also, preface its name with "fftw_"
210 * to avoid any possible name collisions.
211 */
212 void fftw_executor_simple(int n, const fftw_complex *in,
213 fftw_complex *out,
214 fftw_plan_node *p,
215 int istride,
216 int ostride,
217 fftw_recurse_kind recurse_kind)
218 {
219 switch (p->type) {
220 case FFTW_NOTW:
221 HACK_ALIGN_STACK_ODD;
222 (p->nodeu.notw.codelet)(in, out, istride, ostride);
223 break;
224
225 case FFTW_TWIDDLE:
226 {
227 int r = p->nodeu.twiddle.size;
228 int m = n / r;
229 fftw_twiddle_codelet *codelet;
230 fftw_complex *W;
231
232 #ifdef FFTW_ENABLE_VECTOR_RECURSE
233 if (recurse_kind == FFTW_NORMAL_RECURSE)
234 #endif
235 executor_many(m, in, out,
236 p->nodeu.twiddle.recurse,
237 istride * r, ostride,
238 r, istride, m * ostride,
239 FFTW_NORMAL_RECURSE);
240 #ifdef FFTW_ENABLE_VECTOR_RECURSE
241 else
242 executor_many_vector(m, in, out,
243 p->nodeu.twiddle.recurse,
244 istride * r, ostride,
245 r, istride, m * ostride);
246 #endif
247
248 codelet = p->nodeu.twiddle.codelet;
249 W = p->nodeu.twiddle.tw->twarray;
250
251 HACK_ALIGN_STACK_EVEN;
252 codelet(out, W, m * ostride, m, ostride);
253
254 break;
255 }
256
257 case FFTW_GENERIC:
258 {
259 int r = p->nodeu.generic.size;
260 int m = n / r;
261 fftw_generic_codelet *codelet;
262 fftw_complex *W;
263
264 #ifdef FFTW_ENABLE_VECTOR_RECURSE
265 if (recurse_kind == FFTW_NORMAL_RECURSE)
266 #endif
267 executor_many(m, in, out,
268 p->nodeu.generic.recurse,
269 istride * r, ostride,
270 r, istride, m * ostride,
271 FFTW_NORMAL_RECURSE);
272 #ifdef FFTW_ENABLE_VECTOR_RECURSE
273 else
274 executor_many_vector(m, in, out,
275 p->nodeu.generic.recurse,
276 istride * r, ostride,
277 r, istride, m * ostride);
278 #endif
279
280 codelet = p->nodeu.generic.codelet;
281 W = p->nodeu.generic.tw->twarray;
282 codelet(out, W, m, r, n, ostride);
283
284 break;
285 }
286
287 case FFTW_RADER:
288 {
289 int r = p->nodeu.rader.size;
290 int m = n / r;
291 fftw_rader_codelet *codelet;
292 fftw_complex *W;
293
294 #ifdef FFTW_ENABLE_VECTOR_RECURSE
295 if (recurse_kind == FFTW_NORMAL_RECURSE)
296 #endif
297 executor_many(m, in, out,
298 p->nodeu.rader.recurse,
299 istride * r, ostride,
300 r, istride, m * ostride,
301 FFTW_NORMAL_RECURSE);
302 #ifdef FFTW_ENABLE_VECTOR_RECURSE
303 else
304 executor_many_vector(m, in, out,
305 p->nodeu.rader.recurse,
306 istride * r, ostride,
307 r, istride, m * ostride);
308 #endif
309
310 codelet = p->nodeu.rader.codelet;
311 W = p->nodeu.rader.tw->twarray;
312 codelet(out, W, m, r, ostride,
313 p->nodeu.rader.rader_data);
314
315 break;
316 }
317
318 default:
319 fftw_die("BUG in executor: invalid plan\n");
320 break;
321 }
322 }
323
324 static void executor_simple_inplace(int n, fftw_complex *in,
325 fftw_complex *out,
326 fftw_plan_node *p,
327 int istride,
328 fftw_recurse_kind recurse_kind)
329 {
330 switch (p->type) {
331 case FFTW_NOTW:
332 HACK_ALIGN_STACK_ODD;
333 (p->nodeu.notw.codelet)(in, in, istride, istride);
334 break;
335
336 default:
337 {
338 fftw_complex *tmp;
339
340 if (out)
341 tmp = out;
342 else
343 tmp = (fftw_complex *)
344 fftw_malloc(n * sizeof(fftw_complex));
345
346 fftw_executor_simple(n, in, tmp, p, istride, 1,
347 recurse_kind);
348 fftw_strided_copy(n, tmp, istride, in);
349
350 if (!out)
351 fftw_free(tmp);
352 }
353 }
354 }
355
356 static void executor_many_inplace(int n, fftw_complex *in,
357 fftw_complex *out,
358 fftw_plan_node *p,
359 int istride,
360 int howmany, int idist,
361 fftw_recurse_kind recurse_kind)
362 {
363 switch (p->type) {
364 case FFTW_NOTW:
365 {
366 fftw_notw_codelet *codelet = p->nodeu.notw.codelet;
367 int s;
368
369 HACK_ALIGN_STACK_ODD;
370 for (s = 0; s < howmany; ++s)
371 codelet(in + s * idist,
372 in + s * idist,
373 istride, istride);
374 break;
375 }
376
377 default:
378 {
379 int s;
380 fftw_complex *tmp;
381 if (out)
382 tmp = out;
383 else
384 tmp = (fftw_complex *)
385 fftw_malloc(n * sizeof(fftw_complex));
386
387 for (s = 0; s < howmany; ++s) {
388 fftw_executor_simple(n,
389 in + s * idist,
390 tmp,
391 p, istride, 1, recurse_kind);
392 fftw_strided_copy(n, tmp, istride, in + s * idist);
393 }
394
395 if (!out)
396 fftw_free(tmp);
397 }
398 }
399 }
400
401 /* user interface */
402 void fftw(fftw_plan plan, int howmany, fftw_complex *in, int istride,
403 int idist, fftw_complex *out, int ostride, int odist)
404 {
405 int n = plan->n;
406
407 if (plan->flags & FFTW_IN_PLACE) {
408 if (howmany == 1) {
409 executor_simple_inplace(n, in, out, plan->root, istride,
410 plan->recurse_kind);
411 } else {
412 executor_many_inplace(n, in, out, plan->root, istride, howmany,
413 idist, plan->recurse_kind);
414 }
415 } else {
416 if (howmany == 1) {
417 fftw_executor_simple(n, in, out, plan->root, istride, ostride,
418 plan->recurse_kind);
419 } else {
420 #ifdef FFTW_ENABLE_VECTOR_RECURSE
421 int vector_size = plan->vector_size;
422 if (vector_size <= 1)
423 #endif
424 executor_many(n, in, out, plan->root, istride, ostride,
425 howmany, idist, odist, plan->recurse_kind);
426 #ifdef FFTW_ENABLE_VECTOR_RECURSE
427 else {
428 int s;
429 int num_vects = howmany / vector_size;
430 fftw_plan_node *root = plan->root;
431
432 for (s = 0; s < num_vects; ++s)
433 executor_many_vector(n,
434 in + s * (vector_size * idist),
435 out + s * (vector_size * odist),
436 root,
437 istride, ostride,
438 vector_size, idist, odist);
439
440 s = howmany % vector_size;
441 if (s > 0)
442 executor_many(n,
443 in + num_vects * (vector_size * idist),
444 out + num_vects * (vector_size * odist),
445 root,
446 istride, ostride,
447 s, idist, odist,
448 FFTW_NORMAL_RECURSE);
449 }
450 #endif
451 }
452 }
453 }
454
455 void fftw_one(fftw_plan plan, fftw_complex *in, fftw_complex *out)
456 {
457 int n = plan->n;
458
459 if (plan->flags & FFTW_IN_PLACE)
460 executor_simple_inplace(n, in, out, plan->root, 1,
461 plan->recurse_kind);
462 else
463 fftw_executor_simple(n, in, out, plan->root, 1, 1,
464 plan->recurse_kind);
465 }
fftw_plan_struct
Definition: fftw.h:271
fftw-int.h
fftw
void fftw(fftw_plan plan, int howmany, fftw_complex *in, int istride, int idist, fftw_complex *out, int ostride, int odist)
Definition: executor.c:402
fftw_plan_node_struct::nodeu
union fftw_plan_node_struct::@0 nodeu
fftw_twiddle_codelet
void( fftw_twiddle_codelet)(fftw_complex *, const fftw_complex *, int, int, int)
Definition: fftw.h:95
fftw_complex
Definition: fftw.h:57
fftw_rader_codelet
void( fftw_rader_codelet)(fftw_complex *, const fftw_complex *, int, int, int, fftw_rader_data *)
Definition: fftw.h:188
FFTW_IN_PLACE
#define FFTW_IN_PLACE
Definition: fftw.h:292
FFTW_TWIDDLE
Definition: fftw.h:121
fftw_plan_node_struct::rader
struct fftw_plan_node_struct::@0::@4 rader
fftw_free
void fftw_free(void *p)
Definition: malloc.c:178
fftw_plan_struct::n
int n
Definition: fftw.h:272
FFTW_GENERIC
Definition: fftw.h:121
fftw_die
void fftw_die(const char *s)
Definition: malloc.c:192
fftw_plan_struct::recurse_kind
fftw_recurse_kind recurse_kind
Definition: fftw.h:281
fftw_generic_codelet
void( fftw_generic_codelet)(fftw_complex *, const fftw_complex *, int, int, int, int)
Definition: fftw.h:98
HACK_ALIGN_STACK_ODD
#define HACK_ALIGN_STACK_ODD
Definition: fftw-int.h:233
fftw_plan_struct::root
fftw_plan_node * root
Definition: fftw.h:279
fftw_notw_codelet
void( fftw_notw_codelet)(const fftw_complex *, fftw_complex *, int, int)
Definition: fftw.h:93
fftw_malloc
void * fftw_malloc(size_t n)
Definition: malloc.c:160
fftw_recurse_kind
fftw_recurse_kind
Definition: fftw.h:266
fftw_plan_node_struct::type
enum fftw_node_type type
Definition: fftw.h:193
FFTW_RADER
Definition: fftw.h:121
fftw_plan_struct::vector_size
int vector_size
Definition: fftw.h:282
fftw_one
void fftw_one(fftw_plan plan, fftw_complex *in, fftw_complex *out)
Definition: executor.c:455
fftw_plan_node_struct::twiddle
struct fftw_plan_node_struct::@0::@2 twiddle
c_re
#define c_re(c)
Definition: fftw.h:60
fftw_strided_copy
void fftw_strided_copy(int n, fftw_complex *in, int ostride, fftw_complex *out)
Definition: executor.c:35
fftw_version
const char * fftw_version
Definition: executor.c:29
c_im
#define c_im(c)
Definition: fftw.h:61
fftw_executor_simple
void fftw_executor_simple(int n, const fftw_complex *in, fftw_complex *out, fftw_plan_node *p, int istride, int ostride, fftw_recurse_kind recurse_kind)
Definition: executor.c:212
fftw_plan_node_struct
Definition: fftw.h:192
fftw_real
float fftw_real
Definition: fftw.h:49
fftw_plan_node_struct::notw
struct fftw_plan_node_struct::@0::@1 notw
FFTW_VERSION
#define FFTW_VERSION
Definition: config.h:104
HACK_ALIGN_STACK_EVEN
#define HACK_ALIGN_STACK_EVEN
Definition: fftw-int.h:230
FFTW_NOTW
Definition: fftw.h:121
fftw_plan_node_struct::generic
struct fftw_plan_node_struct::@0::@3 generic
FFTW_NORMAL_RECURSE
Definition: fftw.h:267
fftw_plan_struct::flags
int flags
Definition: fftw.h:275