From 442eaa681b0c2db4254d4903f8a0996b4ffc83d0 Mon Sep 17 00:00:00 2001 From: Andreas Rottmann Date: Mon, 19 Jul 2010 22:40:56 +0200 Subject: [PATCH] Fix random number generator on 64-bit platforms * libguile/random.c (scm_c_random): On platforms where `unsigned long' has 64 bit, generate up to 64 bit of randomness. This is expected by scm_c_random_bignum(), and hence was a serious distortion of the random value distribution for values exceeding 2^32. This change also fixes a crash when the `m' argument is a value above 2^32. --- libguile/random.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/libguile/random.c b/libguile/random.c index 281d43aa8..1a9fd59ac 100644 --- a/libguile/random.c +++ b/libguile/random.c @@ -223,7 +223,8 @@ unsigned char scm_masktab[256]; unsigned long scm_c_random (scm_t_rstate *state, unsigned long m) { - unsigned int r, mask; + unsigned long r, mask; +#if SCM_SIZEOF_UNSIGNED_LONG == 4 mask = (m < 0x100 ? scm_masktab[m] : (m < 0x10000 @@ -232,6 +233,31 @@ scm_c_random (scm_t_rstate *state, unsigned long m) ? scm_masktab[m >> 16] << 16 | 0xffff : scm_masktab[m >> 24] << 24 | 0xffffff))); while ((r = scm_the_rng.random_bits (state) & mask) >= m); +#elif SCM_SIZEOF_UNSIGNED_LONG == 8 + mask = (m < 0x100 + ? scm_masktab[m] + : (m < 0x10000 + ? scm_masktab[m >> 8] << 8 | 0xff + : (m < 0x1000000 + ? scm_masktab[m >> 16] << 16 | 0xffff + : (m < (1UL << 32) + ? scm_masktab[m >> 24] << 24 | 0xffffff + : (m < (1UL << 40) + ? ((unsigned long) scm_masktab[m >> 32] << 32 + | 0xffffffffUL) + : (m < (1UL << 48) + ? ((unsigned long) scm_masktab[m >> 40] << 40 + | 0xffffffffffUL) + : (m < (1UL << 56) + ? ((unsigned long) scm_masktab[m >> 48] << 48 + | 0xffffffffffffUL) + : ((unsigned long) scm_masktab[m >> 56] << 56 + | 0xffffffffffffffUL)))))))); + while ((r = ((scm_the_rng.random_bits (state) << 32 + | scm_the_rng.random_bits (state))) & mask) >= m); +#else +#error "Cannot deal with this platform's unsigned long size" +#endif return r; }