summaryrefslogtreecommitdiffstats
path: root/rand.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-08-26 07:07:11 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-08-26 07:07:11 -0700
commit00ce6b18a953b13954a5cad6a54bf4270c9ac275 (patch)
tree512da7561d9e98ef70e968133f66684e86e869b2 /rand.c
parent4822593b544baed61f0a3fa954d058dac66cc892 (diff)
downloadtxr-00ce6b18a953b13954a5cad6a54bf4270c9ac275.tar.gz
txr-00ce6b18a953b13954a5cad6a54bf4270c9ac275.tar.bz2
txr-00ce6b18a953b13954a5cad6a54bf4270c9ac275.zip
random: bug: 32 bit shift.
* rand.c (random): The msb_rand_mask calculation shifts by 32 when msb_rand_bits is zero, like when the modulus is (expt 2 32). By fluke, this has been treated as a zero bit shift on 64 bit intel, so the correct mask was calculated. However, in a PPC64 build, it yields zero. Instead, we calculate the required shift by negating the bit count, in unsigned semantics, and then reducing modulo 32. This gives us the correct value from 0 to 31, resulting in the correct mask.
Diffstat (limited to 'rand.c')
-rw-r--r--rand.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/rand.c b/rand.c
index 719c49c6..d30838ce 100644
--- a/rand.c
+++ b/rand.c
@@ -366,12 +366,12 @@ val random(val state, val modulus)
if (m == 1) {
return zero;
} else if (m > 1) {
- int bits = highest_bit(m - 1);
+ unsigned bits = highest_bit(m - 1);
#if CHAR_BIT * SIZEOF_PTR >= 64
ucnum rands_needed = (bits + 32 - 1) / 32;
#endif
- ucnum msb_rand_bits = bits % 32;
- rand32_t msb_rand_mask = convert(rand32_t, -1) >> (32 - msb_rand_bits);
+ ucnum msb_rand_bit_shift = (- bits) % 32;
+ rand32_t msb_rand_mask = convert(rand32_t, -1) >> msb_rand_bit_shift;
for (;;) {
cnum out = 0;
#if CHAR_BIT * SIZEOF_PTR >= 64