annotate src/fftw-3.3.8/api/mapflags.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 "api/api.h"
Chris@82 22 #include <math.h>
Chris@82 23
Chris@82 24 /* a flag operation: x is either a flag, in which case xm == 0, or
Chris@82 25 a mask, in which case xm == x; using this we can compactly code
Chris@82 26 the various bit operations via (flags & x) ^ xm or (flags | x) ^ xm. */
Chris@82 27 typedef struct {
Chris@82 28 unsigned x, xm;
Chris@82 29 } flagmask;
Chris@82 30
Chris@82 31 typedef struct {
Chris@82 32 flagmask flag;
Chris@82 33 flagmask op;
Chris@82 34 } flagop;
Chris@82 35
Chris@82 36 #define FLAGP(f, msk)(((f) & (msk).x) ^ (msk).xm)
Chris@82 37 #define OP(f, msk)(((f) | (msk).x) ^ (msk).xm)
Chris@82 38
Chris@82 39 #define YES(x) {x, 0}
Chris@82 40 #define NO(x) {x, x}
Chris@82 41 #define IMPLIES(predicate, consequence) { predicate, consequence }
Chris@82 42 #define EQV(a, b) IMPLIES(YES(a), YES(b)), IMPLIES(NO(a), NO(b))
Chris@82 43 #define NEQV(a, b) IMPLIES(YES(a), NO(b)), IMPLIES(NO(a), YES(b))
Chris@82 44
Chris@82 45 static void map_flags(unsigned *iflags, unsigned *oflags,
Chris@82 46 const flagop flagmap[], size_t nmap)
Chris@82 47 {
Chris@82 48 size_t i;
Chris@82 49 for (i = 0; i < nmap; ++i)
Chris@82 50 if (FLAGP(*iflags, flagmap[i].flag))
Chris@82 51 *oflags = OP(*oflags, flagmap[i].op);
Chris@82 52 }
Chris@82 53
Chris@82 54 /* encoding of the planner timelimit into a BITS_FOR_TIMELIMIT-bits
Chris@82 55 nonnegative integer, such that we can still view the integer as
Chris@82 56 ``impatience'': higher means *lower* time limit, and 0 is the
Chris@82 57 highest possible value (about 1 year of calendar time) */
Chris@82 58 static unsigned timelimit_to_flags(double timelimit)
Chris@82 59 {
Chris@82 60 const double tmax = 365 * 24 * 3600;
Chris@82 61 const double tstep = 1.05;
Chris@82 62 const int nsteps = (1 << BITS_FOR_TIMELIMIT);
Chris@82 63 int x;
Chris@82 64
Chris@82 65 if (timelimit < 0 || timelimit >= tmax)
Chris@82 66 return 0;
Chris@82 67 if (timelimit <= 1.0e-10)
Chris@82 68 return nsteps - 1;
Chris@82 69
Chris@82 70 x = (int) (0.5 + (log(tmax / timelimit) / log(tstep)));
Chris@82 71
Chris@82 72 if (x < 0) x = 0;
Chris@82 73 if (x >= nsteps) x = nsteps - 1;
Chris@82 74 return x;
Chris@82 75 }
Chris@82 76
Chris@82 77 void X(mapflags)(planner *plnr, unsigned flags)
Chris@82 78 {
Chris@82 79 unsigned l, u, t;
Chris@82 80
Chris@82 81 /* map of api flags -> api flags, to implement consistency rules
Chris@82 82 and combination flags */
Chris@82 83 const flagop self_flagmap[] = {
Chris@82 84 /* in some cases (notably for halfcomplex->real transforms),
Chris@82 85 DESTROY_INPUT is the default, so we need to support
Chris@82 86 an inverse flag to disable it.
Chris@82 87
Chris@82 88 (PRESERVE, DESTROY) -> (PRESERVE, DESTROY)
Chris@82 89 (0, 0) (1, 0)
Chris@82 90 (0, 1) (0, 1)
Chris@82 91 (1, 0) (1, 0)
Chris@82 92 (1, 1) (1, 0)
Chris@82 93 */
Chris@82 94 IMPLIES(YES(FFTW_PRESERVE_INPUT), NO(FFTW_DESTROY_INPUT)),
Chris@82 95 IMPLIES(NO(FFTW_DESTROY_INPUT), YES(FFTW_PRESERVE_INPUT)),
Chris@82 96
Chris@82 97 IMPLIES(YES(FFTW_EXHAUSTIVE), YES(FFTW_PATIENT)),
Chris@82 98
Chris@82 99 IMPLIES(YES(FFTW_ESTIMATE), NO(FFTW_PATIENT)),
Chris@82 100 IMPLIES(YES(FFTW_ESTIMATE),
Chris@82 101 YES(FFTW_ESTIMATE_PATIENT
Chris@82 102 | FFTW_NO_INDIRECT_OP
Chris@82 103 | FFTW_ALLOW_PRUNING)),
Chris@82 104
Chris@82 105 IMPLIES(NO(FFTW_EXHAUSTIVE),
Chris@82 106 YES(FFTW_NO_SLOW)),
Chris@82 107
Chris@82 108 /* a canonical set of fftw2-like impatience flags */
Chris@82 109 IMPLIES(NO(FFTW_PATIENT),
Chris@82 110 YES(FFTW_NO_VRECURSE
Chris@82 111 | FFTW_NO_RANK_SPLITS
Chris@82 112 | FFTW_NO_VRANK_SPLITS
Chris@82 113 | FFTW_NO_NONTHREADED
Chris@82 114 | FFTW_NO_DFT_R2HC
Chris@82 115 | FFTW_NO_FIXED_RADIX_LARGE_N
Chris@82 116 | FFTW_BELIEVE_PCOST))
Chris@82 117 };
Chris@82 118
Chris@82 119 /* map of (processed) api flags to internal problem/planner flags */
Chris@82 120 const flagop l_flagmap[] = {
Chris@82 121 EQV(FFTW_PRESERVE_INPUT, NO_DESTROY_INPUT),
Chris@82 122 EQV(FFTW_NO_SIMD, NO_SIMD),
Chris@82 123 EQV(FFTW_CONSERVE_MEMORY, CONSERVE_MEMORY),
Chris@82 124 EQV(FFTW_NO_BUFFERING, NO_BUFFERING),
Chris@82 125 NEQV(FFTW_ALLOW_LARGE_GENERIC, NO_LARGE_GENERIC)
Chris@82 126 };
Chris@82 127
Chris@82 128 const flagop u_flagmap[] = {
Chris@82 129 IMPLIES(YES(FFTW_EXHAUSTIVE), NO(0xFFFFFFFF)),
Chris@82 130 IMPLIES(NO(FFTW_EXHAUSTIVE), YES(NO_UGLY)),
Chris@82 131
Chris@82 132 /* the following are undocumented, "beyond-guru" flags that
Chris@82 133 require some understanding of FFTW internals */
Chris@82 134 EQV(FFTW_ESTIMATE_PATIENT, ESTIMATE),
Chris@82 135 EQV(FFTW_ALLOW_PRUNING, ALLOW_PRUNING),
Chris@82 136 EQV(FFTW_BELIEVE_PCOST, BELIEVE_PCOST),
Chris@82 137 EQV(FFTW_NO_DFT_R2HC, NO_DFT_R2HC),
Chris@82 138 EQV(FFTW_NO_NONTHREADED, NO_NONTHREADED),
Chris@82 139 EQV(FFTW_NO_INDIRECT_OP, NO_INDIRECT_OP),
Chris@82 140 EQV(FFTW_NO_RANK_SPLITS, NO_RANK_SPLITS),
Chris@82 141 EQV(FFTW_NO_VRANK_SPLITS, NO_VRANK_SPLITS),
Chris@82 142 EQV(FFTW_NO_VRECURSE, NO_VRECURSE),
Chris@82 143 EQV(FFTW_NO_SLOW, NO_SLOW),
Chris@82 144 EQV(FFTW_NO_FIXED_RADIX_LARGE_N, NO_FIXED_RADIX_LARGE_N)
Chris@82 145 };
Chris@82 146
Chris@82 147 map_flags(&flags, &flags, self_flagmap, NELEM(self_flagmap));
Chris@82 148
Chris@82 149 l = u = 0;
Chris@82 150 map_flags(&flags, &l, l_flagmap, NELEM(l_flagmap));
Chris@82 151 map_flags(&flags, &u, u_flagmap, NELEM(u_flagmap));
Chris@82 152
Chris@82 153 /* enforce l <= u */
Chris@82 154 PLNR_L(plnr) = l;
Chris@82 155 PLNR_U(plnr) = u | l;
Chris@82 156
Chris@82 157 /* assert that the conversion didn't lose bits */
Chris@82 158 A(PLNR_L(plnr) == l);
Chris@82 159 A(PLNR_U(plnr) == (u | l));
Chris@82 160
Chris@82 161 /* compute flags representation of the timelimit */
Chris@82 162 t = timelimit_to_flags(plnr->timelimit);
Chris@82 163
Chris@82 164 PLNR_TIMELIMIT_IMPATIENCE(plnr) = t;
Chris@82 165 A(PLNR_TIMELIMIT_IMPATIENCE(plnr) == t);
Chris@82 166 }