Mercurial > hg > sv-dependency-builds
diff src/fftw-3.3.3/libbench2/problem.c @ 10:37bf6b4a2645
Add FFTW3
author | Chris Cannam |
---|---|
date | Wed, 20 Mar 2013 15:35:50 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/fftw-3.3.3/libbench2/problem.c Wed Mar 20 15:35:50 2013 +0000 @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2001 Matteo Frigo + * Copyright (c) 2001 Massachusetts Institute of Technology + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +#include "config.h" +#include "bench.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +int always_pad_real = 0; /* by default, only pad in-place case */ + +typedef enum { + SAME, PADDED, HALFISH +} n_transform; + +/* funny transformations for last dimension of PROBLEM_REAL */ +static int transform_n(int n, n_transform nt) +{ + switch (nt) { + case SAME: return n; + case PADDED: return 2*(n/2+1); + case HALFISH: return (n/2+1); + default: BENCH_ASSERT(0); return 0; + } +} + +/* do what I mean */ +static bench_tensor *dwim(bench_tensor *t, bench_iodim **last_iodim, + n_transform nti, n_transform nto, + bench_iodim *dt) +{ + int i; + bench_iodim *d, *d1; + + if (!FINITE_RNK(t->rnk) || t->rnk < 1) + return t; + + i = t->rnk; + d1 = *last_iodim; + + while (--i >= 0) { + d = t->dims + i; + if (!d->is) + d->is = d1->is * transform_n(d1->n, d1==dt ? nti : SAME); + if (!d->os) + d->os = d1->os * transform_n(d1->n, d1==dt ? nto : SAME); + d1 = d; + } + + *last_iodim = d1; + return t; +} + +static void transpose_tensor(bench_tensor *t) +{ + if (!FINITE_RNK(t->rnk) || t->rnk < 2) + return; + + t->dims[0].os = t->dims[1].os; + t->dims[1].os = t->dims[0].os * t->dims[0].n; +} + +static const char *parseint(const char *s, int *n) +{ + int sign = 1; + + *n = 0; + + if (*s == '-') { + sign = -1; + ++s; + } else if (*s == '+') { + sign = +1; + ++s; + } + + BENCH_ASSERT(isdigit(*s)); + while (isdigit(*s)) { + *n = *n * 10 + (*s - '0'); + ++s; + } + + *n *= sign; + + if (*s == 'k' || *s == 'K') { + *n *= 1024; + ++s; + } + + if (*s == 'm' || *s == 'M') { + *n *= 1024 * 1024; + ++s; + } + + return s; +} + +struct dimlist { bench_iodim car; r2r_kind_t k; struct dimlist *cdr; }; + +static const char *parsetensor(const char *s, bench_tensor **tp, + r2r_kind_t **k) +{ + struct dimlist *l = 0, *m; + bench_tensor *t; + int rnk = 0; + + L1: + m = (struct dimlist *)bench_malloc(sizeof(struct dimlist)); + /* nconc onto l */ + m->cdr = l; l = m; + ++rnk; + + s = parseint(s, &m->car.n); + + if (*s == ':') { + /* read input stride */ + ++s; + s = parseint(s, &m->car.is); + if (*s == ':') { + /* read output stride */ + ++s; + s = parseint(s, &m->car.os); + } else { + /* default */ + m->car.os = m->car.is; + } + } else { + m->car.is = 0; + m->car.os = 0; + } + + if (*s == 'f' || *s == 'F') { + m->k = R2R_R2HC; + ++s; + } + else if (*s == 'b' || *s == 'B') { + m->k = R2R_HC2R; + ++s; + } + else if (*s == 'h' || *s == 'H') { + m->k = R2R_DHT; + ++s; + } + else if (*s == 'e' || *s == 'E' || *s == 'o' || *s == 'O') { + char c = *(s++); + int ab; + + s = parseint(s, &ab); + + if (c == 'e' || c == 'E') { + if (ab == 0) + m->k = R2R_REDFT00; + else if (ab == 1) + m->k = R2R_REDFT01; + else if (ab == 10) + m->k = R2R_REDFT10; + else if (ab == 11) + m->k = R2R_REDFT11; + else + BENCH_ASSERT(0); + } + else { + if (ab == 0) + m->k = R2R_RODFT00; + else if (ab == 1) + m->k = R2R_RODFT01; + else if (ab == 10) + m->k = R2R_RODFT10; + else if (ab == 11) + m->k = R2R_RODFT11; + else + BENCH_ASSERT(0); + } + } + else + m->k = R2R_R2HC; + + if (*s == 'x' || *s == 'X') { + ++s; + goto L1; + } + + /* now we have a dimlist. Build bench_tensor, etc. */ + + if (k && rnk > 0) { + int i; + *k = (r2r_kind_t *) bench_malloc(sizeof(r2r_kind_t) * rnk); + for (m = l, i = rnk - 1; i >= 0; --i, m = m->cdr) { + BENCH_ASSERT(m); + (*k)[i] = m->k; + } + } + + t = mktensor(rnk); + while (--rnk >= 0) { + bench_iodim *d = t->dims + rnk; + BENCH_ASSERT(l); + m = l; l = m->cdr; + d->n = m->car.n; + d->is = m->car.is; + d->os = m->car.os; + bench_free(m); + } + + *tp = t; + return s; +} + +/* parse a problem description, return a problem */ +bench_problem *problem_parse(const char *s) +{ + bench_problem *p; + bench_iodim last_iodim0 = {1,1,1}, *last_iodim = &last_iodim0; + bench_iodim *sz_last_iodim; + bench_tensor *sz; + n_transform nti = SAME, nto = SAME; + int transpose = 0; + + p = (bench_problem *) bench_malloc(sizeof(bench_problem)); + p->kind = PROBLEM_COMPLEX; + p->k = 0; + p->sign = -1; + p->in = p->out = 0; + p->inphys = p->outphys = 0; + p->iphyssz = p->ophyssz = 0; + p->in_place = 0; + p->destroy_input = 0; + p->split = 0; + p->userinfo = 0; + p->scrambled_in = p->scrambled_out = 0; + p->sz = p->vecsz = 0; + p->ini = p->outi = 0; + p->pstring = (char *) bench_malloc(sizeof(char) * (strlen(s) + 1)); + strcpy(p->pstring, s); + + L1: + switch (tolower(*s)) { + case 'i': p->in_place = 1; ++s; goto L1; + case 'o': p->in_place = 0; ++s; goto L1; + case 'd': p->destroy_input = 1; ++s; goto L1; + case '/': p->split = 1; ++s; goto L1; + case 'f': + case '-': p->sign = -1; ++s; goto L1; + case 'b': + case '+': p->sign = 1; ++s; goto L1; + case 'r': p->kind = PROBLEM_REAL; ++s; goto L1; + case 'c': p->kind = PROBLEM_COMPLEX; ++s; goto L1; + case 'k': p->kind = PROBLEM_R2R; ++s; goto L1; + case 't': transpose = 1; ++s; goto L1; + + /* hack for MPI: */ + case '[': p->scrambled_in = 1; ++s; goto L1; + case ']': p->scrambled_out = 1; ++s; goto L1; + + default : ; + } + + s = parsetensor(s, &sz, p->kind == PROBLEM_R2R ? &p->k : 0); + + if (p->kind == PROBLEM_REAL) { + if (p->sign < 0) { + nti = p->in_place || always_pad_real ? PADDED : SAME; + nto = HALFISH; + } + else { + nti = HALFISH; + nto = p->in_place || always_pad_real ? PADDED : SAME; + } + } + + sz_last_iodim = sz->dims + sz->rnk - 1; + if (*s == '*') { /* "external" vector */ + ++s; + p->sz = dwim(sz, &last_iodim, nti, nto, sz_last_iodim); + s = parsetensor(s, &sz, 0); + p->vecsz = dwim(sz, &last_iodim, nti, nto, sz_last_iodim); + } else if (*s == 'v' || *s == 'V') { /* "internal" vector */ + bench_tensor *vecsz; + ++s; + s = parsetensor(s, &vecsz, 0); + p->vecsz = dwim(vecsz, &last_iodim, nti, nto, sz_last_iodim); + p->sz = dwim(sz, &last_iodim, nti, nto, sz_last_iodim); + } else { + p->sz = dwim(sz, &last_iodim, nti, nto, sz_last_iodim); + p->vecsz = mktensor(0); + } + + if (transpose) { + transpose_tensor(p->sz); + transpose_tensor(p->vecsz); + } + + if (!p->in_place) + p->out = ((bench_real *) p->in) + (1 << 20); /* whatever */ + + BENCH_ASSERT(p->sz && p->vecsz); + BENCH_ASSERT(!*s); + return p; +} + +void problem_destroy(bench_problem *p) +{ + BENCH_ASSERT(p); + problem_free(p); + bench_free0(p->k); + bench_free0(p->pstring); + bench_free(p); +} +