To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

The primary repository for this project is hosted at https://github.com/sonic-visualiser/sv-dependency-builds .
This repository is a read-only copy which is updated automatically every hour.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / src / fftw-3.3.8 / dft / dftw-genericbuf.c @ 167:bd3cc4d1df30

History | View | Annotate | Download (5.69 KB)

1
/*
2
 * Copyright (c) 2003, 2007-14 Matteo Frigo
3
 * Copyright (c) 2003, 2007-14 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18
 *
19
 */
20

    
21
/* express a twiddle problem in terms of dft + multiplication by
22
   twiddle factors */
23

    
24
#include "dft/ct.h"
25

    
26
typedef struct {
27
     ct_solver super;
28
     INT batchsz;
29
} S;
30

    
31
typedef struct {
32
     plan_dftw super;
33

    
34
     INT r, rs, m, ms, v, vs, mb, me;
35
     INT batchsz;
36
     plan *cld;
37

    
38
     triggen *t;
39
     const S *slv;
40
} P;
41

    
42

    
43
#define BATCHDIST(r) ((r) + 16)
44

    
45
/**************************************************************/
46
static void bytwiddle(const P *ego, INT mb, INT me, R *buf, R *rio, R *iio)
47
{
48
     INT j, k;
49
     INT r = ego->r, rs = ego->rs, ms = ego->ms;
50
     triggen *t = ego->t;
51
     for (j = 0; j < r; ++j) {
52
          for (k = mb; k < me; ++k)
53
               t->rotate(t, j * k,
54
                         rio[j * rs + k * ms],
55
                         iio[j * rs + k * ms],
56
                         &buf[j * 2 + 2 * BATCHDIST(r) * (k - mb) + 0]);
57
     }
58
}
59

    
60
static int applicable0(const S *ego,
61
                       INT r, INT irs, INT ors,
62
                       INT m, INT v,
63
                       INT mcount)
64
{
65
     return (1
66
             && v == 1
67
             && irs == ors
68
             && mcount >= ego->batchsz
69
             && mcount % ego->batchsz == 0
70
             && r >= 64 
71
             && m >= r
72
          );
73
}
74

    
75
static int applicable(const S *ego,
76
                      INT r, INT irs, INT ors,
77
                      INT m, INT v,
78
                      INT mcount,
79
                      const planner *plnr)
80
{
81
     if (!applicable0(ego, r, irs, ors, m, v, mcount))
82
          return 0;
83
     if (NO_UGLYP(plnr) && m * r < 65536)
84
          return 0;
85

    
86
     return 1;
87
}
88

    
89
static void dobatch(const P *ego, INT mb, INT me, R *buf, R *rio, R *iio)
90
{
91
     plan_dft *cld;
92
     INT ms = ego->ms;
93

    
94
     bytwiddle(ego, mb, me, buf, rio, iio);
95

    
96
     cld = (plan_dft *) ego->cld;
97
     cld->apply(ego->cld, buf, buf + 1, buf, buf + 1);
98
     X(cpy2d_pair_co)(buf, buf + 1,
99
                      rio + ms * mb, iio + ms * mb,
100
                      me-mb, 2 * BATCHDIST(ego->r), ms,
101
                      ego->r, 2, ego->rs);
102
}
103

    
104
static void apply(const plan *ego_, R *rio, R *iio)
105
{
106
     const P *ego = (const P *) ego_;
107
     R *buf = (R *) MALLOC(sizeof(R) * 2 * BATCHDIST(ego->r) * ego->batchsz,
108
                           BUFFERS);
109
     INT m;
110

    
111
     for (m = ego->mb; m < ego->me; m += ego->batchsz)
112
          dobatch(ego, m, m + ego->batchsz, buf, rio, iio);
113

    
114
     A(m == ego->me);
115

    
116
     X(ifree)(buf);
117
}
118

    
119
static void awake(plan *ego_, enum wakefulness wakefulness)
120
{
121
     P *ego = (P *) ego_;
122
     X(plan_awake)(ego->cld, wakefulness);
123

    
124
     switch (wakefulness) {
125
         case SLEEPY:
126
              X(triggen_destroy)(ego->t); ego->t = 0;
127
              break;
128
         default:
129
              ego->t = X(mktriggen)(AWAKE_SQRTN_TABLE, ego->r * ego->m);
130
              break;
131
     }
132
}
133

    
134
static void destroy(plan *ego_)
135
{
136
     P *ego = (P *) ego_;
137
     X(plan_destroy_internal)(ego->cld);
138
}
139

    
140
static void print(const plan *ego_, printer *p)
141
{
142
     const P *ego = (const P *) ego_;
143
     p->print(p, "(dftw-genericbuf/%D-%D-%D%(%p%))",
144
              ego->batchsz, ego->r, ego->m, ego->cld);
145
}
146

    
147
static plan *mkcldw(const ct_solver *ego_,
148
                    INT r, INT irs, INT ors,
149
                    INT m, INT ms,
150
                    INT v, INT ivs, INT ovs,
151
                    INT mstart, INT mcount,
152
                    R *rio, R *iio,
153
                    planner *plnr)
154
{
155
     const S *ego = (const S *)ego_;
156
     P *pln;
157
     plan *cld = 0;
158
     R *buf;
159

    
160
     static const plan_adt padt = {
161
          0, awake, print, destroy
162
     };
163
     
164
     UNUSED(ivs); UNUSED(ovs); UNUSED(rio); UNUSED(iio);
165

    
166
     A(mstart >= 0 && mstart + mcount <= m);
167
     if (!applicable(ego, r, irs, ors, m, v, mcount, plnr))
168
          return (plan *)0;
169

    
170
     buf = (R *) MALLOC(sizeof(R) * 2 * BATCHDIST(r) * ego->batchsz, BUFFERS);
171
     cld = X(mkplan_d)(plnr,
172
                        X(mkproblem_dft_d)(
173
                             X(mktensor_1d)(r, 2, 2),
174
                             X(mktensor_1d)(ego->batchsz,
175
                                            2 * BATCHDIST(r),
176
                                            2 * BATCHDIST(r)),
177
                             buf, buf + 1, buf, buf + 1
178
                             )
179
                        );
180
     X(ifree)(buf);
181
     if (!cld) goto nada;
182

    
183
     pln = MKPLAN_DFTW(P, &padt, apply);
184
     pln->slv = ego;
185
     pln->cld = cld;
186
     pln->r = r;
187
     pln->m = m;
188
     pln->ms = ms;
189
     pln->rs = irs;
190
     pln->batchsz = ego->batchsz;
191
     pln->mb = mstart;
192
     pln->me = mstart + mcount;
193

    
194
     {
195
          double n0 = (r - 1) * (mcount - 1);
196
          pln->super.super.ops = cld->ops;
197
          pln->super.super.ops.mul += 8 * n0;
198
          pln->super.super.ops.add += 4 * n0;
199
          pln->super.super.ops.other += 8 * n0;
200
     }
201
     return &(pln->super.super);
202

    
203
 nada:
204
     X(plan_destroy_internal)(cld);
205
     return (plan *) 0;
206
}
207

    
208
static void regsolver(planner *plnr, INT r, INT batchsz)
209
{
210
     S *slv = (S *)X(mksolver_ct)(sizeof(S), r, DECDIT, mkcldw, 0);
211
     slv->batchsz = batchsz;
212
     REGISTER_SOLVER(plnr, &(slv->super.super));
213

    
214
     if (X(mksolver_ct_hook)) {
215
          slv = (S *)X(mksolver_ct_hook)(sizeof(S), r, DECDIT, mkcldw, 0);
216
          slv->batchsz = batchsz;
217
          REGISTER_SOLVER(plnr, &(slv->super.super));
218
     }
219

    
220
}
221

    
222
void X(ct_genericbuf_register)(planner *p)
223
{
224
     static const INT radices[] = { -1, -2, -4, -8, -16, -32, -64 };
225
     static const INT batchsizes[] = { 4, 8, 16, 32, 64 };
226
     unsigned i, j;
227

    
228
     for (i = 0; i < sizeof(radices) / sizeof(radices[0]); ++i)
229
          for (j = 0; j < sizeof(batchsizes) / sizeof(batchsizes[0]); ++j)
230
               regsolver(p, radices[i], batchsizes[j]);
231
}