~diresu/blender/blender-command-port

« back to all changes in this revision

Viewing changes to extern/fftw/dft/generic.c

  • Committer: theeth
  • Date: 2008-10-14 16:52:04 UTC
  • Revision ID: vcs-imports@canonical.com-20081014165204-r32w2gm6s0osvdhn
copy back trunk

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
     twid *td;
 
30
     INT n, is, os;
 
31
} P;
 
32
 
 
33
 
 
34
static void cdot(INT n, const E *x, const R *w, 
 
35
                 R *or0, R *oi0, R *or1, R *oi1)
 
36
{
 
37
     INT i;
 
38
 
 
39
     E rr = x[0], ri = 0, ir = x[1], ii = 0; 
 
40
     x += 2;
 
41
     for (i = 1; i + i < n; ++i) {
 
42
          rr += x[0] * w[0];
 
43
          ir += x[1] * w[0];
 
44
          ri += x[2] * w[1];
 
45
          ii += x[3] * w[1];
 
46
          x += 4; w += 2;
 
47
     }
 
48
     *or0 = rr + ii;
 
49
     *oi0 = ir - ri;
 
50
     *or1 = rr - ii;
 
51
     *oi1 = ir + ri;
 
52
}
 
53
 
 
54
static void hartley(INT n, const R *xr, const R *xi, INT xs, E *o,
 
55
                    R *pr, R *pi)
 
56
{
 
57
     INT i;
 
58
     E sr, si;
 
59
     o[0] = sr = xr[0]; o[1] = si = xi[0]; o += 2;
 
60
     for (i = 1; i + i < n; ++i) {
 
61
          sr += (o[0] = xr[i * xs] + xr[(n - i) * xs]);
 
62
          si += (o[1] = xi[i * xs] + xi[(n - i) * xs]);
 
63
          o[2] = xr[i * xs] - xr[(n - i) * xs];
 
64
          o[3] = xi[i * xs] - xi[(n - i) * xs];
 
65
          o += 4;
 
66
     }
 
67
     *pr = sr;
 
68
     *pi = si;
 
69
}
 
70
                    
 
71
static void apply(const plan *ego_, R *ri, R *ii, R *ro, R *io)
 
72
{
 
73
     const P *ego = (const P *) ego_;
 
74
     INT i;
 
75
     INT n = ego->n, is = ego->is, os = ego->os;
 
76
     const R *W = ego->td->W;
 
77
     E *buf;
 
78
 
 
79
     STACK_MALLOC(E *, buf, n * 2 * sizeof(E));
 
80
     hartley(n, ri, ii, is, buf, ro, io);
 
81
 
 
82
     for (i = 1; i + i < n; ++i) {
 
83
          cdot(n, buf, W,
 
84
               ro + i * os, io + i * os,
 
85
               ro + (n - i) * os, io + (n - i) * os);
 
86
          W += n - 1;
 
87
     }
 
88
 
 
89
     STACK_FREE(buf);
 
90
}
 
91
 
 
92
static void awake(plan *ego_, enum wakefulness wakefulness)
 
93
{
 
94
     P *ego = (P *) ego_;
 
95
     static const tw_instr half_tw[] = {
 
96
          { TW_HALF, 1, 0 },
 
97
          { TW_NEXT, 1, 0 }
 
98
     };
 
99
 
 
100
     X(twiddle_awake)(wakefulness, &ego->td, half_tw, ego->n, ego->n,
 
101
                      (ego->n - 1) / 2);
 
102
}
 
103
 
 
104
static void print(const plan *ego_, printer *p)
 
105
{
 
106
     const P *ego = (const P *) ego_;
 
107
 
 
108
     p->print(p, "(dft-generic-%D)", ego->n);
 
109
}
 
110
 
 
111
static int applicable0(const problem *p_)
 
112
{
 
113
     const problem_dft *p = (const problem_dft *) p_;
 
114
     return (1
 
115
             && p->sz->rnk == 1
 
116
             && p->vecsz->rnk == 0
 
117
             && (p->sz->dims[0].n % 2) == 1 
 
118
             && X(is_prime)(p->sz->dims[0].n)
 
119
          );
 
120
}
 
121
 
 
122
static int applicable(const solver *ego, const problem *p_, 
 
123
                      const planner *plnr)
 
124
{
 
125
     UNUSED(ego);
 
126
     if (NO_SLOWP(plnr)) return 0;
 
127
     if (!applicable0(p_)) return 0;
 
128
 
 
129
     if (NO_LARGE_GENERICP(plnr)) {
 
130
          const problem_dft *p = (const problem_dft *) p_;
 
131
          if (p->sz->dims[0].n >= GENERIC_MIN_BAD) return 0; 
 
132
     }
 
133
     return 1;
 
134
}
 
135
 
 
136
static plan *mkplan(const solver *ego, const problem *p_, planner *plnr)
 
137
{
 
138
     const problem_dft *p;
 
139
     P *pln;
 
140
     INT n;
 
141
 
 
142
     static const plan_adt padt = {
 
143
          X(dft_solve), awake, print, X(plan_null_destroy)
 
144
     };
 
145
 
 
146
     if (!applicable(ego, p_, plnr))
 
147
          return (plan *)0;
 
148
 
 
149
     pln = MKPLAN_DFT(P, &padt, apply);
 
150
 
 
151
     p = (const problem_dft *) p_;
 
152
     pln->n = n = p->sz->dims[0].n;
 
153
     pln->is = p->sz->dims[0].is;
 
154
     pln->os = p->sz->dims[0].os;
 
155
     pln->td = 0;
 
156
 
 
157
     pln->super.super.ops.add = (n-1) * 5;
 
158
     pln->super.super.ops.mul = 0;
 
159
     pln->super.super.ops.fma = (n-1) * (n-1) ;
 
160
#if 0 /* these are nice pipelined sequential loads and should cost nothing */
 
161
     pln->super.super.ops.other = (n-1)*(4 + 1 + 2 * (n-1));  /* approximate */
 
162
#endif
 
163
 
 
164
     return &(pln->super.super);
 
165
}
 
166
 
 
167
static solver *mksolver(void)
 
168
{
 
169
     static const solver_adt sadt = { PROBLEM_DFT, mkplan };
 
170
     S *slv = MKSOLVER(S, &sadt);
 
171
     return &(slv->super);
 
172
}
 
173
 
 
174
void X(dft_generic_register)(planner *p)
 
175
{
 
176
     REGISTER_SOLVER(p, mksolver());
 
177
}