diff --git a/app/meson.build b/app/meson.build index 626e89f8..cc465564 100644 --- a/app/meson.build +++ b/app/meson.build @@ -170,6 +170,8 @@ check_functions = [ 'strdup', 'asprintf', 'vasprintf', + 'nrand48', + 'jrand48', ] foreach f : check_functions diff --git a/app/src/compat.c b/app/src/compat.c index 11ddd3cb..bb0152aa 100644 --- a/app/src/compat.c +++ b/app/src/compat.c @@ -51,3 +51,47 @@ int vasprintf(char **strp, const char *fmt, va_list ap) { return len; } #endif + +#if !defined(HAVE_NRAND48) || !defined(HAVE_JRAND48) +#define SC_RAND48_MASK UINT64_C(0xFFFFFFFFFFFF) // 48 bits +#define SC_RAND48_A UINT64_C(0x5DEECE66D) +#define SC_RAND48_C 0xB +static inline uint64_t rand_iter48(uint64_t x) { + assert((x & ~SC_RAND48_MASK) == 0); + return (x * SC_RAND48_A + SC_RAND48_C) & SC_RAND48_MASK; +} + +static uint64_t rand_iter48_xsubi(unsigned short xsubi[3]) { + uint64_t x = ((uint64_t) xsubi[0] << 32) + | ((uint64_t) xsubi[1] << 16) + | xsubi[2]; + + x = rand_iter48(x); + + xsubi[0] = (x >> 32) & 0XFFFF; + xsubi[1] = (x >> 16) & 0XFFFF; + xsubi[2] = x & 0XFFFF; + + return x; +} + +#ifndef HAVE_NRAND48 +long nrand48(unsigned short xsubi[3]) { + // range [0, 2^31) + return rand_iter48_xsubi(xsubi) >> 17; +} +#endif + +#ifndef HAVE_JRAND48 +long jrand48(unsigned short xsubi[3]) { + // range [-2^31, 2^31) + union { + uint32_t u; + int32_t i; + } v; + v.u = rand_iter48_xsubi(xsubi) >> 16; + return v.i; +} +#endif + +#endif diff --git a/app/src/compat.h b/app/src/compat.h index 8265dbc8..857623e6 100644 --- a/app/src/compat.h +++ b/app/src/compat.h @@ -59,4 +59,12 @@ int asprintf(char **strp, const char *fmt, ...); int vasprintf(char **strp, const char *fmt, va_list ap); #endif +#ifndef HAVE_NRAND48 +long nrand48(unsigned short xsubi[3]); +#endif + +#ifndef HAVE_JRAND48 +long jrand48(unsigned short xsubi[3]); +#endif + #endif