From 4b480a21eade9c451c3b9f068f86dbc55b708536 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 26 Aug 2021 07:07:11 -0700 Subject: 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. --- rand.c | 6 +++--- 1 file 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 -- cgit v1.2.3