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