lp_test_main.c revision a07437f8a6a863654487c5586cbd02bfc20f0a3b
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
43void
44dump_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
56double
57read_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
119void
120write_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
188void
189random_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
213void
214read_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
222void
223write_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
231float
232random_float(void)
233{
234    return (float)((double)rand()/(double)RAND_MAX);
235}
236
237
238void
239random_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
247boolean
248compare_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
263boolean
264compare_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
271void
272dump_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
353int 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}
394