annotate src/fftw-3.3.8/rdft/ct-hc2c.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 #include "ct-hc2c.h"
Chris@82 22 #include "dft/dft.h"
Chris@82 23
Chris@82 24 typedef struct {
Chris@82 25 plan_rdft2 super;
Chris@82 26 plan *cld;
Chris@82 27 plan *cldw;
Chris@82 28 INT r;
Chris@82 29 } P;
Chris@82 30
Chris@82 31 static void apply_dit(const plan *ego_, R *r0, R *r1, R *cr, R *ci)
Chris@82 32 {
Chris@82 33 const P *ego = (const P *) ego_;
Chris@82 34 plan_rdft *cld;
Chris@82 35 plan_hc2c *cldw;
Chris@82 36 UNUSED(r1);
Chris@82 37
Chris@82 38 cld = (plan_rdft *) ego->cld;
Chris@82 39 cld->apply(ego->cld, r0, cr);
Chris@82 40
Chris@82 41 cldw = (plan_hc2c *) ego->cldw;
Chris@82 42 cldw->apply(ego->cldw, cr, ci);
Chris@82 43 }
Chris@82 44
Chris@82 45 static void apply_dif(const plan *ego_, R *r0, R *r1, R *cr, R *ci)
Chris@82 46 {
Chris@82 47 const P *ego = (const P *) ego_;
Chris@82 48 plan_rdft *cld;
Chris@82 49 plan_hc2c *cldw;
Chris@82 50 UNUSED(r1);
Chris@82 51
Chris@82 52 cldw = (plan_hc2c *) ego->cldw;
Chris@82 53 cldw->apply(ego->cldw, cr, ci);
Chris@82 54
Chris@82 55 cld = (plan_rdft *) ego->cld;
Chris@82 56 cld->apply(ego->cld, cr, r0);
Chris@82 57 }
Chris@82 58
Chris@82 59 static void apply_dit_dft(const plan *ego_, R *r0, R *r1, R *cr, R *ci)
Chris@82 60 {
Chris@82 61 const P *ego = (const P *) ego_;
Chris@82 62 plan_dft *cld;
Chris@82 63 plan_hc2c *cldw;
Chris@82 64
Chris@82 65 cld = (plan_dft *) ego->cld;
Chris@82 66 cld->apply(ego->cld, r0, r1, cr, ci);
Chris@82 67
Chris@82 68 cldw = (plan_hc2c *) ego->cldw;
Chris@82 69 cldw->apply(ego->cldw, cr, ci);
Chris@82 70 }
Chris@82 71
Chris@82 72 static void apply_dif_dft(const plan *ego_, R *r0, R *r1, R *cr, R *ci)
Chris@82 73 {
Chris@82 74 const P *ego = (const P *) ego_;
Chris@82 75 plan_dft *cld;
Chris@82 76 plan_hc2c *cldw;
Chris@82 77
Chris@82 78 cldw = (plan_hc2c *) ego->cldw;
Chris@82 79 cldw->apply(ego->cldw, cr, ci);
Chris@82 80
Chris@82 81 cld = (plan_dft *) ego->cld;
Chris@82 82 cld->apply(ego->cld, ci, cr, r1, r0);
Chris@82 83 }
Chris@82 84
Chris@82 85 static void awake(plan *ego_, enum wakefulness wakefulness)
Chris@82 86 {
Chris@82 87 P *ego = (P *) ego_;
Chris@82 88 X(plan_awake)(ego->cld, wakefulness);
Chris@82 89 X(plan_awake)(ego->cldw, wakefulness);
Chris@82 90 }
Chris@82 91
Chris@82 92 static void destroy(plan *ego_)
Chris@82 93 {
Chris@82 94 P *ego = (P *) ego_;
Chris@82 95 X(plan_destroy_internal)(ego->cldw);
Chris@82 96 X(plan_destroy_internal)(ego->cld);
Chris@82 97 }
Chris@82 98
Chris@82 99 static void print(const plan *ego_, printer *p)
Chris@82 100 {
Chris@82 101 const P *ego = (const P *) ego_;
Chris@82 102 p->print(p, "(rdft2-ct-%s/%D%(%p%)%(%p%))",
Chris@82 103 (ego->super.apply == apply_dit ||
Chris@82 104 ego->super.apply == apply_dit_dft)
Chris@82 105 ? "dit" : "dif",
Chris@82 106 ego->r, ego->cldw, ego->cld);
Chris@82 107 }
Chris@82 108
Chris@82 109 static int applicable0(const hc2c_solver *ego, const problem *p_, planner *plnr)
Chris@82 110 {
Chris@82 111 const problem_rdft2 *p = (const problem_rdft2 *) p_;
Chris@82 112 INT r;
Chris@82 113
Chris@82 114 return (1
Chris@82 115 && p->sz->rnk == 1
Chris@82 116 && p->vecsz->rnk <= 1
Chris@82 117
Chris@82 118 && (/* either the problem is R2HC, which is solved by DIT */
Chris@82 119 (p->kind == R2HC)
Chris@82 120 ||
Chris@82 121 /* or the problem is HC2R, in which case it is solved
Chris@82 122 by DIF, which destroys the input */
Chris@82 123 (p->kind == HC2R &&
Chris@82 124 (p->r0 == p->cr || !NO_DESTROY_INPUTP(plnr))))
Chris@82 125
Chris@82 126 && ((r = X(choose_radix)(ego->r, p->sz->dims[0].n)) > 0)
Chris@82 127 && p->sz->dims[0].n > r);
Chris@82 128 }
Chris@82 129
Chris@82 130 static int hc2c_applicable(const hc2c_solver *ego, const problem *p_,
Chris@82 131 planner *plnr)
Chris@82 132 {
Chris@82 133 const problem_rdft2 *p;
Chris@82 134
Chris@82 135 if (!applicable0(ego, p_, plnr))
Chris@82 136 return 0;
Chris@82 137
Chris@82 138 p = (const problem_rdft2 *) p_;
Chris@82 139
Chris@82 140 return (0
Chris@82 141 || p->vecsz->rnk == 0
Chris@82 142 || !NO_VRECURSEP(plnr)
Chris@82 143 );
Chris@82 144 }
Chris@82 145
Chris@82 146 static plan *mkplan(const solver *ego_, const problem *p_, planner *plnr)
Chris@82 147 {
Chris@82 148 const hc2c_solver *ego = (const hc2c_solver *) ego_;
Chris@82 149 const problem_rdft2 *p;
Chris@82 150 P *pln = 0;
Chris@82 151 plan *cld = 0, *cldw = 0;
Chris@82 152 INT n, r, m, v, ivs, ovs;
Chris@82 153 iodim *d;
Chris@82 154
Chris@82 155 static const plan_adt padt = {
Chris@82 156 X(rdft2_solve), awake, print, destroy
Chris@82 157 };
Chris@82 158
Chris@82 159 if (!hc2c_applicable(ego, p_, plnr))
Chris@82 160 return (plan *) 0;
Chris@82 161
Chris@82 162 p = (const problem_rdft2 *) p_;
Chris@82 163 d = p->sz->dims;
Chris@82 164 n = d[0].n;
Chris@82 165 r = X(choose_radix)(ego->r, n);
Chris@82 166 A((r % 2) == 0);
Chris@82 167 m = n / r;
Chris@82 168
Chris@82 169 X(tensor_tornk1)(p->vecsz, &v, &ivs, &ovs);
Chris@82 170
Chris@82 171 switch (p->kind) {
Chris@82 172 case R2HC:
Chris@82 173 cldw = ego->mkcldw(ego, R2HC,
Chris@82 174 r, m * d[0].os,
Chris@82 175 m, d[0].os,
Chris@82 176 v, ovs,
Chris@82 177 p->cr, p->ci, plnr);
Chris@82 178 if (!cldw) goto nada;
Chris@82 179
Chris@82 180 switch (ego->hc2ckind) {
Chris@82 181 case HC2C_VIA_RDFT:
Chris@82 182 cld = X(mkplan_d)(
Chris@82 183 plnr,
Chris@82 184 X(mkproblem_rdft_1_d)(
Chris@82 185 X(mktensor_1d)(m, (r/2)*d[0].is, d[0].os),
Chris@82 186 X(mktensor_3d)(
Chris@82 187 2, p->r1 - p->r0, p->ci - p->cr,
Chris@82 188 r / 2, d[0].is, m * d[0].os,
Chris@82 189 v, ivs, ovs),
Chris@82 190 p->r0, p->cr, R2HC)
Chris@82 191 );
Chris@82 192 if (!cld) goto nada;
Chris@82 193
Chris@82 194 pln = MKPLAN_RDFT2(P, &padt, apply_dit);
Chris@82 195 break;
Chris@82 196
Chris@82 197 case HC2C_VIA_DFT:
Chris@82 198 cld = X(mkplan_d)(
Chris@82 199 plnr,
Chris@82 200 X(mkproblem_dft_d)(
Chris@82 201 X(mktensor_1d)(m, (r/2)*d[0].is, d[0].os),
Chris@82 202 X(mktensor_2d)(
Chris@82 203 r / 2, d[0].is, m * d[0].os,
Chris@82 204 v, ivs, ovs),
Chris@82 205 p->r0, p->r1, p->cr, p->ci)
Chris@82 206 );
Chris@82 207 if (!cld) goto nada;
Chris@82 208
Chris@82 209 pln = MKPLAN_RDFT2(P, &padt, apply_dit_dft);
Chris@82 210 break;
Chris@82 211 }
Chris@82 212 break;
Chris@82 213
Chris@82 214 case HC2R:
Chris@82 215 cldw = ego->mkcldw(ego, HC2R,
Chris@82 216 r, m * d[0].is,
Chris@82 217 m, d[0].is,
Chris@82 218 v, ivs,
Chris@82 219 p->cr, p->ci, plnr);
Chris@82 220 if (!cldw) goto nada;
Chris@82 221
Chris@82 222 switch (ego->hc2ckind) {
Chris@82 223 case HC2C_VIA_RDFT:
Chris@82 224 cld = X(mkplan_d)(
Chris@82 225 plnr,
Chris@82 226 X(mkproblem_rdft_1_d)(
Chris@82 227 X(mktensor_1d)(m, d[0].is, (r/2)*d[0].os),
Chris@82 228 X(mktensor_3d)(
Chris@82 229 2, p->ci - p->cr, p->r1 - p->r0,
Chris@82 230 r / 2, m * d[0].is, d[0].os,
Chris@82 231 v, ivs, ovs),
Chris@82 232 p->cr, p->r0, HC2R)
Chris@82 233 );
Chris@82 234 if (!cld) goto nada;
Chris@82 235
Chris@82 236 pln = MKPLAN_RDFT2(P, &padt, apply_dif);
Chris@82 237 break;
Chris@82 238
Chris@82 239 case HC2C_VIA_DFT:
Chris@82 240 cld = X(mkplan_d)(
Chris@82 241 plnr,
Chris@82 242 X(mkproblem_dft_d)(
Chris@82 243 X(mktensor_1d)(m, d[0].is, (r/2)*d[0].os),
Chris@82 244 X(mktensor_2d)(
Chris@82 245 r / 2, m * d[0].is, d[0].os,
Chris@82 246 v, ivs, ovs),
Chris@82 247 p->ci, p->cr, p->r1, p->r0)
Chris@82 248 );
Chris@82 249 if (!cld) goto nada;
Chris@82 250
Chris@82 251 pln = MKPLAN_RDFT2(P, &padt, apply_dif_dft);
Chris@82 252 break;
Chris@82 253 }
Chris@82 254 break;
Chris@82 255
Chris@82 256 default:
Chris@82 257 A(0);
Chris@82 258 }
Chris@82 259
Chris@82 260 pln->cld = cld;
Chris@82 261 pln->cldw = cldw;
Chris@82 262 pln->r = r;
Chris@82 263 X(ops_add)(&cld->ops, &cldw->ops, &pln->super.super.ops);
Chris@82 264
Chris@82 265 /* inherit could_prune_now_p attribute from cldw */
Chris@82 266 pln->super.super.could_prune_now_p = cldw->could_prune_now_p;
Chris@82 267
Chris@82 268 return &(pln->super.super);
Chris@82 269
Chris@82 270 nada:
Chris@82 271 X(plan_destroy_internal)(cldw);
Chris@82 272 X(plan_destroy_internal)(cld);
Chris@82 273 return (plan *) 0;
Chris@82 274 }
Chris@82 275
Chris@82 276 hc2c_solver *X(mksolver_hc2c)(size_t size, INT r,
Chris@82 277 hc2c_kind hc2ckind,
Chris@82 278 hc2c_mkinferior mkcldw)
Chris@82 279 {
Chris@82 280 static const solver_adt sadt = { PROBLEM_RDFT2, mkplan, 0 };
Chris@82 281 hc2c_solver *slv = (hc2c_solver *)X(mksolver)(size, &sadt);
Chris@82 282 slv->r = r;
Chris@82 283 slv->hc2ckind = hc2ckind;
Chris@82 284 slv->mkcldw = mkcldw;
Chris@82 285 return slv;
Chris@82 286 }
Chris@82 287
Chris@82 288 plan *X(mkplan_hc2c)(size_t size, const plan_adt *adt, hc2capply apply)
Chris@82 289 {
Chris@82 290 plan_hc2c *ego;
Chris@82 291
Chris@82 292 ego = (plan_hc2c *) X(mkplan)(size, adt);
Chris@82 293 ego->apply = apply;
Chris@82 294
Chris@82 295 return &(ego->super);
Chris@82 296 }