util.h (7943B)
1 /* 2 Copyright 2010-2011, D. E. Shaw Research. 3 All rights reserved. 4 5 Redistribution and use in source and binary forms, with or without 6 modification, are permitted provided that the following conditions are 7 met: 8 9 * Redistributions of source code must retain the above copyright 10 notice, this list of conditions, and the following disclaimer. 11 12 * Redistributions in binary form must reproduce the above copyright 13 notice, this list of conditions, and the following disclaimer in the 14 documentation and/or other materials provided with the distribution. 15 16 * Neither the name of D. E. Shaw Research nor the names of its 17 contributors may be used to endorse or promote products derived from 18 this software without specific prior written permission. 19 20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 #ifndef UTIL_H__ 33 #define UTIL_H__ 34 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <errno.h> 39 #include <assert.h> 40 #include <math.h> 41 #include <Random123/features/compilerfeatures.h> 42 43 extern const char *progname; 44 extern int debug; 45 extern int verbose; 46 47 #if defined(_MSC_VER) 48 #define NOMINMAX /* tells Windows.h to NOT define min() & max() */ 49 #include <Windows.h> 50 R123_STATIC_INLINE double now(){ 51 LARGE_INTEGER f; // ticks per second 52 LARGE_INTEGER t; 53 QueryPerformanceFrequency(&f); 54 QueryPerformanceCounter(&t); // ticks since epoch 55 return ((double)t.QuadPart)/((double)f.QuadPart); 56 } 57 #else // _MSC_VER 58 #include <sys/time.h> 59 R123_STATIC_INLINE double now(){ 60 struct timeval tv; 61 gettimeofday(&tv, 0); 62 return 1.e-6*tv.tv_usec + tv.tv_sec; 63 } 64 #endif // _MSC_VER 65 66 /* timer returns difference between current time and *d, also updates *d with current time. */ 67 R123_STATIC_INLINE double timer(double *d) { 68 double dold = *d; 69 *d = now(); 70 return *d - dold; 71 } 72 73 /* strdup may or may not be in string.h, depending on the value 74 of the pp-symbol _XOPEN_SOURCE and other arcana. Just 75 do it ourselves. 76 Mnemonic: "ntcs" = "nul-terminated character string" */ 77 char *ntcsdup(const char *s){ 78 char *p = (char *)malloc(strlen(s)+1); 79 strcpy(p, s); 80 return p; 81 } 82 83 /* MSVC doesn't know about strtoull. Strictly speaking, strtoull 84 isn't standardized in C++98, either, but that seems not to be a 85 problem so we blissfully ignore it and use strtoull (or its MSVC 86 equivalent, _strtoui64) in both C and C++. If strtoull in C++ 87 becomes a problem, we can adopt the prtu strategy (see below) and 88 write C++ versions of strtouNN, that use an istringstream 89 instead. */ 90 #ifdef _MSC_FULL_VER 91 #define strtoull _strtoui64 92 #endif 93 uint32_t strtou32(const char *p, char **endp, int base){ 94 uint32_t ret; 95 errno = 0; 96 ret = strtoul(p, endp, base); 97 assert(errno==0); 98 return ret; 99 } 100 uint64_t strtou64(const char *p, char **endp, int base){ 101 uint64_t ret; 102 errno = 0; 103 ret = strtoull(p, endp, base); 104 assert(errno==0); 105 return ret; 106 } 107 108 #if defined(__cplusplus) 109 /* Strict C++98 doesn't grok %llx or unsigned long long, and with 110 aggressive error-checking, e.g., g++ -pedantic -Wall, will refuse 111 to compile code like: 112 113 fprintf(stderr, "%llx", (R123_ULONG_LONG)v); 114 115 On the other hand, when compiling to a 32-bit target, the only 116 64-bit type is long long, so we're out of luck if we can't use llx. 117 A portable, almost-standard way to do I/O on uint64_t values in C++ 118 is to use bona fide C++ I/O streams. We are still playing 119 fast-and-loose with standards because C++98 doesn't have <stdint.h> 120 and hence doesn't even guarantee that there's a uint64_t, much less 121 that the insertion operator<<(ostream&) works correctly with 122 whatever we've typedef'ed to uint64_t in 123 <features/compilerfeatures.h>. Hope for the best... */ 124 #include <iostream> 125 #include <limits> 126 template <typename T> 127 void prtu(T val){ 128 using namespace std; 129 cerr.width(std::numeric_limits<T>::digits/4); 130 char prevfill = cerr.fill('0'); 131 ios_base::fmtflags prevflags = cerr.setf(ios_base::hex, ios_base::basefield); 132 cerr << val; 133 cerr.flags(prevflags); 134 cerr.fill(prevfill); 135 assert(!cerr.bad()); 136 } 137 void prtu32(uint32_t v){ prtu(v); } 138 void prtu64(uint64_t v){ prtu(v); } 139 140 #else /* __cplusplus */ 141 /* C should be easy. inttypes.h was standardized in 1999. But Microsoft 142 refuses to recognize the 12-year old standard, so: */ 143 #if defined(_MSC_FULL_VER) 144 #define PRIx32 "x" 145 #define PRIx64 "I64x" 146 #else /* _MSC_FULL_VER */ 147 #include <inttypes.h> 148 #endif /* _MSVC_FULL_VER */ 149 void prtu32(uint32_t v){ fprintf(stderr, "%08" PRIx32, v); } 150 void prtu64(uint64_t v){ fprintf(stderr, "%016" PRIx64, v); } 151 152 #endif /* __cplusplus */ 153 154 #define CHECKNOTEQUAL(x, y) do { if ((x) != (y)) ; else { \ 155 fprintf(stderr, "%s: %s line %d error %s == %s (%s)\n", progname, __FILE__, __LINE__, #x, #y, strerror(errno)); \ 156 exit(1); \ 157 } } while (0) 158 #define CHECKEQUAL(x, y) do { if ((x) == (y)) ; else { \ 159 fprintf(stderr, "%s: %s line %d error %s != %s (%s)\n", progname, __FILE__, __LINE__, #x, #y, strerror(errno)); \ 160 exit(1); \ 161 } } while (0) 162 #define CHECKZERO(x) CHECKEQUAL((x), 0) 163 #define CHECKNOTZERO(x) CHECKNOTEQUAL((x), 0) 164 165 #define dprintf(x) do { if (debug < 1) ; else { printf x; fflush(stdout); } } while (0) 166 167 #define ALLZEROS(x, K, N) \ 168 do { \ 169 int allzeros = 1; \ 170 unsigned xi, xj; \ 171 for (xi = 0; xi < (unsigned)(K); xi++) \ 172 for (xj = 0; xj < (unsigned)(N); xj++) \ 173 allzeros = allzeros & ((x)[xi].v[xj] == 0); \ 174 if (allzeros) fprintf(stderr, "%s: Unexpected, all %lu elements of %ux%u had all zeros!\n", progname, (unsigned long)K, (unsigned)N, 8/*CHAR_BITS*/*(unsigned)sizeof(x[0].v[0])); \ 175 } while(0) 176 177 /* Read in N words of width W into ARR */ 178 #define SCANFARRAY(ARR, NAME, N, W) \ 179 do { \ 180 int xi, xj; \ 181 unsigned long long xv; \ 182 for (xi = 0; xi < (N); xi++) { \ 183 /* Avoid any cleverness with SCNx##W because Microsoft (as of Visual Studio 10.x) silently trashes the stack by pretending that %hhx is %x). */ \ 184 const char *xfmt = " %llx%n"; \ 185 ret = sscanf(cp, xfmt, &xv, &xj); \ 186 ARR.v[xi] = (uint##W##_t)xv; \ 187 if (debug > 1) printf("line %d: xfmt for W=%d is \"%s\", got ret=%d xj=%d, %s[%d]=%llx cp=%s", linenum, W, xfmt, ret, xj, #ARR, xi, (unsigned long long) ARR.v[xi], cp); \ 188 if (ret < 1) { \ 189 fprintf(stderr, "%s: ran out of words reading %s on line %d: " #NAME #N "x" #W " %2d %s", \ 190 progname, #ARR, linenum, rounds, line); \ 191 errs++; \ 192 return; \ 193 } \ 194 cp += xj; \ 195 } \ 196 } while(0) 197 198 #define PRINTARRAY(ARR, fp) \ 199 do { \ 200 char ofmt[64]; \ 201 size_t xj; \ 202 /* use %lu and the cast (instead of z) for portability to Microsoft, sizeof(v[0]) should fit easily in an unsigned long. Avoid inttypes for the same reason. */ \ 203 sprintf(ofmt, " %%0%lullx", (unsigned long)sizeof(ARR.v[0])*2UL); \ 204 for (xj = 0; xj < sizeof(ARR.v)/sizeof(ARR.v[0]); xj++) { \ 205 fprintf(fp, ofmt, (unsigned long long) ARR.v[xj]); \ 206 } \ 207 } while(0) 208 209 #define PRINTLINE(NAME, N, W, R, ictr, ukey, octr, fp) \ 210 do { \ 211 fprintf(fp, "%s %d ", #NAME #N "x" #W, R); \ 212 PRINTARRAY(ictr, fp); \ 213 putc(' ', fp); \ 214 PRINTARRAY(ukey, fp); \ 215 putc(' ', fp); \ 216 PRINTARRAY(octr, fp); \ 217 putc('\n', fp); \ 218 fflush(fp); \ 219 } while(0) 220 221 #endif /* UTIL_H__ */