lp_test_main.c revision 9a8e9f4595b66ea094b293da1afcded8f06ab3d6
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
45static INLINE double
46round(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
56void
57dump_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
69double
70read_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
132void
133write_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
201void
202random_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
229void
230read_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
238void
239write_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
247float
248random_float(void)
249{
250    return (float)((double)rand()/(double)RAND_MAX);
251}
252
253
254void
255random_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
263boolean
264compare_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
285boolean
286compare_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
293void
294dump_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
375int 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}
418