diff options
author | Andy Wingo <wingo@pobox.com> | 2010-07-26 14:34:27 +0200 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2010-07-26 14:38:20 +0200 |
commit | 3bac8ddf92edc1f954b8f3cd3a8f0f89623cfcda (patch) | |
tree | ca78ecf14b93d8cd9801b6a621b121bf4d0b8da8 | |
parent | db6e848d195cb2e887f119dd2831483a83b2572b (diff) | |
download | guile-3bac8ddf92edc1f954b8f3cd3a8f0f89623cfcda.tar.gz |
though scm_c_random returns a ulong, it's only 32 random bits
* libguile/random.c (scm_c_random): Revert previous patch adapting to
assume ulong-sized bits, as the RNGs really only give us 32 bits at a
time.
(scm_c_random_bignum): Adjust to expect random_bits giving us 32 bits
at a time.
* libguile/random.h: Add comments.
-rw-r--r-- | libguile/random.c | 59 | ||||
-rw-r--r-- | libguile/random.h | 5 |
2 files changed, 21 insertions, 43 deletions
diff --git a/libguile/random.c b/libguile/random.c index 8785eac2e..e150fb4dc 100644 --- a/libguile/random.c +++ b/libguile/random.c @@ -178,11 +178,11 @@ scm_c_exp1 (scm_t_rstate *state) unsigned char scm_masktab[256]; +/* Returns 32 random bits. */ unsigned long scm_c_random (scm_t_rstate *state, unsigned long m) { - unsigned long r, mask; -#if SCM_SIZEOF_UNSIGNED_LONG == 4 + scm_t_uint32 r, mask; mask = (m < 0x100 ? scm_masktab[m] : (m < 0x10000 @@ -191,31 +191,6 @@ 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; } @@ -239,24 +214,24 @@ scm_c_random_bignum (scm_t_rstate *state, SCM m) { SCM result = scm_i_mkbig (); const size_t m_bits = mpz_sizeinbase (SCM_I_BIG_MPZ (m), 2); - /* how many bits would only partially fill the last unsigned long? */ - const size_t end_bits = m_bits % (sizeof (unsigned long) * SCM_CHAR_BIT); - unsigned long *random_chunks = NULL; - const unsigned long num_full_chunks = - m_bits / (sizeof (unsigned long) * SCM_CHAR_BIT); - const unsigned long num_chunks = num_full_chunks + ((end_bits) ? 1 : 0); + /* how many bits would only partially fill the last u32? */ + const size_t end_bits = m_bits % (sizeof (scm_t_uint32) * SCM_CHAR_BIT); + scm_t_uint32 *random_chunks = NULL; + const scm_t_uint32 num_full_chunks = + m_bits / (sizeof (scm_t_uint32) * SCM_CHAR_BIT); + const scm_t_uint32 num_chunks = num_full_chunks + ((end_bits) ? 1 : 0); /* we know the result will be this big */ mpz_realloc2 (SCM_I_BIG_MPZ (result), m_bits); random_chunks = - (unsigned long *) scm_gc_calloc (num_chunks * sizeof (unsigned long), + (scm_t_uint32 *) scm_gc_calloc (num_chunks * sizeof (scm_t_uint32), "random bignum chunks"); do { - unsigned long *current_chunk = random_chunks + (num_chunks - 1); - unsigned long chunks_left = num_chunks; + scm_t_uint32 *current_chunk = random_chunks + (num_chunks - 1); + scm_t_uint32 chunks_left = num_chunks; mpz_set_ui (SCM_I_BIG_MPZ (result), 0); @@ -265,23 +240,23 @@ scm_c_random_bignum (scm_t_rstate *state, SCM m) /* generate a mask with ones in the end_bits position, i.e. if end_bits is 3, then we'd have a mask of ...0000000111 */ const unsigned long rndbits = scm_the_rng.random_bits (state); - int rshift = (sizeof (unsigned long) * SCM_CHAR_BIT) - end_bits; - unsigned long mask = ((unsigned long) ULONG_MAX) >> rshift; - unsigned long highest_bits = rndbits & mask; + int rshift = (sizeof (scm_t_uint32) * SCM_CHAR_BIT) - end_bits; + scm_t_uint32 mask = 0xffffffff >> rshift; + scm_t_uint32 highest_bits = ((scm_t_uint32) rndbits) & mask; *current_chunk-- = highest_bits; chunks_left--; } while (chunks_left) { - /* now fill in the remaining unsigned long sized chunks */ + /* now fill in the remaining scm_t_uint32 sized chunks */ *current_chunk-- = scm_the_rng.random_bits (state); chunks_left--; } mpz_import (SCM_I_BIG_MPZ (result), num_chunks, -1, - sizeof (unsigned long), + sizeof (scm_t_uint32), 0, 0, random_chunks); @@ -289,7 +264,7 @@ scm_c_random_bignum (scm_t_rstate *state, SCM m) all bits in order not to get a distorted distribution) */ } while (mpz_cmp (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (m)) >= 0); scm_gc_free (random_chunks, - num_chunks * sizeof (unsigned long), + num_chunks * sizeof (scm_t_uint32), "random bignum chunks"); return scm_i_normbig (result); } diff --git a/libguile/random.h b/libguile/random.h index 6ec43ff53..c16fa0efb 100644 --- a/libguile/random.h +++ b/libguile/random.h @@ -3,7 +3,7 @@ #ifndef SCM_RANDOM_H #define SCM_RANDOM_H -/* Copyright (C) 1999,2000,2001, 2006 Free Software Foundation, Inc. +/* Copyright (C) 1999,2000,2001, 2006, 2010 Free Software Foundation, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -45,6 +45,7 @@ typedef struct scm_t_rstate { typedef struct scm_t_rng { size_t rstate_size; /* size of random state */ + /* Though this returns an unsigned long, it's only 32 bits of randomness. */ unsigned long (*random_bits) (scm_t_rstate *state); /* gives 32 random bits */ void (*init_rstate) (scm_t_rstate *state, const char *seed, int n); scm_t_rstate *(*copy_rstate) (scm_t_rstate *state); @@ -62,6 +63,7 @@ typedef struct scm_t_i_rstate { unsigned long c; } scm_t_i_rstate; +/* Though this returns an unsigned long, it's only 32 bits of randomness. */ SCM_API unsigned long scm_i_uniform32 (scm_t_i_rstate *); SCM_API void scm_i_init_rstate (scm_t_i_rstate *, const char *seed, int n); SCM_API scm_t_i_rstate *scm_i_copy_rstate (scm_t_i_rstate *); @@ -76,6 +78,7 @@ SCM_API scm_t_rstate *scm_c_default_rstate (void); SCM_API double scm_c_uniform01 (scm_t_rstate *); SCM_API double scm_c_normal01 (scm_t_rstate *); SCM_API double scm_c_exp1 (scm_t_rstate *); +/* Though this returns an unsigned long, it's only 32 bits of randomness. */ SCM_API unsigned long scm_c_random (scm_t_rstate *, unsigned long m); SCM_API SCM scm_c_random_bignum (scm_t_rstate *, SCM m); |