annotate src/fftw-3.3.8/dft/dftw-generic.c @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents d0c2a83c1364
children
rev   line source
Chris@82 1 /*
Chris@82 2 * Copyright (c) 2003, 2007-14 Matteo Frigo
Chris@82 3 * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology
Chris@82 4 *
Chris@82 5 * This program is free software; you can redistribute it and/or modify
Chris@82 6 * it under the terms of the GNU General Public License as published by
Chris@82 7 * the Free Software Foundation; either version 2 of the License, or
Chris@82 8 * (at your option) any later version.
Chris@82 9 *
Chris@82 10 * This program is distributed in the hope that it will be useful,
Chris@82 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@82 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@82 13 * GNU General Public License for more details.
Chris@82 14 *
Chris@82 15 * You should have received a copy of the GNU General Public License
Chris@82 16 * along with this program; if not, write to the Free Software
Chris@82 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Chris@82 18 *
Chris@82 19 */
Chris@82 20
Chris@82 21 /* express a twiddle problem in terms of dft + multiplication by
Chris@82 22 twiddle factors */
Chris@82 23
Chris@82 24 #include "dft/ct.h"
Chris@82 25
Chris@82 26 typedef ct_solver S;
Chris@82 27
Chris@82 28 typedef struct {
Chris@82 29 plan_dftw super;
Chris@82 30
Chris@82 31 INT r, rs, m, mb, me, ms, v, vs;
Chris@82 32
Chris@82 33 plan *cld;
Chris@82 34
Chris@82 35 twid *td;
Chris@82 36
Chris@82 37 const S *slv;
Chris@82 38 int dec;
Chris@82 39 } P;
Chris@82 40
Chris@82 41 static void mktwiddle(P *ego, enum wakefulness wakefulness)
Chris@82 42 {
Chris@82 43 static const tw_instr tw[] = { { TW_FULL, 0, 0 }, { TW_NEXT, 1, 0 } };
Chris@82 44
Chris@82 45 /* note that R and M are swapped, to allow for sequential
Chris@82 46 access both to data and twiddles */
Chris@82 47 X(twiddle_awake)(wakefulness, &ego->td, tw,
Chris@82 48 ego->r * ego->m, ego->m, ego->r);
Chris@82 49 }
Chris@82 50
Chris@82 51 static void bytwiddle(const P *ego, R *rio, R *iio)
Chris@82 52 {
Chris@82 53 INT iv, ir, im;
Chris@82 54 INT r = ego->r, rs = ego->rs;
Chris@82 55 INT m = ego->m, mb = ego->mb, me = ego->me, ms = ego->ms;
Chris@82 56 INT v = ego->v, vs = ego->vs;
Chris@82 57 const R *W = ego->td->W;
Chris@82 58
Chris@82 59 mb += (mb == 0); /* skip m=0 iteration */
Chris@82 60 for (iv = 0; iv < v; ++iv) {
Chris@82 61 for (ir = 1; ir < r; ++ir) {
Chris@82 62 for (im = mb; im < me; ++im) {
Chris@82 63 R *pr = rio + ms * im + rs * ir;
Chris@82 64 R *pi = iio + ms * im + rs * ir;
Chris@82 65 E xr = *pr;
Chris@82 66 E xi = *pi;
Chris@82 67 E wr = W[2 * im + (2 * (m-1)) * ir - 2];
Chris@82 68 E wi = W[2 * im + (2 * (m-1)) * ir - 1];
Chris@82 69 *pr = xr * wr + xi * wi;
Chris@82 70 *pi = xi * wr - xr * wi;
Chris@82 71 }
Chris@82 72 }
Chris@82 73 rio += vs;
Chris@82 74 iio += vs;
Chris@82 75 }
Chris@82 76 }
Chris@82 77
Chris@82 78 static int applicable(INT irs, INT ors, INT ivs, INT ovs,
Chris@82 79 const planner *plnr)
Chris@82 80 {
Chris@82 81 return (1
Chris@82 82 && irs == ors
Chris@82 83 && ivs == ovs
Chris@82 84 && !NO_SLOWP(plnr)
Chris@82 85 );
Chris@82 86 }
Chris@82 87
Chris@82 88 static void apply_dit(const plan *ego_, R *rio, R *iio)
Chris@82 89 {
Chris@82 90 const P *ego = (const P *) ego_;
Chris@82 91 plan_dft *cld;
Chris@82 92 INT dm = ego->ms * ego->mb;
Chris@82 93
Chris@82 94 bytwiddle(ego, rio, iio);
Chris@82 95
Chris@82 96 cld = (plan_dft *) ego->cld;
Chris@82 97 cld->apply(ego->cld, rio + dm, iio + dm, rio + dm, iio + dm);
Chris@82 98 }
Chris@82 99
Chris@82 100 static void apply_dif(const plan *ego_, R *rio, R *iio)
Chris@82 101 {
Chris@82 102 const P *ego = (const P *) ego_;
Chris@82 103 plan_dft *cld;
Chris@82 104 INT dm = ego->ms * ego->mb;
Chris@82 105
Chris@82 106 cld = (plan_dft *) ego->cld;
Chris@82 107 cld->apply(ego->cld, rio + dm, iio + dm, rio + dm, iio + dm);
Chris@82 108
Chris@82 109 bytwiddle(ego, rio, iio);
Chris@82 110 }
Chris@82 111
Chris@82 112 static void awake(plan *ego_, enum wakefulness wakefulness)
Chris@82 113 {
Chris@82 114 P *ego = (P *) ego_;
Chris@82 115 X(plan_awake)(ego->cld, wakefulness);
Chris@82 116 mktwiddle(ego, wakefulness);
Chris@82 117 }
Chris@82 118
Chris@82 119 static void destroy(plan *ego_)
Chris@82 120 {
Chris@82 121 P *ego = (P *) ego_;
Chris@82 122 X(plan_destroy_internal)(ego->cld);
Chris@82 123 }
Chris@82 124
Chris@82 125 static void print(const plan *ego_, printer *p)
Chris@82 126 {
Chris@82 127 const P *ego = (const P *) ego_;
Chris@82 128 p->print(p, "(dftw-generic-%s-%D-%D%v%(%p%))",
Chris@82 129 ego->dec == DECDIT ? "dit" : "dif",
Chris@82 130 ego->r, ego->m, ego->v, ego->cld);
Chris@82 131 }
Chris@82 132
Chris@82 133 static plan *mkcldw(const ct_solver *ego_,
Chris@82 134 INT r, INT irs, INT ors,
Chris@82 135 INT m, INT ms,
Chris@82 136 INT v, INT ivs, INT ovs,
Chris@82 137 INT mstart, INT mcount,
Chris@82 138 R *rio, R *iio,
Chris@82 139 planner *plnr)
Chris@82 140 {
Chris@82 141 const S *ego = (const S *)ego_;
Chris@82 142 P *pln;
Chris@82 143 plan *cld = 0;
Chris@82 144 INT dm = ms * mstart;
Chris@82 145
Chris@82 146 static const plan_adt padt = {
Chris@82 147 0, awake, print, destroy
Chris@82 148 };
Chris@82 149
Chris@82 150 A(mstart >= 0 && mstart + mcount <= m);
Chris@82 151 if (!applicable(irs, ors, ivs, ovs, plnr))
Chris@82 152 return (plan *)0;
Chris@82 153
Chris@82 154 cld = X(mkplan_d)(plnr,
Chris@82 155 X(mkproblem_dft_d)(
Chris@82 156 X(mktensor_1d)(r, irs, irs),
Chris@82 157 X(mktensor_2d)(mcount, ms, ms, v, ivs, ivs),
Chris@82 158 rio + dm, iio + dm, rio + dm, iio + dm)
Chris@82 159 );
Chris@82 160 if (!cld) goto nada;
Chris@82 161
Chris@82 162 pln = MKPLAN_DFTW(P, &padt, ego->dec == DECDIT ? apply_dit : apply_dif);
Chris@82 163 pln->slv = ego;
Chris@82 164 pln->cld = cld;
Chris@82 165 pln->r = r;
Chris@82 166 pln->rs = irs;
Chris@82 167 pln->m = m;
Chris@82 168 pln->ms = ms;
Chris@82 169 pln->v = v;
Chris@82 170 pln->vs = ivs;
Chris@82 171 pln->mb = mstart;
Chris@82 172 pln->me = mstart + mcount;
Chris@82 173 pln->dec = ego->dec;
Chris@82 174 pln->td = 0;
Chris@82 175
Chris@82 176 {
Chris@82 177 double n0 = (r - 1) * (mcount - 1) * v;
Chris@82 178 pln->super.super.ops = cld->ops;
Chris@82 179 pln->super.super.ops.mul += 8 * n0;
Chris@82 180 pln->super.super.ops.add += 4 * n0;
Chris@82 181 pln->super.super.ops.other += 8 * n0;
Chris@82 182 }
Chris@82 183 return &(pln->super.super);
Chris@82 184
Chris@82 185 nada:
Chris@82 186 X(plan_destroy_internal)(cld);
Chris@82 187 return (plan *) 0;
Chris@82 188 }
Chris@82 189
Chris@82 190 static void regsolver(planner *plnr, INT r, int dec)
Chris@82 191 {
Chris@82 192 S *slv = (S *)X(mksolver_ct)(sizeof(S), r, dec, mkcldw, 0);
Chris@82 193 REGISTER_SOLVER(plnr, &(slv->super));
Chris@82 194 if (X(mksolver_ct_hook)) {
Chris@82 195 slv = (S *)X(mksolver_ct_hook)(sizeof(S), r, dec, mkcldw, 0);
Chris@82 196 REGISTER_SOLVER(plnr, &(slv->super));
Chris@82 197 }
Chris@82 198 }
Chris@82 199
Chris@82 200 void X(ct_generic_register)(planner *p)
Chris@82 201 {
Chris@82 202 regsolver(p, 0, DECDIT);
Chris@82 203 regsolver(p, 0, DECDIF);
Chris@82 204 }