~ubuntu-branches/ubuntu/raring/fftw3/raring-proposed

« back to all changes in this revision

Viewing changes to dft/bluestein.c

  • Committer: Bazaar Package Importer
  • Author(s): Paul Brossier
  • Date: 2006-05-31 13:44:05 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20060531134405-ol9hrbg6bh81sg0c
Tags: 3.1.1-1
* New upstream release (closes: #350327, #338487, #338501)
* Add --enable-portable-binary to use -mtune instead of -march
* Use --with-gcc-arch=G5 / pentium4 on powerpc / i386
* Updated Standards-Version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2003, 2006 Matteo Frigo
 
3
 * Copyright (c) 2003, 2006 Massachusetts Institute of Technology
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 *
 
19
 */
 
20
 
 
21
#include "dft.h"
 
22
 
 
23
typedef struct {
 
24
     solver super;
 
25
} S;
 
26
 
 
27
typedef struct {
 
28
     plan_dft super;
 
29
     INT n;     /* problem size */
 
30
     INT nb;    /* size of convolution */
 
31
     R *w;      /* lambda k . exp(2*pi*i*k^2/(2*n)) */
 
32
     R *W;      /* DFT(w) */
 
33
     plan *cldf;
 
34
     INT is, os;
 
35
} P;
 
36
 
 
37
static void bluestein_sequence(enum wakefulness wakefulness, INT n, R *w)
 
38
{
 
39
     INT k, ksq, n2 = 2 * n;
 
40
     triggen *t = X(mktriggen)(wakefulness, n2);
 
41
 
 
42
     ksq = 0;
 
43
     for (k = 0; k < n; ++k) {
 
44
          t->cexp(t, ksq, w+2*k);
 
45
          /* careful with overflow */
 
46
          ksq += 2*k + 1; while (ksq > n2) ksq -= n2;
 
47
     }
 
48
 
 
49
     X(triggen_destroy)(t);
 
50
}
 
51
 
 
52
static void mktwiddle(enum wakefulness wakefulness, P *p)
 
53
{
 
54
     INT i;
 
55
     INT n = p->n, nb = p->nb;
 
56
     R *w, *W;
 
57
     E nbf = (E)nb;
 
58
 
 
59
     p->w = w = (R *) MALLOC(2 * n * sizeof(R), TWIDDLES);
 
60
     p->W = W = (R *) MALLOC(2 * nb * sizeof(R), TWIDDLES);
 
61
 
 
62
     bluestein_sequence(wakefulness, n, w);
 
63
 
 
64
     for (i = 0; i < nb; ++i)
 
65
          W[2*i] = W[2*i+1] = K(0.0);
 
66
 
 
67
     W[0] = w[0] / nbf;
 
68
     W[1] = w[1] / nbf;
 
69
 
 
70
     for (i = 1; i < n; ++i) {
 
71
          W[2*i] = W[2*(nb-i)] = w[2*i] / nbf;
 
72
          W[2*i+1] = W[2*(nb-i)+1] = w[2*i+1] / nbf;
 
73
     }
 
74
 
 
75
     {
 
76
          plan_dft *cldf = (plan_dft *)p->cldf;
 
77
          /* cldf must be awake */
 
78
          cldf->apply(p->cldf, W, W+1, W, W+1);
 
79
     }
 
80
}
 
81
 
 
82
static void apply(const plan *ego_, R *ri, R *ii, R *ro, R *io)
 
83
{
 
84
     const P *ego = (const P *) ego_;
 
85
     INT i, n = ego->n, nb = ego->nb, is = ego->is, os = ego->os;
 
86
     R *w = ego->w, *W = ego->W;
 
87
     R *b = (R *) MALLOC(2 * nb * sizeof(R), BUFFERS);
 
88
 
 
89
     /* multiply input by conjugate bluestein sequence */
 
90
     for (i = 0; i < n; ++i) {
 
91
          E xr = ri[i*is], xi = ii[i*is];
 
92
          E wr = w[2*i], wi = w[2*i+1];
 
93
          b[2*i] = xr * wr + xi * wi;
 
94
          b[2*i+1] = xi * wr - xr * wi;
 
95
     }
 
96
 
 
97
     for (; i < nb; ++i) b[2*i] = b[2*i+1] = K(0.0);
 
98
 
 
99
     /* convolution: FFT */
 
100
     {
 
101
          plan_dft *cldf = (plan_dft *)ego->cldf;
 
102
          cldf->apply(ego->cldf, b, b+1, b, b+1);
 
103
     }
 
104
 
 
105
     /* convolution: pointwise multiplication */
 
106
     for (i = 0; i < nb; ++i) {
 
107
          E xr = b[2*i], xi = b[2*i+1];
 
108
          E wr = W[2*i], wi = W[2*i+1];
 
109
          b[2*i] = xi * wr + xr * wi;
 
110
          b[2*i+1] = xr * wr - xi * wi;
 
111
     }
 
112
 
 
113
     /* convolution: IFFT by FFT with real/imag input/output swapped */
 
114
     {
 
115
          plan_dft *cldf = (plan_dft *)ego->cldf;
 
116
          cldf->apply(ego->cldf, b, b+1, b, b+1);
 
117
     }
 
118
 
 
119
     /* multiply output by conjugate bluestein sequence */
 
120
     for (i = 0; i < n; ++i) {
 
121
          E xi = b[2*i], xr = b[2*i+1];
 
122
          E wr = w[2*i], wi = w[2*i+1];
 
123
          ro[i*os] = xr * wr + xi * wi;
 
124
          io[i*os] = xi * wr - xr * wi;
 
125
     }
 
126
 
 
127
     X(ifree)(b);         
 
128
}
 
129
 
 
130
static void awake(plan *ego_, enum wakefulness wakefulness)
 
131
{
 
132
     P *ego = (P *) ego_;
 
133
 
 
134
     X(plan_awake)(ego->cldf, wakefulness);
 
135
 
 
136
     switch (wakefulness) {
 
137
         case SLEEPY:
 
138
              X(ifree0)(ego->w); ego->w = 0;
 
139
              X(ifree0)(ego->W); ego->W = 0;
 
140
              break;
 
141
         default:
 
142
              A(!ego->w);
 
143
              mktwiddle(wakefulness, ego);
 
144
              break;
 
145
     }
 
146
}
 
147
 
 
148
static int applicable0(const problem *p_)
 
149
{
 
150
     const problem_dft *p = (const problem_dft *) p_;
 
151
     return (1
 
152
             && p->sz->rnk == 1
 
153
             && p->vecsz->rnk == 0
 
154
             /* FIXME: allow other sizes */
 
155
             && X(is_prime)(p->sz->dims[0].n)
 
156
 
 
157
             /* FIXME: infinite recursion of bluestein with itself */
 
158
             && p->sz->dims[0].n > 16
 
159
          );
 
160
}
 
161
 
 
162
static int applicable(const solver *ego, const problem *p_, 
 
163
                      const planner *plnr)
 
164
{
 
165
     UNUSED(ego);
 
166
     if (NO_SLOWP(plnr)) return 0;
 
167
     if (!applicable0(p_)) return 0;
 
168
     return 1;
 
169
}
 
170
 
 
171
static void destroy(plan *ego_)
 
172
{
 
173
     P *ego = (P *) ego_;
 
174
     X(plan_destroy_internal)(ego->cldf);
 
175
}
 
176
 
 
177
static void print(const plan *ego_, printer *p)
 
178
{
 
179
     const P *ego = (const P *)ego_;
 
180
     p->print(p, "(dft-bluestein-%D/%D%(%p%))",
 
181
              ego->n, ego->nb, ego->cldf);
 
182
}
 
183
 
 
184
static INT choose_transform_size(INT minsz)
 
185
{
 
186
     static const INT primes[] = { 2, 3, 5, 0 };
 
187
     while (!X(factors_into)(minsz, primes))
 
188
          ++minsz;
 
189
     return minsz;
 
190
}
 
191
 
 
192
static plan *mkplan(const solver *ego, const problem *p_, planner *plnr)
 
193
{
 
194
     const problem_dft *p = (const problem_dft *) p_;
 
195
     P *pln;
 
196
     INT n, nb;
 
197
     plan *cldf = 0;
 
198
     R *buf = (R *) 0;
 
199
 
 
200
     static const plan_adt padt = {
 
201
          X(dft_solve), awake, print, destroy
 
202
     };
 
203
 
 
204
     if (!applicable(ego, p_, plnr))
 
205
          return (plan *) 0;
 
206
 
 
207
     n = p->sz->dims[0].n;
 
208
     nb = choose_transform_size(2 * n - 1);
 
209
     buf = (R *) MALLOC(2 * nb * sizeof(R), BUFFERS);
 
210
 
 
211
     cldf = X(mkplan_f_d)(plnr, 
 
212
                          X(mkproblem_dft_d)(X(mktensor_1d)(nb, 2, 2),
 
213
                                             X(mktensor_1d)(1, 0, 0),
 
214
                                             buf, buf+1, 
 
215
                                             buf, buf+1),
 
216
                          NO_SLOW, 0, 0);
 
217
     if (!cldf) goto nada;
 
218
 
 
219
     X(ifree)(buf);
 
220
 
 
221
     pln = MKPLAN_DFT(P, &padt, apply);
 
222
 
 
223
     pln->n = n;
 
224
     pln->nb = nb;
 
225
     pln->w = 0;
 
226
     pln->W = 0;
 
227
     pln->cldf = cldf;
 
228
     pln->is = p->sz->dims[0].is;
 
229
     pln->os = p->sz->dims[0].os;
 
230
 
 
231
     X(ops_add)(&cldf->ops, &cldf->ops, &pln->super.super.ops);
 
232
     pln->super.super.ops.add += 4 * n + 2 * nb;
 
233
     pln->super.super.ops.mul += 8 * n + 4 * nb;
 
234
     pln->super.super.ops.other += 6 * (n + nb);
 
235
 
 
236
     return &(pln->super.super);
 
237
 
 
238
 nada:
 
239
     X(ifree0)(buf);
 
240
     X(plan_destroy_internal)(cldf);
 
241
     return (plan *)0;
 
242
}
 
243
 
 
244
 
 
245
static solver *mksolver(void)
 
246
{
 
247
     static const solver_adt sadt = { PROBLEM_DFT, mkplan };
 
248
     S *slv = MKSOLVER(S, &sadt);
 
249
     return &(slv->super);
 
250
}
 
251
 
 
252
void X(dft_bluestein_register)(planner *p)
 
253
{
 
254
     REGISTER_SOLVER(p, mksolver());
 
255
}