lp_test_main.c revision 9f9b44222f45a4548070c1019674abe173e2f253
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      unsigned long long mask;
209      if (type.floating)
210         mask = ~(unsigned long long)0;
211      else if (type.fixed)
212         mask = ((unsigned long long)1 << (type.width / 2)) - 1;
213      else if (type.sign)
214         mask = ((unsigned long long)1 << (type.width - 1)) - 1;
215      else
216         mask = ((unsigned long long)1 << type.width) - 1;
217      value += (double)(mask & rand());
218   }
219   if(!type.sign)
220      if(rand() & 1)
221         value = -value;
222   write_elem(type, dst, index, value);
223}
224
225
226void
227read_vec(struct lp_type type, const void *src, double *dst)
228{
229   unsigned i;
230   for (i = 0; i < type.length; ++i)
231      dst[i] = read_elem(type, src, i);
232}
233
234
235void
236write_vec(struct lp_type type, void *dst, const double *src)
237{
238   unsigned i;
239   for (i = 0; i < type.length; ++i)
240      write_elem(type, dst, i, src[i]);
241}
242
243
244float
245random_float(void)
246{
247    return (float)((double)rand()/(double)RAND_MAX);
248}
249
250
251void
252random_vec(struct lp_type type, void *dst)
253{
254   unsigned i;
255   for (i = 0; i < type.length; ++i)
256      random_elem(type, dst, i);
257}
258
259
260boolean
261compare_vec_with_eps(struct lp_type type, const void *res, const void *ref, double eps)
262{
263   unsigned i;
264   for (i = 0; i < type.length; ++i) {
265      double res_elem = read_elem(type, res, i);
266      double ref_elem = read_elem(type, ref, i);
267      double delta = fabs(res_elem - ref_elem);
268      if(delta >= 2.0*eps)
269         return FALSE;
270   }
271
272   return TRUE;
273}
274
275
276boolean
277compare_vec(struct lp_type type, const void *res, const void *ref)
278{
279   double eps = lp_const_eps(type);
280   return compare_vec_with_eps(type, res, ref, eps);
281}
282
283
284void
285dump_vec(FILE *fp, struct lp_type type, const void *src)
286{
287   unsigned i;
288   for (i = 0; i < type.length; ++i) {
289      if(i)
290         fprintf(fp, " ");
291      if (type.floating) {
292         double value;
293         switch(type.width) {
294         case 32:
295            value = *((const float *)src + i);
296            break;
297         case 64:
298            value = *((const double *)src + i);
299            break;
300         default:
301            assert(0);
302            value = 0.0;
303         }
304         fprintf(fp, "%f", value);
305      }
306      else {
307         if(type.sign && !type.norm) {
308            long long value;
309            const char *format;
310            switch(type.width) {
311            case 8:
312               value = *((const int8_t *)src + i);
313               format = "%3lli";
314               break;
315            case 16:
316               value = *((const int16_t *)src + i);
317               format = "%5lli";
318               break;
319            case 32:
320               value = *((const int32_t *)src + i);
321               format = "%10lli";
322               break;
323            case 64:
324               value = *((const int64_t *)src + i);
325               format = "%20lli";
326               break;
327            default:
328               assert(0);
329               value = 0.0;
330               format = "?";
331            }
332            fprintf(fp, format, value);
333         }
334         else {
335            unsigned long long value;
336            const char *format;
337            switch(type.width) {
338            case 8:
339               value = *((const uint8_t *)src + i);
340               format = type.norm ? "%2x" : "%4llu";
341               break;
342            case 16:
343               value = *((const uint16_t *)src + i);
344               format = type.norm ? "%4x" : "%6llx";
345               break;
346            case 32:
347               value = *((const uint32_t *)src + i);
348               format = type.norm ? "%8x" : "%11llx";
349               break;
350            case 64:
351               value = *((const uint64_t *)src + i);
352               format = type.norm ? "%16x" : "%21llx";
353               break;
354            default:
355               assert(0);
356               value = 0.0;
357               format = "?";
358            }
359            fprintf(fp, format, value);
360         }
361      }
362   }
363}
364
365
366int main(int argc, char **argv)
367{
368   unsigned verbose = 0;
369   FILE *fp = NULL;
370   unsigned long n = 1000;
371   unsigned i;
372   boolean success;
373
374   for(i = 1; i < argc; ++i) {
375      if(strcmp(argv[i], "-v") == 0)
376         ++verbose;
377      else if(strcmp(argv[i], "-o") == 0)
378         fp = fopen(argv[++i], "wt");
379      else
380         n = atoi(argv[i]);
381   }
382
383   lp_build_init();
384
385   util_cpu_detect();
386
387   if(fp) {
388      /* Warm up the caches */
389      test_some(0, NULL, 100);
390
391      write_tsv_header(fp);
392   }
393
394   if(n)
395      success = test_some(verbose, fp, n);
396   else
397      success = test_all(verbose, fp);
398
399   if(fp)
400      fclose(fp);
401
402   return success ? 0 : 1;
403}
404