| Bsoft 1.9 Bernard's software package

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

twiddle.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 * twiddle.c -- compute twiddle factors
22 * These are the twiddle factors for *direct* fft. Flip sign to get
23 * the inverse
24 */
25
26 /* $Id: twiddle.c,v 1.42 2003/03/16 23:43:46 stevenj Exp $ */
27 #include "fftw-int.h"
28 #include <math.h>
29 #include <stdlib.h>
30 #include <limits.h>
31
32 #ifndef TRUE
33 #define TRUE (1 == 1)
34 #endif
35
36 #ifndef FALSE
37 #define FALSE (1 == 0)
38 #endif
39
40 #ifdef USE_FFTW_SAFE_MULMOD
41 /* compute (x * y) mod p, but watch out for integer overflows; we must
42 have x, y >= 0, p > 0. This routine is slow. */
43 int fftw_safe_mulmod(int x, int y, int p)
44 {
45 if (y == 0 || x <= INT_MAX / y)
46 return((x * y) % p);
47 else {
48 int y2 = y/2;
49 return((fftw_safe_mulmod(x, y2, p) +
50 fftw_safe_mulmod(x, y - y2, p)) % p);
51 }
52 }
53 #endif /* USE_FFTW_SAFE_MULMOD */
54
55 static fftw_complex *fftw_compute_rader_twiddle(int n, int r, int g)
56 {
57 FFTW_TRIG_REAL twoPiOverN;
58 int m = n / r;
59 int i, j, gpower;
60 fftw_complex *W;
61
62 twoPiOverN = FFTW_K2PI / (FFTW_TRIG_REAL) n;
63 W = (fftw_complex *) fftw_malloc((r - 1) * m * sizeof(fftw_complex));
64 for (i = 0; i < m; ++i)
65 for (gpower = 1, j = 0; j < r - 1; ++j,
66 gpower = MULMOD(gpower, g, r)) {
67 int k = i * (r - 1) + j;
68 FFTW_TRIG_REAL
69 ij = (FFTW_TRIG_REAL) (i * gpower);
70 c_re(W[k]) = FFTW_TRIG_COS(twoPiOverN * ij);
71 c_im(W[k]) = FFTW_FORWARD * FFTW_TRIG_SIN(twoPiOverN * ij);
72 }
73
74 return W;
75 }
76
77 /*
78 * compute the W coefficients (that is, powers of the root of 1)
79 * and store them into an array.
80 */
81 static fftw_complex *fftw_compute_twiddle(int n, const fftw_codelet_desc *d)
82 {
83 FFTW_TRIG_REAL twoPiOverN;
84 int i, j;
85 fftw_complex *W;
86
87 twoPiOverN = FFTW_K2PI / (FFTW_TRIG_REAL) n;
88
89 if (!d) {
90 /* generic codelet, needs all twiddles in order */
91 W = (fftw_complex *) fftw_malloc(n * sizeof(fftw_complex));
92 for (i = 0; i < n; ++i) {
93 c_re(W[i]) = FFTW_TRIG_COS(twoPiOverN * (FFTW_TRIG_REAL) i);
94 c_im(W[i]) = FFTW_FORWARD * FFTW_TRIG_SIN(twoPiOverN * (FFTW_TRIG_REAL) i);
95 }
96 } else if (d->type == FFTW_RADER)
97 W = fftw_compute_rader_twiddle(n, d->size, d->signature);
98 else {
99 int r = d->size;
100 int m = n / r, m_alloc;
101 int r1 = d->ntwiddle;
102 int istart;
103
104 if (d->type == FFTW_TWIDDLE) {
105 istart = 0;
106 m_alloc = m;
107 } else if (d->type == FFTW_HC2HC) {
108 /*
109 * This is tricky, do not change lightly.
110 */
111 m = (m + 1) / 2;
112 m_alloc = m - 1;
113 istart = 1;
114 } else {
115 fftw_die("compute_twiddle: invalid argument\n");
116 /* paranoia for gcc */
117 m_alloc = 0;
118 istart = 0;
119 }
120
121 W = (fftw_complex *) fftw_malloc(r1 * m_alloc * sizeof(fftw_complex));
122 for (i = istart; i < m; ++i)
123 for (j = 0; j < r1; ++j) {
124 int k = (i - istart) * r1 + j;
125 FFTW_TRIG_REAL
126 ij = (FFTW_TRIG_REAL) (i * d->twiddle_order[j]);
127 c_re(W[k]) = FFTW_TRIG_COS(twoPiOverN * ij);
128 c_im(W[k]) = FFTW_FORWARD * FFTW_TRIG_SIN(twoPiOverN * ij);
129 }
130 }
131
132 return W;
133 }
134
135 /*
136 * these routines implement a simple reference-count-based
137 * management of twiddle structures
138 */
139 static fftw_twiddle *twlist = (fftw_twiddle *) 0;
140 int fftw_twiddle_size = 0; /* total allocated size, for debugging */
141
142 /* true if the two codelets can share the same twiddle factors */
143 static int compatible(const fftw_codelet_desc *d1, const fftw_codelet_desc *d2)
144 {
145 int i;
146
147 /* true if they are the same codelet */
148 if (d1 == d2)
149 return TRUE;
150
151 /* false if one is null and the other is not */
152 if (!d1 || !d2)
153 return FALSE;
154
155 /* false if size is different */
156 if (d1->size != d2->size)
157 return FALSE;
158
159 /* false if different types (FFTW_TWIDDLE/FFTW_HC2HC/FFTW_RADER) */
160 if (d1->type != d2->type)
161 return FALSE;
162
163 /* false if they need different # of twiddles */
164 if (d1->ntwiddle != d2->ntwiddle)
165 return FALSE;
166
167 /* false if the twiddle orders are different */
168 for (i = 0; i < d1->ntwiddle; ++i)
169 if (d1->twiddle_order[i] != d2->twiddle_order[i])
170 return FALSE;
171
172 return TRUE;
173 }
174
175 fftw_twiddle *fftw_create_twiddle(int n, const fftw_codelet_desc *d)
176 {
177 fftw_twiddle *tw;
178
179 /* lookup this n in the twiddle list */
180 for (tw = twlist; tw; tw = tw->next)
181 if (n == tw->n && compatible(d, tw->cdesc)) {
182 ++tw->refcnt;
183 return tw;
184 }
185 /* not found --- allocate a new struct twiddle */
186 tw = (fftw_twiddle *) fftw_malloc(sizeof(fftw_twiddle));
187 fftw_twiddle_size += n;
188
189 tw->n = n;
190 tw->cdesc = d;
191 tw->twarray = fftw_compute_twiddle(n, d);
192 tw->refcnt = 1;
193
194 /* enqueue the new struct */
195 tw->next = twlist;
196 twlist = tw;
197
198 return tw;
199 }
200
201 void fftw_destroy_twiddle(fftw_twiddle * tw)
202 {
203 fftw_twiddle **p;
204 --tw->refcnt;
205
206 if (tw->refcnt == 0) {
207 /* remove from the list of known twiddle factors */
208 for (p = &twlist; p; p = &((*p)->next))
209 if (*p == tw) {
210 *p = tw->next;
211 fftw_twiddle_size -= tw->n;
212 fftw_free(tw->twarray);
213 fftw_free(tw);
214 return;
215 }
216 fftw_die("BUG in fftw_destroy_twiddle\n");
217 }
218 }
TRUE
#define TRUE
Definition: twiddle.c:33
fftw_codelet_desc
Definition: fftw.h:126
fftw_twiddle_struct::cdesc
const fftw_codelet_desc * cdesc
Definition: fftw.h:172
fftw_twiddle_struct
Definition: fftw.h:170
fftw-int.h
fftw_complex
Definition: fftw.h:57
FFTW_TWIDDLE
Definition: fftw.h:121
fftw_twiddle_size
int fftw_twiddle_size
Definition: twiddle.c:140
fftw_destroy_twiddle
void fftw_destroy_twiddle(fftw_twiddle *tw)
Definition: twiddle.c:201
fftw_codelet_desc::twiddle_order
const int * twiddle_order
Definition: fftw.h:134
fftw_twiddle_struct::refcnt
int refcnt
Definition: fftw.h:175
fftw_free
void fftw_free(void *p)
Definition: malloc.c:178
FFTW_HC2HC
Definition: fftw.h:122
fftw_die
void fftw_die(const char *s)
Definition: malloc.c:192
FFTW_TRIG_COS
#define FFTW_TRIG_COS
Definition: fftw-int.h:186
fftw_create_twiddle
fftw_twiddle * fftw_create_twiddle(int n, const fftw_codelet_desc *d)
Definition: twiddle.c:175
FALSE
#define FALSE
Definition: twiddle.c:37
fftw_malloc
void * fftw_malloc(size_t n)
Definition: malloc.c:160
fftw_codelet_desc::type
enum fftw_node_type type
Definition: fftw.h:131
fftw_twiddle_struct::next
struct fftw_twiddle_struct * next
Definition: fftw.h:174
FFTW_TRIG_SIN
#define FFTW_TRIG_SIN
Definition: fftw-int.h:185
fftw_codelet_desc::ntwiddle
int ntwiddle
Definition: fftw.h:133
FFTW_RADER
Definition: fftw.h:121
fftw_twiddle_struct::n
int n
Definition: fftw.h:171
c_re
#define c_re(c)
Definition: fftw.h:60
FFTW_TRIG_REAL
double FFTW_TRIG_REAL
Definition: fftw-int.h:187
MULMOD
#define MULMOD(x, y, p)
Definition: fftw-int.h:154
fftw_twiddle_struct::twarray
fftw_complex * twarray
Definition: fftw.h:173
fftw_codelet_desc::size
int size
Definition: fftw.h:129
c_im
#define c_im(c)
Definition: fftw.h:61
FFTW_K2PI
#define FFTW_K2PI
Definition: fftw-int.h:189
fftw_codelet_desc::signature
int signature
Definition: fftw.h:132
FFTW_FORWARD
Definition: fftw.h:64