diff options
author | Andreas Rottmann <a.rottmann@gmx.at> | 2010-07-19 22:40:56 +0200 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2010-07-19 22:40:56 +0200 |
commit | 442eaa681b0c2db4254d4903f8a0996b4ffc83d0 (patch) | |
tree | d28496035ffbc5e179218cad7a82f7783be00459 /libguile/random.c | |
parent | d68a81e038597ba3d47f39b4cd8a5864953dc1d5 (diff) | |
download | guile-442eaa681b0c2db4254d4903f8a0996b4ffc83d0.tar.gz |
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.
Diffstat (limited to 'libguile/random.c')
-rw-r--r-- | libguile/random.c | 28 |
1 files changed, 27 insertions, 1 deletions
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; } |