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