summaryrefslogtreecommitdiffstats
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
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.
-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