summaryrefslogtreecommitdiff
path: root/libguile/random.c
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2010-07-27 11:32:31 +0200
committerAndy Wingo <wingo@pobox.com>2010-07-27 11:32:40 +0200
commit9defb64118774c8f1a1f6af05d6f1705e7a40619 (patch)
tree6cf4f1da300926e7414d9a0da25918bfbecfeb2c /libguile/random.c
parent17fc9efecbc9cb0c7e32664dbd0e2c863194cd7f (diff)
downloadguile-9defb64118774c8f1a1f6af05d6f1705e7a40619.tar.gz
64-bit random fixes
* libguile/random.c (scm_random): Fix generation of inum randoms with more than 32 bits. * libguile/random.h (scm_t_rstate): Fix a comment.
Diffstat (limited to 'libguile/random.c')
-rw-r--r--libguile/random.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/libguile/random.c b/libguile/random.c
index 6703dac22..83870f6ad 100644
--- a/libguile/random.c
+++ b/libguile/random.c
@@ -371,9 +371,26 @@ SCM_DEFINE (scm_random, "random", 1, 1, 0,
SCM_VALIDATE_RSTATE (2, state);
if (SCM_I_INUMP (n))
{
- scm_t_uint32 m = SCM_I_INUM (n);
- SCM_ASSERT_RANGE (1, n, m > 0);
- return scm_from_uint32 (scm_c_random (SCM_RSTATE (state), m));
+ unsigned long m = (unsigned long) SCM_I_INUM (n);
+ SCM_ASSERT_RANGE (1, n, SCM_I_INUM (n) > 0);
+#if SCM_SIZEOF_UNSIGNED_LONG <= 4
+ return scm_from_uint32 (scm_c_random (SCM_RSTATE (state),
+ (scm_t_uint32) m));
+#elif SCM_SIZEOF_UNSIGNED_LONG <= 8
+ if (m <= SCM_T_UINT32_MAX)
+ return scm_from_uint32 (scm_c_random (SCM_RSTATE (state),
+ (scm_t_uint32) m));
+ else
+ {
+ scm_t_uint64 upper, lower;
+
+ upper = scm_c_random (SCM_RSTATE (state), (scm_t_uint32) (m >> 32));
+ lower = scm_c_random (SCM_RSTATE (state), SCM_T_UINT32_MAX);
+ return scm_from_uint64 ((upper << 32) | lower);
+ }
+#else
+#error "Cannot deal with this platform's unsigned long size"
+#endif
}
SCM_VALIDATE_NIM (1, n);
if (SCM_REALP (n))