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