random123

Counter-based Random Number Generators
git clone git://git.meso-star.com/random123.git
Log | Files | Refs | README | LICENSE

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__ */