Merge branch 'master' of ssh://git.freedesktop.org/git/mesa/mesa into pipe-video
[mesa.git] / src / gallium / drivers / llvmpipe / lp_test_main.c
1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28
29 /**
30 * @file
31 * Shared testing code.
32 *
33 * @author Jose Fonseca <jfonseca@vmware.com>
34 */
35
36
37 #include "util/u_cpu_detect.h"
38
39 #include "gallivm/lp_bld_const.h"
40 #include "gallivm/lp_bld_init.h"
41 #include "lp_test.h"
42
43
44 #ifdef PIPE_CC_MSVC
45 static INLINE double
46 round(double x)
47 {
48 if (x >= 0.0)
49 return floor(x + 0.5);
50 else
51 return ceil(x - 0.5);
52 }
53 #endif
54
55
56 void
57 dump_type(FILE *fp,
58 struct lp_type type)
59 {
60 fprintf(fp, "%s%s%u%sx%u",
61 type.sign ? (type.floating || type.fixed ? "" : "s") : "u",
62 type.floating ? "f" : (type.fixed ? "h" : "i"),
63 type.width,
64 type.norm ? "n" : "",
65 type.length);
66 }
67
68
69 double
70 read_elem(struct lp_type type, const void *src, unsigned index)
71 {
72 double scale = lp_const_scale(type);
73 double value;
74 assert(index < type.length);
75 if (type.floating) {
76 switch(type.width) {
77 case 32:
78 value = *((const float *)src + index);
79 break;
80 case 64:
81 value = *((const double *)src + index);
82 break;
83 default:
84 assert(0);
85 return 0.0;
86 }
87 }
88 else {
89 if(type.sign) {
90 switch(type.width) {
91 case 8:
92 value = *((const int8_t *)src + index);
93 break;
94 case 16:
95 value = *((const int16_t *)src + index);
96 break;
97 case 32:
98 value = *((const int32_t *)src + index);
99 break;
100 case 64:
101 value = *((const int64_t *)src + index);
102 break;
103 default:
104 assert(0);
105 return 0.0;
106 }
107 }
108 else {
109 switch(type.width) {
110 case 8:
111 value = *((const uint8_t *)src + index);
112 break;
113 case 16:
114 value = *((const uint16_t *)src + index);
115 break;
116 case 32:
117 value = *((const uint32_t *)src + index);
118 break;
119 case 64:
120 value = *((const uint64_t *)src + index);
121 break;
122 default:
123 assert(0);
124 return 0.0;
125 }
126 }
127 }
128 return value/scale;
129 }
130
131
132 void
133 write_elem(struct lp_type type, void *dst, unsigned index, double value)
134 {
135 assert(index < type.length);
136 if(!type.sign && value < 0.0)
137 value = 0.0;
138 if(type.norm && value < -1.0)
139 value = -1.0;
140 if(type.norm && value > 1.0)
141 value = 1.0;
142 if (type.floating) {
143 switch(type.width) {
144 case 32:
145 *((float *)dst + index) = (float)(value);
146 break;
147 case 64:
148 *((double *)dst + index) = value;
149 break;
150 default:
151 assert(0);
152 }
153 }
154 else {
155 double scale = lp_const_scale(type);
156 value = round(value*scale);
157 if(type.sign) {
158 long long lvalue = (long long)value;
159 lvalue = MIN2(lvalue, ((long long)1 << (type.width - 1)) - 1);
160 switch(type.width) {
161 case 8:
162 *((int8_t *)dst + index) = (int8_t)lvalue;
163 break;
164 case 16:
165 *((int16_t *)dst + index) = (int16_t)lvalue;
166 break;
167 case 32:
168 *((int32_t *)dst + index) = (int32_t)lvalue;
169 break;
170 case 64:
171 *((int64_t *)dst + index) = (int64_t)lvalue;
172 break;
173 default:
174 assert(0);
175 }
176 }
177 else {
178 unsigned long long lvalue = (long long)value;
179 lvalue = MIN2(lvalue, ((unsigned long long)1 << type.width) - 1);
180 switch(type.width) {
181 case 8:
182 *((uint8_t *)dst + index) = (uint8_t)lvalue;
183 break;
184 case 16:
185 *((uint16_t *)dst + index) = (uint16_t)lvalue;
186 break;
187 case 32:
188 *((uint32_t *)dst + index) = (uint32_t)lvalue;
189 break;
190 case 64:
191 *((uint64_t *)dst + index) = (uint64_t)lvalue;
192 break;
193 default:
194 assert(0);
195 }
196 }
197 }
198 }
199
200
201 void
202 random_elem(struct lp_type type, void *dst, unsigned index)
203 {
204 double value;
205 assert(index < type.length);
206 value = (double)rand()/(double)RAND_MAX;
207 if(!type.norm) {
208 if (type.floating) {
209 value *= 2.0;
210 }
211 else {
212 unsigned long long mask;
213 if (type.fixed)
214 mask = ((unsigned long long)1 << (type.width / 2)) - 1;
215 else if (type.sign)
216 mask = ((unsigned long long)1 << (type.width - 1)) - 1;
217 else
218 mask = ((unsigned long long)1 << type.width) - 1;
219 value += (double)(mask & rand());
220 }
221 }
222 if(!type.sign)
223 if(rand() & 1)
224 value = -value;
225 write_elem(type, dst, index, value);
226 }
227
228
229 void
230 read_vec(struct lp_type type, const void *src, double *dst)
231 {
232 unsigned i;
233 for (i = 0; i < type.length; ++i)
234 dst[i] = read_elem(type, src, i);
235 }
236
237
238 void
239 write_vec(struct lp_type type, void *dst, const double *src)
240 {
241 unsigned i;
242 for (i = 0; i < type.length; ++i)
243 write_elem(type, dst, i, src[i]);
244 }
245
246
247 float
248 random_float(void)
249 {
250 return (float)((double)rand()/(double)RAND_MAX);
251 }
252
253
254 void
255 random_vec(struct lp_type type, void *dst)
256 {
257 unsigned i;
258 for (i = 0; i < type.length; ++i)
259 random_elem(type, dst, i);
260 }
261
262
263 boolean
264 compare_vec_with_eps(struct lp_type type, const void *res, const void *ref, double eps)
265 {
266 unsigned i;
267 eps *= type.floating ? 8.0 : 2.0;
268 for (i = 0; i < type.length; ++i) {
269 double res_elem = read_elem(type, res, i);
270 double ref_elem = read_elem(type, ref, i);
271 double delta = res_elem - ref_elem;
272 if (ref_elem < -1.0 || ref_elem > 1.0) {
273 delta /= ref_elem;
274 }
275 delta = fabs(delta);
276 if (delta >= eps) {
277 return FALSE;
278 }
279 }
280
281 return TRUE;
282 }
283
284
285 boolean
286 compare_vec(struct lp_type type, const void *res, const void *ref)
287 {
288 double eps = lp_const_eps(type);
289 return compare_vec_with_eps(type, res, ref, eps);
290 }
291
292
293 void
294 dump_vec(FILE *fp, struct lp_type type, const void *src)
295 {
296 unsigned i;
297 for (i = 0; i < type.length; ++i) {
298 if(i)
299 fprintf(fp, " ");
300 if (type.floating) {
301 double value;
302 switch(type.width) {
303 case 32:
304 value = *((const float *)src + i);
305 break;
306 case 64:
307 value = *((const double *)src + i);
308 break;
309 default:
310 assert(0);
311 value = 0.0;
312 }
313 fprintf(fp, "%f", value);
314 }
315 else {
316 if(type.sign && !type.norm) {
317 long long value;
318 const char *format;
319 switch(type.width) {
320 case 8:
321 value = *((const int8_t *)src + i);
322 format = "%3lli";
323 break;
324 case 16:
325 value = *((const int16_t *)src + i);
326 format = "%5lli";
327 break;
328 case 32:
329 value = *((const int32_t *)src + i);
330 format = "%10lli";
331 break;
332 case 64:
333 value = *((const int64_t *)src + i);
334 format = "%20lli";
335 break;
336 default:
337 assert(0);
338 value = 0.0;
339 format = "?";
340 }
341 fprintf(fp, format, value);
342 }
343 else {
344 unsigned long long value;
345 const char *format;
346 switch(type.width) {
347 case 8:
348 value = *((const uint8_t *)src + i);
349 format = type.norm ? "%2x" : "%4llu";
350 break;
351 case 16:
352 value = *((const uint16_t *)src + i);
353 format = type.norm ? "%4x" : "%6llx";
354 break;
355 case 32:
356 value = *((const uint32_t *)src + i);
357 format = type.norm ? "%8x" : "%11llx";
358 break;
359 case 64:
360 value = *((const uint64_t *)src + i);
361 format = type.norm ? "%16x" : "%21llx";
362 break;
363 default:
364 assert(0);
365 value = 0.0;
366 format = "?";
367 }
368 fprintf(fp, format, value);
369 }
370 }
371 }
372 }
373
374
375 int main(int argc, char **argv)
376 {
377 unsigned verbose = 0;
378 FILE *fp = NULL;
379 unsigned long n = 1000;
380 unsigned i;
381 boolean success;
382 boolean single = FALSE;
383
384 for(i = 1; i < argc; ++i) {
385 if(strcmp(argv[i], "-v") == 0)
386 ++verbose;
387 else if(strcmp(argv[i], "-s") == 0)
388 single = TRUE;
389 else if(strcmp(argv[i], "-o") == 0)
390 fp = fopen(argv[++i], "wt");
391 else
392 n = atoi(argv[i]);
393 }
394
395 lp_build_init();
396
397 util_cpu_detect();
398
399 if(fp) {
400 /* Warm up the caches */
401 test_some(0, NULL, 100);
402
403 write_tsv_header(fp);
404 }
405
406 if (single)
407 success = test_single(verbose, fp);
408 else if (n)
409 success = test_some(verbose, fp, n);
410 else
411 success = test_all(verbose, fp);
412
413 if(fp)
414 fclose(fp);
415
416 return success ? 0 : 1;
417 }