-
-
Notifications
You must be signed in to change notification settings - Fork 10.9k
BUG: random: Generator.integers(2**32) always returned 0. #16076
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e8b8401
1ded86d
ca5ade8
621efc7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -6,6 +6,8 @@ | |||
#include <intrin.h> | ||||
#endif | ||||
|
||||
#include <assert.h> | ||||
|
||||
/* Inline generators for internal use */ | ||||
static NPY_INLINE uint32_t next_uint32(bitgen_t *bitgen_state) { | ||||
return bitgen_state->next_uint32(bitgen_state->state); | ||||
|
@@ -1149,6 +1151,8 @@ static NPY_INLINE uint64_t bounded_lemire_uint64(bitgen_t *bitgen_state, | |||
*/ | ||||
const uint64_t rng_excl = rng + 1; | ||||
|
||||
assert(rng != 0xFFFFFFFFFFFFFFFFULL); | ||||
|
||||
#if __SIZEOF_INT128__ | ||||
/* 128-bit uint available (e.g. GCC/clang). `m` is the __uint128_t scaled | ||||
* integer. */ | ||||
|
@@ -1239,6 +1243,8 @@ static NPY_INLINE uint32_t buffered_bounded_lemire_uint32( | |||
uint64_t m; | ||||
uint32_t leftover; | ||||
|
||||
assert(rng != 0xFFFFFFFFUL); | ||||
|
||||
/* Generate a scaled random number. */ | ||||
m = ((uint64_t)next_uint32(bitgen_state)) * rng_excl; | ||||
|
||||
|
@@ -1273,6 +1279,8 @@ static NPY_INLINE uint16_t buffered_bounded_lemire_uint16( | |||
uint32_t m; | ||||
uint16_t leftover; | ||||
|
||||
assert(rng != 0xFFFFU); | ||||
|
||||
/* Generate a scaled random number. */ | ||||
m = ((uint32_t)buffered_uint16(bitgen_state, bcnt, buf)) * rng_excl; | ||||
|
||||
|
@@ -1308,6 +1316,9 @@ static NPY_INLINE uint8_t buffered_bounded_lemire_uint8(bitgen_t *bitgen_state, | |||
uint16_t m; | ||||
uint8_t leftover; | ||||
|
||||
assert(rng != 0xFFU); | ||||
|
||||
|
||||
/* Generate a scaled random number. */ | ||||
m = ((uint16_t)buffered_uint8(bitgen_state, bcnt, buf)) * rng_excl; | ||||
|
||||
|
@@ -1337,6 +1348,14 @@ uint64_t random_bounded_uint64(bitgen_t *bitgen_state, uint64_t off, | |||
return off; | ||||
} else if (rng <= 0xFFFFFFFFUL) { | ||||
/* Call 32-bit generator if range in 32-bit. */ | ||||
if (rng == 0xFFFFFFFFUL) { | ||||
/* | ||||
* The 32-bit Lemire method does not handle rng=0xFFFFFFFF, so we'll | ||||
* call next_uint32 directly. This also works when use_masked is True, | ||||
* so we handle both cases here. | ||||
*/ | ||||
return off + (uint64_t) next_uint32(bitgen_state); | ||||
} | ||||
if (use_masked) { | ||||
return off + buffered_bounded_masked_uint32(bitgen_state, rng, mask, NULL, | ||||
NULL); | ||||
|
@@ -1450,22 +1469,34 @@ void random_bounded_uint64_fill(bitgen_t *bitgen_state, uint64_t off, | |||
out[i] = off; | ||||
} | ||||
} else if (rng <= 0xFFFFFFFFUL) { | ||||
uint32_t buf = 0; | ||||
int bcnt = 0; | ||||
|
||||
/* Call 32-bit generator if range in 32-bit. */ | ||||
if (use_masked) { | ||||
/* Smallest bit mask >= max */ | ||||
uint64_t mask = gen_mask(rng); | ||||
|
||||
/* | ||||
* The 32-bit Lemire method does not handle rng=0xFFFFFFFF, so we'll | ||||
* call next_uint32 directly. This also works when use_masked is True, | ||||
* so we handle both cases here. | ||||
*/ | ||||
if (rng == 0xFFFFFFFFUL) { | ||||
for (i = 0; i < cnt; i++) { | ||||
out[i] = off + buffered_bounded_masked_uint32(bitgen_state, rng, mask, | ||||
&bcnt, &buf); | ||||
out[i] = off + (uint64_t) next_uint32(bitgen_state); | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this code used in Would it be safest to added a test in RandomState too with the same end points? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is tested by the test that was added in gh-14501:
8000
|
||||
} | ||||
} else { | ||||
for (i = 0; i < cnt; i++) { | ||||
out[i] = off + | ||||
buffered_bounded_lemire_uint32(bitgen_state, rng, &bcnt, &buf); | ||||
uint32_t buf = 0; | ||||
int bcnt = 0; | ||||
|
||||
if (use_masked) { | ||||
/* Smallest bit mask >= max */ | ||||
uint64_t mask = gen_mask(rng); | ||||
|
||||
for (i = 0; i < cnt; i++) { | ||||
out[i] = off + buffered_bounded_masked_uint32(bitgen_state, rng, mask, | ||||
&bcnt, &buf); | ||||
} | ||||
} else { | ||||
for (i = 0; i < cnt; i++) { | ||||
out[i] = off + | ||||
buffered_bounded_lemire_uint32(bitgen_state, rng, &bcnt, &buf); | ||||
} | ||||
} | ||||
} | ||||
} else if (rng == 0xFFFFFFFFFFFFFFFFULL) { | ||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the same would apply here as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this needs a test. When calling
randint
with scalar values oflow
andhigh
, this path is not reached, even whensize
isNone
. It turns out that the functionrandom_bounded_uint64
is called by the code that handles broadcasting forrandom.randint
. I'll add a repeatability test for that.