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