From a78a167a4f74759fd291802b95193a0f39a4cb59 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 31 Dec 2016 13:01:19 +0200 Subject: [PATCH] Serialize random number generation on MS-Windows * src/w32.c (rand_as183): New function. (random): Use it instead of MS runtime's 'rand'. This avoids producing separate and identical random series in each Lisp thread. (srandom): Modify to supply 3 seed values to 'rand_as183'. --- src/w32.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/w32.c b/src/w32.c index e96f29791ea..59dc685710e 100644 --- a/src/w32.c +++ b/src/w32.c @@ -2154,17 +2154,40 @@ w32_init_random (void *buf, ptrdiff_t buflen) return -1; } +/* MS-Windows 'rand' produces separate identical series for each + thread, so we replace it with our version. */ + +/* Algorithm AS183: An Efficient and Portable Pseudo-random Number + Generator, by B.A. Wichmann, I.D. Hill. AS, v31, No. 2 (1982). */ +static int ix = 3172, iy = 9814, iz = 20125; +#define RAND_MAX_X 30269 +#define RAND_MAX_Y 30307 +#define RAND_MAX_Z 30323 + +static int +rand_as183 (void) +{ + ix = (171 * ix) % RAND_MAX_X; + iy = (172 * iy) % RAND_MAX_Y; + iz = (170 * iz) % RAND_MAX_Z; + + return (ix + iy + iz) & 0x7fff; +} + int random (void) { - /* rand () on NT gives us 15 random bits...hack together 30 bits. */ - return ((rand () << 15) | rand ()); + /* rand_as183 () gives us 15 random bits...hack together 30 bits. */ + return ((rand_as183 () << 15) | rand_as183 ()); } void srandom (int seed) { srand (seed); + ix = rand () % RAND_MAX_X; + iy = rand () % RAND_MAX_Y; + iz = rand () % RAND_MAX_Z; } /* Return the maximum length in bytes of a multibyte character -- 2.39.2