annotate src/fftw-3.3.8/tests/hook.c @ 82:d0c2a83c1364

Add FFTW 3.3.8 source, and a Linux build
author Chris Cannam
date Tue, 19 Nov 2019 14:52:55 +0000
parents
children
rev   line source
Chris@82 1 /* fftw hook to be used in the benchmark program.
Chris@82 2
Chris@82 3 We keep it in a separate file because
Chris@82 4
Chris@82 5 1) bench.c is supposed to test the API---we do not want to #include
Chris@82 6 "ifftw.h" and accidentally use internal symbols/macros.
Chris@82 7 2) this code is a royal mess. The messiness is due to
Chris@82 8 A) confusion between internal fftw tensors and bench_tensor's
Chris@82 9 (which we want to keep separate because the benchmark
Chris@82 10 program tests other routines too)
Chris@82 11 B) despite A), our desire to recycle the libbench verifier.
Chris@82 12 */
Chris@82 13
Chris@82 14 #include <stdio.h>
Chris@82 15 #include "libbench2/bench-user.h"
Chris@82 16
Chris@82 17 #define CALLING_FFTW /* hack for Windows DLL nonsense */
Chris@82 18 #include "api/api.h"
Chris@82 19 #include "dft/dft.h"
Chris@82 20 #include "rdft/rdft.h"
Chris@82 21
Chris@82 22 extern int paranoid; /* in bench.c */
Chris@82 23 extern X(plan) the_plan; /* in bench.c */
Chris@82 24
Chris@82 25 /*
Chris@82 26 transform an fftw tensor into a bench_tensor.
Chris@82 27 */
Chris@82 28 static bench_tensor *fftw_tensor_to_bench_tensor(tensor *t)
Chris@82 29 {
Chris@82 30 bench_tensor *bt = mktensor(t->rnk);
Chris@82 31
Chris@82 32 if (FINITE_RNK(t->rnk)) {
Chris@82 33 int i;
Chris@82 34 for (i = 0; i < t->rnk; ++i) {
Chris@82 35 /* FIXME: 64-bit unclean because of INT -> int conversion */
Chris@82 36 bt->dims[i].n = t->dims[i].n;
Chris@82 37 bt->dims[i].is = t->dims[i].is;
Chris@82 38 bt->dims[i].os = t->dims[i].os;
Chris@82 39 BENCH_ASSERT(bt->dims[i].n == t->dims[i].n);
Chris@82 40 BENCH_ASSERT(bt->dims[i].is == t->dims[i].is);
Chris@82 41 BENCH_ASSERT(bt->dims[i].os == t->dims[i].os);
Chris@82 42 }
Chris@82 43 }
Chris@82 44 return bt;
Chris@82 45 }
Chris@82 46
Chris@82 47 /*
Chris@82 48 transform an fftw problem into a bench_problem.
Chris@82 49 */
Chris@82 50 static bench_problem *fftw_problem_to_bench_problem(planner *plnr,
Chris@82 51 const problem *p_)
Chris@82 52 {
Chris@82 53 bench_problem *bp = 0;
Chris@82 54 switch (p_->adt->problem_kind) {
Chris@82 55 case PROBLEM_DFT:
Chris@82 56 {
Chris@82 57 const problem_dft *p = (const problem_dft *) p_;
Chris@82 58
Chris@82 59 if (!p->ri || !p->ii)
Chris@82 60 abort();
Chris@82 61
Chris@82 62 bp = (bench_problem *) bench_malloc(sizeof(bench_problem));
Chris@82 63
Chris@82 64 bp->kind = PROBLEM_COMPLEX;
Chris@82 65 bp->sign = FFT_SIGN;
Chris@82 66 bp->split = 1; /* tensor strides are in R's, not C's */
Chris@82 67 bp->in = UNTAINT(p->ri);
Chris@82 68 bp->out = UNTAINT(p->ro);
Chris@82 69 bp->ini = UNTAINT(p->ii);
Chris@82 70 bp->outi = UNTAINT(p->io);
Chris@82 71 bp->inphys = bp->outphys = 0;
Chris@82 72 bp->iphyssz = bp->ophyssz = 0;
Chris@82 73 bp->in_place = p->ri == p->ro;
Chris@82 74 bp->sz = fftw_tensor_to_bench_tensor(p->sz);
Chris@82 75 bp->vecsz = fftw_tensor_to_bench_tensor(p->vecsz);
Chris@82 76 bp->k = 0;
Chris@82 77 break;
Chris@82 78 }
Chris@82 79 case PROBLEM_RDFT:
Chris@82 80 {
Chris@82 81 const problem_rdft *p = (const problem_rdft *) p_;
Chris@82 82 int i;
Chris@82 83
Chris@82 84 if (!p->I || !p->O)
Chris@82 85 abort();
Chris@82 86
Chris@82 87 for (i = 0; i < p->sz->rnk; ++i)
Chris@82 88 switch (p->kind[i]) {
Chris@82 89 case R2HC01:
Chris@82 90 case R2HC10:
Chris@82 91 case R2HC11:
Chris@82 92 case HC2R01:
Chris@82 93 case HC2R10:
Chris@82 94 case HC2R11:
Chris@82 95 return bp;
Chris@82 96 default:
Chris@82 97 ;
Chris@82 98 }
Chris@82 99
Chris@82 100 bp = (bench_problem *) bench_malloc(sizeof(bench_problem));
Chris@82 101
Chris@82 102 bp->kind = PROBLEM_R2R;
Chris@82 103 bp->sign = FFT_SIGN;
Chris@82 104 bp->split = 0;
Chris@82 105 bp->in = UNTAINT(p->I);
Chris@82 106 bp->out = UNTAINT(p->O);
Chris@82 107 bp->ini = bp->outi = 0;
Chris@82 108 bp->inphys = bp->outphys = 0;
Chris@82 109 bp->iphyssz = bp->ophyssz = 0;
Chris@82 110 bp->in_place = p->I == p->O;
Chris@82 111 bp->sz = fftw_tensor_to_bench_tensor(p->sz);
Chris@82 112 bp->vecsz = fftw_tensor_to_bench_tensor(p->vecsz);
Chris@82 113 bp->k = (r2r_kind_t *) bench_malloc(sizeof(r2r_kind_t) * p->sz->rnk);
Chris@82 114 for (i = 0; i < p->sz->rnk; ++i)
Chris@82 115 switch (p->kind[i]) {
Chris@82 116 case R2HC: bp->k[i] = R2R_R2HC; break;
Chris@82 117 case HC2R: bp->k[i] = R2R_HC2R; break;
Chris@82 118 case DHT: bp->k[i] = R2R_DHT; break;
Chris@82 119 case REDFT00: bp->k[i] = R2R_REDFT00; break;
Chris@82 120 case REDFT01: bp->k[i] = R2R_REDFT01; break;
Chris@82 121 case REDFT10: bp->k[i] = R2R_REDFT10; break;
Chris@82 122 case REDFT11: bp->k[i] = R2R_REDFT11; break;
Chris@82 123 case RODFT00: bp->k[i] = R2R_RODFT00; break;
Chris@82 124 case RODFT01: bp->k[i] = R2R_RODFT01; break;
Chris@82 125 case RODFT10: bp->k[i] = R2R_RODFT10; break;
Chris@82 126 case RODFT11: bp->k[i] = R2R_RODFT11; break;
Chris@82 127 default: CK(0);
Chris@82 128 }
Chris@82 129 break;
Chris@82 130 }
Chris@82 131 case PROBLEM_RDFT2:
Chris@82 132 {
Chris@82 133 const problem_rdft2 *p = (const problem_rdft2 *) p_;
Chris@82 134 int rnk = p->sz->rnk;
Chris@82 135
Chris@82 136 if (!p->r0 || !p->r1 || !p->cr || !p->ci)
Chris@82 137 abort();
Chris@82 138
Chris@82 139 /* give up verifying rdft2 R2HCII */
Chris@82 140 if (p->kind != R2HC && p->kind != HC2R)
Chris@82 141 return bp;
Chris@82 142
Chris@82 143 if (rnk > 0) {
Chris@82 144 /* can't verify separate even/odd arrays for now */
Chris@82 145 if (2 * (p->r1 - p->r0) !=
Chris@82 146 ((p->kind == R2HC) ?
Chris@82 147 p->sz->dims[rnk-1].is : p->sz->dims[rnk-1].os))
Chris@82 148 return bp;
Chris@82 149 }
Chris@82 150
Chris@82 151 bp = (bench_problem *) bench_malloc(sizeof(bench_problem));
Chris@82 152
Chris@82 153 bp->kind = PROBLEM_REAL;
Chris@82 154 bp->sign = p->kind == R2HC ? FFT_SIGN : -FFT_SIGN;
Chris@82 155 bp->split = 1; /* tensor strides are in R's, not C's */
Chris@82 156 if (p->kind == R2HC) {
Chris@82 157 bp->sign = FFT_SIGN;
Chris@82 158 bp->in = UNTAINT(p->r0);
Chris@82 159 bp->out = UNTAINT(p->cr);
Chris@82 160 bp->ini = 0;
Chris@82 161 bp->outi = UNTAINT(p->ci);
Chris@82 162 }
Chris@82 163 else {
Chris@82 164 bp->sign = -FFT_SIGN;
Chris@82 165 bp->out = UNTAINT(p->r0);
Chris@82 166 bp->in = UNTAINT(p->cr);
Chris@82 167 bp->outi = 0;
Chris@82 168 bp->ini = UNTAINT(p->ci);
Chris@82 169 }
Chris@82 170 bp->inphys = bp->outphys = 0;
Chris@82 171 bp->iphyssz = bp->ophyssz = 0;
Chris@82 172 bp->in_place = p->r0 == p->cr;
Chris@82 173 bp->sz = fftw_tensor_to_bench_tensor(p->sz);
Chris@82 174 if (rnk > 0) {
Chris@82 175 if (p->kind == R2HC)
Chris@82 176 bp->sz->dims[rnk-1].is /= 2;
Chris@82 177 else
Chris@82 178 bp->sz->dims[rnk-1].os /= 2;
Chris@82 179 }
Chris@82 180 bp->vecsz = fftw_tensor_to_bench_tensor(p->vecsz);
Chris@82 181 bp->k = 0;
Chris@82 182 break;
Chris@82 183 }
Chris@82 184 default:
Chris@82 185 abort();
Chris@82 186 }
Chris@82 187
Chris@82 188 bp->userinfo = 0;
Chris@82 189 bp->pstring = 0;
Chris@82 190 bp->destroy_input = !NO_DESTROY_INPUTP(plnr);
Chris@82 191
Chris@82 192 return bp;
Chris@82 193 }
Chris@82 194
Chris@82 195 static void hook(planner *plnr, plan *pln, const problem *p_, int optimalp)
Chris@82 196 {
Chris@82 197 int rounds = 5;
Chris@82 198 double tol = SINGLE_PRECISION ? 1.0e-3 : 1.0e-10;
Chris@82 199 UNUSED(optimalp);
Chris@82 200
Chris@82 201 if (verbose > 5) {
Chris@82 202 printer *pr = X(mkprinter_file)(stdout);
Chris@82 203 pr->print(pr, "%P:%(%p%)\n", p_, pln);
Chris@82 204 X(printer_destroy)(pr);
Chris@82 205 printf("cost %g \n\n", pln->pcost);
Chris@82 206 }
Chris@82 207
Chris@82 208 if (paranoid) {
Chris@82 209 bench_problem *bp;
Chris@82 210
Chris@82 211 bp = fftw_problem_to_bench_problem(plnr, p_);
Chris@82 212 if (bp) {
Chris@82 213 X(plan) the_plan_save = the_plan;
Chris@82 214
Chris@82 215 the_plan = (apiplan *) MALLOC(sizeof(apiplan), PLANS);
Chris@82 216 the_plan->pln = pln;
Chris@82 217 the_plan->prb = (problem *) p_;
Chris@82 218
Chris@82 219 X(plan_awake)(pln, AWAKE_SQRTN_TABLE);
Chris@82 220 verify_problem(bp, rounds, tol);
Chris@82 221 X(plan_awake)(pln, SLEEPY);
Chris@82 222
Chris@82 223 X(ifree)(the_plan);
Chris@82 224 the_plan = the_plan_save;
Chris@82 225
Chris@82 226 problem_destroy(bp);
Chris@82 227 }
Chris@82 228
Chris@82 229 }
Chris@82 230 }
Chris@82 231
Chris@82 232 static void paranoid_checks(void)
Chris@82 233 {
Chris@82 234 /* FIXME: assumes char = 8 bits, which is false on at least one
Chris@82 235 DSP I know of. */
Chris@82 236 #if 0
Chris@82 237 /* if flags_t is not 64 bits i want to know it. */
Chris@82 238 CK(sizeof(flags_t) == 8);
Chris@82 239
Chris@82 240 CK(sizeof(md5uint) >= 4);
Chris@82 241 #endif
Chris@82 242
Chris@82 243 CK(sizeof(uintptr_t) >= sizeof(R *));
Chris@82 244
Chris@82 245 CK(sizeof(INT) >= sizeof(R *));
Chris@82 246 }
Chris@82 247
Chris@82 248 void install_hook(void)
Chris@82 249 {
Chris@82 250 planner *plnr = X(the_planner)();
Chris@82 251 plnr->hook = hook;
Chris@82 252 paranoid_checks();
Chris@82 253 }
Chris@82 254
Chris@82 255 void uninstall_hook(void)
Chris@82 256 {
Chris@82 257 planner *plnr = X(the_planner)();
Chris@82 258 plnr->hook = 0;
Chris@82 259 }