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