1 /*
2  * Copyright (c) 2001 Matteo Frigo
3  * Copyright (c) 2001 Massachusetts Institute of Technology
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  *
19  */
20 
21 #ifndef __BENCH_USER_H__
22 #define __BENCH_USER_H__
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif                          /* __cplusplus */
27 
28 /* benchmark program definitions for user code */
29 #include "config.h"
30 #include <limits.h>
31 
32 #if HAVE_STDDEF_H
33 #include <stddef.h>
34 #endif
35 
36 #if HAVE_STDLIB_H
37 #include <stdlib.h>
38 #endif
39 
40 #if defined(BENCHFFT_SINGLE)
41 typedef float bench_real;
42 #elif defined(BENCHFFT_LDOUBLE)
43 typedef long double bench_real;
44 #elif defined(BENCHFFT_QUAD)
45 typedef __float128 bench_real;
46 #else
47 typedef double bench_real;
48 #endif
49 
50 typedef bench_real bench_complex[2];
51 
52 #define c_re(c)  ((c)[0])
53 #define c_im(c)  ((c)[1])
54 
55 #undef DOUBLE_PRECISION
56 #define DOUBLE_PRECISION (sizeof(bench_real) == sizeof(double))
57 #undef SINGLE_PRECISION
58 #define SINGLE_PRECISION (!DOUBLE_PRECISION && sizeof(bench_real) == sizeof(float))
59 #undef LDOUBLE_PRECISION
60 #define LDOUBLE_PRECISION (!DOUBLE_PRECISION && sizeof(bench_real) == sizeof(long double))
61 
62 #undef QUAD_PRECISION
63 #ifdef BENCHFFT_QUAD
64 #define QUAD_PRECISION (!LDOUBLE_PRECISION && sizeof(bench_real) == sizeof(__float128))
65 #else
66 #define QUAD_PRECISION 0
67 #endif
68 
69 typedef enum { PROBLEM_COMPLEX, PROBLEM_REAL, PROBLEM_R2R } problem_kind_t;
70 
71 typedef enum {
72      R2R_R2HC, R2R_HC2R, R2R_DHT,
73      R2R_REDFT00, R2R_REDFT01, R2R_REDFT10, R2R_REDFT11,
74      R2R_RODFT00, R2R_RODFT01, R2R_RODFT10, R2R_RODFT11
75 } r2r_kind_t;
76 
77 typedef struct {
78      int n;
79      int is;			/* input stride */
80      int os;			/* output stride */
81 } bench_iodim;
82 
83 typedef struct {
84      int rnk;
85      bench_iodim *dims;
86 } bench_tensor;
87 
88 bench_tensor *mktensor(int rnk);
89 void tensor_destroy(bench_tensor *sz);
90 size_t tensor_sz(const bench_tensor *sz);
91 bench_tensor *tensor_compress(const bench_tensor *sz);
92 int tensor_unitstridep(bench_tensor *t);
93 int tensor_rowmajorp(bench_tensor *t);
94 int tensor_real_rowmajorp(bench_tensor *t, int sign, int in_place);
95 bench_tensor *tensor_append(const bench_tensor *a, const bench_tensor *b);
96 bench_tensor *tensor_copy(const bench_tensor *sz);
97 bench_tensor *tensor_copy_sub(const bench_tensor *sz, int start_dim, int rnk);
98 bench_tensor *tensor_copy_swapio(const bench_tensor *sz);
99 void tensor_ibounds(bench_tensor *t, int *lbp, int *ubp);
100 void tensor_obounds(bench_tensor *t, int *lbp, int *ubp);
101 
102 /*
103   Definition of rank -infinity.
104   This definition has the property that if you want rank 0 or 1,
105   you can simply test for rank <= 1.  This is a common case.
106 
107   A tensor of rank -infinity has size 0.
108 */
109 #define BENCH_RNK_MINFTY  INT_MAX
110 #define BENCH_FINITE_RNK(rnk) ((rnk) != BENCH_RNK_MINFTY)
111 
112 typedef struct {
113      problem_kind_t kind;
114      r2r_kind_t *k;
115      bench_tensor *sz;
116      bench_tensor *vecsz;
117      int sign;
118      int in_place;
119      int destroy_input;
120      int split;
121      void *in, *out;
122      void *inphys, *outphys;
123      int iphyssz, ophyssz;
124      char *pstring;
125      void *userinfo; /* user can store whatever */
126      int scrambled_in, scrambled_out; /* hack for MPI */
127 
128      /* internal hack so that we can use verifier in FFTW test program */
129      void *ini, *outi; /* if nonzero, point to imag. parts for dft */
130 
131      /* another internal hack to avoid passing around too many parameters */
132      double setup_time;
133 } bench_problem;
134 
135 extern int verbose;
136 
137 extern int no_speed_allocation;
138 
139 extern int always_pad_real;
140 
141 #define LIBBENCH_TIMER 0
142 #define USER_TIMER 1
143 #define BENCH_NTIMERS 2
144 extern void timer_start(int which_timer);
145 extern double timer_stop(int which_timer);
146 
147 extern int can_do(bench_problem *p);
148 extern void setup(bench_problem *p);
149 extern void doit(int iter, bench_problem *p);
150 extern void done(bench_problem *p);
151 extern void main_init(int *argc, char ***argv);
152 extern void cleanup(void);
153 extern void verify(const char *param, int rounds, double tol);
154 extern void useropt(const char *arg);
155 
156 extern void verify_problem(bench_problem *p, int rounds, double tol);
157 
158 extern void problem_alloc(bench_problem *p);
159 extern void problem_free(bench_problem *p);
160 extern void problem_zero(bench_problem *p);
161 extern void problem_destroy(bench_problem *p);
162 
163 extern int power_of_two(int n);
164 extern int log_2(int n);
165 
166 
167 #define CASSIGN(out, in) (c_re(out) = c_re(in), c_im(out) = c_im(in))
168 
169 bench_tensor *verify_pack(const bench_tensor *sz, int s);
170 
171 typedef struct {
172      double l;
173      double i;
174      double s;
175 } errors;
176 
177 void verify_dft(bench_problem *p, int rounds, double tol, errors *e);
178 void verify_rdft2(bench_problem *p, int rounds, double tol, errors *e);
179 void verify_r2r(bench_problem *p, int rounds, double tol, errors *e);
180 
181 /**************************************************************/
182 /* routines to override */
183 
184 extern void after_problem_ccopy_from(bench_problem *p, bench_real *ri, bench_real *ii);
185 extern void after_problem_ccopy_to(bench_problem *p, bench_real *ro, bench_real *io);
186 extern void after_problem_hccopy_from(bench_problem *p, bench_real *ri, bench_real *ii);
187 extern void after_problem_hccopy_to(bench_problem *p, bench_real *ro, bench_real *io);
188 extern void after_problem_rcopy_from(bench_problem *p, bench_real *ri);
189 extern void after_problem_rcopy_to(bench_problem *p, bench_real *ro);
190 extern void bench_exit(int status);
191 extern double bench_cost_postprocess(double cost);
192 
193 /**************************************************************
194  * malloc
195  **************************************************************/
196 extern void *bench_malloc(size_t size);
197 extern void bench_free(void *ptr);
198 extern void bench_free0(void *ptr);
199 
200 /**************************************************************
201  * alloca
202  **************************************************************/
203 #ifdef HAVE_ALLOCA_H
204 #include <alloca.h>
205 #endif
206 
207 /**************************************************************
208  * assert
209  **************************************************************/
210 extern void bench_assertion_failed(const char *s, int line, const char *file);
211 #define BENCH_ASSERT(ex)						 \
212       (void)((ex) || (bench_assertion_failed(#ex, __LINE__, __FILE__), 0))
213 
214 #define UNUSED(x) (void)x
215 
216 /***************************************
217  * Documentation strings
218  ***************************************/
219 struct bench_doc {
220      const char *key;
221      const char *val;
222      const char *(*f)(void);
223 };
224 
225 extern struct bench_doc bench_doc[];
226 
227 #ifdef CC
228 #define CC_DOC BENCH_DOC("cc", CC)
229 #elif defined(BENCH_CC)
230 #define CC_DOC BENCH_DOC("cc", BENCH_CC)
231 #else
232 #define CC_DOC /* none */
233 #endif
234 
235 #ifdef CXX
236 #define CXX_DOC BENCH_DOC("cxx", CXX)
237 #elif defined(BENCH_CXX)
238 #define CXX_DOC BENCH_DOC("cxx", BENCH_CXX)
239 #else
240 #define CXX_DOC /* none */
241 #endif
242 
243 #ifdef F77
244 #define F77_DOC BENCH_DOC("f77", F77)
245 #elif defined(BENCH_F77)
246 #define F77_DOC BENCH_DOC("f77", BENCH_F77)
247 #else
248 #define F77_DOC /* none */
249 #endif
250 
251 #ifdef F90
252 #define F90_DOC BENCH_DOC("f90", F90)
253 #elif defined(BENCH_F90)
254 #define F90_DOC BENCH_DOC("f90", BENCH_F90)
255 #else
256 #define F90_DOC /* none */
257 #endif
258 
259 #define BEGIN_BENCH_DOC						\
260 struct bench_doc bench_doc[] = {				\
261     CC_DOC							\
262     CXX_DOC							\
263     F77_DOC							\
264     F90_DOC
265 
266 #define BENCH_DOC(key, val) { key, val, 0 },
267 #define BENCH_DOCF(key, f) { key, 0, f },
268 
269 #define END_BENCH_DOC				\
270      {0, 0, 0}};
271 
272 #ifdef __cplusplus
273 }                               /* extern "C" */
274 #endif                          /* __cplusplus */
275 
276 #endif /* __BENCH_USER_H__ */
277