Merge branch 'mesa_7_6_branch'
[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 "lp_bld_const.h"
40 #include "lp_test.h"
41
42
43 void
44 dump_type(FILE *fp,
45 struct lp_type type)
46 {
47 fprintf(fp, "%s%s%u%sx%u",
48 type.sign ? (type.floating || type.fixed ? "" : "s") : "u",
49 type.floating ? "f" : (type.fixed ? "h" : "i"),
50 type.width,
51 type.norm ? "n" : "",
52 type.length);
53 }
54
55
56 double
57 read_elem(struct lp_type type, const void *src, unsigned index)
58 {
59 double scale = lp_const_scale(type);
60 double value;
61 assert(index < type.length);
62 if (type.floating) {
63 switch(type.width) {
64 case 32:
65 value = *((const float *)src + index);
66 break;
67 case 64:
68 value = *((const double *)src + index);
69 break;
70 default:
71 assert(0);
72 return 0.0;
73 }
74 }
75 else {
76 if(type.sign) {
77 switch(type.width) {
78 case 8:
79 value = *((const int8_t *)src + index);
80 break;
81 case 16:
82 value = *((const int16_t *)src + index);
83 break;
84 case 32:
85 value = *((const int32_t *)src + index);
86 break;
87 case 64:
88 value = *((const int64_t *)src + index);
89 break;
90 default:
91 assert(0);
92 return 0.0;
93 }
94 }
95 else {
96 switch(type.width) {
97 case 8:
98 value = *((const uint8_t *)src + index);
99 break;
100 case 16:
101 value = *((const uint16_t *)src + index);
102 break;
103 case 32:
104 value = *((const uint32_t *)src + index);
105 break;
106 case 64:
107 value = *((const uint64_t *)src + index);
108 break;
109 default:
110 assert(0);
111 return 0.0;
112 }
113 }
114 }
115 return value/scale;
116 }
117
118
119 void
120 write_elem(struct lp_type type, void *dst, unsigned index, double value)
121 {
122 assert(index < type.length);
123 if(!type.sign && value < 0.0)
124 value = 0.0;
125 if(type.norm && value < -1.0)
126 value = -1.0;
127 if(type.norm && value > 1.0)
128 value = 1.0;
129 if (type.floating) {
130 switch(type.width) {
131 case 32:
132 *((float *)dst + index) = (float)(value);
133 break;
134 case 64:
135 *((double *)dst + index) = value;
136 break;
137 default:
138 assert(0);
139 }
140 }
141 else {
142 double scale = lp_const_scale(type);
143 value = round(value*scale);
144 if(type.sign) {
145 long long lvalue = (long long)value;
146 lvalue = MIN2(lvalue, ((long long)1 << (type.width - 1)) - 1);
147 switch(type.width) {
148 case 8:
149 *((int8_t *)dst + index) = (int8_t)lvalue;
150 break;
151 case 16:
152 *((int16_t *)dst + index) = (int16_t)lvalue;
153 break;
154 case 32:
155 *((int32_t *)dst + index) = (int32_t)lvalue;
156 break;
157 case 64:
158 *((int64_t *)dst + index) = (int64_t)lvalue;
159 break;
160 default:
161 assert(0);
162 }
163 }
164 else {
165 unsigned long long lvalue = (long long)value;
166 lvalue = MIN2(lvalue, ((unsigned long long)1 << type.width) - 1);
167 switch(type.width) {
168 case 8:
169 *((uint8_t *)dst + index) = (uint8_t)lvalue;
170 break;
171 case 16:
172 *((uint16_t *)dst + index) = (uint16_t)lvalue;
173 break;
174 case 32:
175 *((uint32_t *)dst + index) = (uint32_t)lvalue;
176 break;
177 case 64:
178 *((uint64_t *)dst + index) = (uint64_t)lvalue;
179 break;
180 default:
181 assert(0);
182 }
183 }
184 }
185 }
186
187
188 void
189 random_elem(struct lp_type type, void *dst, unsigned index)
190 {
191 double value;
192 assert(index < type.length);
193 value = (double)rand()/(double)RAND_MAX;
194 if(!type.norm) {
195 unsigned long long mask;
196 if (type.floating)
197 mask = ~(unsigned long long)0;
198 else if (type.fixed)
199 mask = ((unsigned long long)1 << (type.width / 2)) - 1;
200 else if (type.sign)
201 mask = ((unsigned long long)1 << (type.width - 1)) - 1;
202 else
203 mask = ((unsigned long long)1 << type.width) - 1;
204 value += (double)(mask & rand());
205 }
206 if(!type.sign)
207 if(rand() & 1)
208 value = -value;
209 write_elem(type, dst, index, value);
210 }
211
212
213 void
214 read_vec(struct lp_type type, const void *src, double *dst)
215 {
216 unsigned i;
217 for (i = 0; i < type.length; ++i)
218 dst[i] = read_elem(type, src, i);
219 }
220
221
222 void
223 write_vec(struct lp_type type, void *dst, const double *src)
224 {
225 unsigned i;
226 for (i = 0; i < type.length; ++i)
227 write_elem(type, dst, i, src[i]);
228 }
229
230
231 float
232 random_float(void)
233 {
234 return (float)((double)rand()/(double)RAND_MAX);
235 }
236
237
238 void
239 random_vec(struct lp_type type, void *dst)
240 {
241 unsigned i;
242 for (i = 0; i < type.length; ++i)
243 random_elem(type, dst, i);
244 }
245
246
247 boolean
248 compare_vec_with_eps(struct lp_type type, const void *res, const void *ref, double eps)
249 {
250 unsigned i;
251 for (i = 0; i < type.length; ++i) {
252 double res_elem = read_elem(type, res, i);
253 double ref_elem = read_elem(type, ref, i);
254 double delta = fabs(res_elem - ref_elem);
255 if(delta >= 2.0*eps)
256 return FALSE;
257 }
258
259 return TRUE;
260 }
261
262
263 boolean
264 compare_vec(struct lp_type type, const void *res, const void *ref)
265 {
266 double eps = lp_const_eps(type);
267 return compare_vec_with_eps(type, res, ref, eps);
268 }
269
270
271 void
272 dump_vec(FILE *fp, struct lp_type type, const void *src)
273 {
274 unsigned i;
275 for (i = 0; i < type.length; ++i) {
276 if(i)
277 fprintf(fp, " ");
278 if (type.floating) {
279 double value;
280 switch(type.width) {
281 case 32:
282 value = *((const float *)src + i);
283 break;
284 case 64:
285 value = *((const double *)src + i);
286 break;
287 default:
288 assert(0);
289 value = 0.0;
290 }
291 fprintf(fp, "%f", value);
292 }
293 else {
294 if(type.sign && !type.norm) {
295 long long value;
296 const char *format;
297 switch(type.width) {
298 case 8:
299 value = *((const int8_t *)src + i);
300 format = "%3lli";
301 break;
302 case 16:
303 value = *((const int16_t *)src + i);
304 format = "%5lli";
305 break;
306 case 32:
307 value = *((const int32_t *)src + i);
308 format = "%10lli";
309 break;
310 case 64:
311 value = *((const int64_t *)src + i);
312 format = "%20lli";
313 break;
314 default:
315 assert(0);
316 value = 0.0;
317 format = "?";
318 }
319 fprintf(fp, format, value);
320 }
321 else {
322 unsigned long long value;
323 const char *format;
324 switch(type.width) {
325 case 8:
326 value = *((const uint8_t *)src + i);
327 format = type.norm ? "%2x" : "%4llu";
328 break;
329 case 16:
330 value = *((const uint16_t *)src + i);
331 format = type.norm ? "%4x" : "%6llx";
332 break;
333 case 32:
334 value = *((const uint32_t *)src + i);
335 format = type.norm ? "%8x" : "%11llx";
336 break;
337 case 64:
338 value = *((const uint64_t *)src + i);
339 format = type.norm ? "%16x" : "%21llx";
340 break;
341 default:
342 assert(0);
343 value = 0.0;
344 format = "?";
345 }
346 fprintf(fp, format, value);
347 }
348 }
349 }
350 }
351
352
353 int main(int argc, char **argv)
354 {
355 unsigned verbose = 0;
356 FILE *fp = NULL;
357 unsigned long n = 1000;
358 unsigned i;
359 boolean success;
360
361 for(i = 1; i < argc; ++i) {
362 if(strcmp(argv[i], "-v") == 0)
363 ++verbose;
364 else if(strcmp(argv[i], "-o") == 0)
365 fp = fopen(argv[++i], "wt");
366 else
367 n = atoi(argv[i]);
368 }
369
370 #ifdef LLVM_NATIVE_ARCH
371 LLVMLinkInJIT();
372 LLVMInitializeNativeTarget();
373 #endif
374
375 util_cpu_detect();
376
377 if(fp) {
378 /* Warm up the caches */
379 test_some(0, NULL, 100);
380
381 write_tsv_header(fp);
382 }
383
384 if(n)
385 success = test_some(verbose, fp, n);
386 else
387 success = test_all(verbose, fp);
388
389 if(fp)
390 fclose(fp);
391
392 return success ? 0 : 1;
393 }