diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-08-26 07:07:11 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-08-26 07:07:11 -0700 |
commit | 00ce6b18a953b13954a5cad6a54bf4270c9ac275 (patch) | |
tree | 512da7561d9e98ef70e968133f66684e86e869b2 | |
parent | 4822593b544baed61f0a3fa954d058dac66cc892 (diff) | |
download | txr-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.c | 6 |
1 files changed, 3 insertions, 3 deletions
@@ -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 |