summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Sheppard <kevin.k.sheppard@gmail.com>2019-09-13 23:04:15 +0100
committerKevin Sheppard <kevin.k.sheppard@gmail.com>2019-09-14 21:35:15 +0100
commit5e148ad95f6135382ee5adf999a38342b792ae06 (patch)
treedc3602426c41e68e32a2ffda27cbfe0b015acbeb
parent31ffdecf07d18ed4dbb66b171cb0f998d4b190fa (diff)
downloadnumpy-5e148ad95f6135382ee5adf999a38342b792ae06.tar.gz
BUG: Fix randint when range is 2**32
Fix randint to use 32-bit path when range is exactly 2**32 closes #14189
-rw-r--r--doc/release/upcoming_changes/14501.improvement.rst6
-rw-r--r--numpy/random/src/distributions/distributions.c4
-rw-r--r--numpy/random/tests/test_randomstate_regression.py11
3 files changed, 19 insertions, 2 deletions
diff --git a/doc/release/upcoming_changes/14501.improvement.rst b/doc/release/upcoming_changes/14501.improvement.rst
new file mode 100644
index 000000000..f397ecccf
--- /dev/null
+++ b/doc/release/upcoming_changes/14501.improvement.rst
@@ -0,0 +1,6 @@
+`numpy.random.randint` produced incorrect value when the range was ``2**32``
+----------------------------------------------------------------------------
+The implementation introduced in 1.17.0 had an incorrect check when
+determining whether to use the 32-bit path or the full 64-bit
+path that incorrectly redirected random integer generation with a high - low
+range of ``2**32`` to the 64-bit generator.
diff --git a/numpy/random/src/distributions/distributions.c b/numpy/random/src/distributions/distributions.c
index 65257ecbf..f8d6b9dc5 100644
--- a/numpy/random/src/distributions/distributions.c
+++ b/numpy/random/src/distributions/distributions.c
@@ -1478,7 +1478,7 @@ uint64_t random_bounded_uint64(bitgen_t *bitgen_state, uint64_t off,
uint64_t rng, uint64_t mask, bool use_masked) {
if (rng == 0) {
return off;
- } else if (rng < 0xFFFFFFFFUL) {
+ } else if (rng <= 0xFFFFFFFFUL) {
/* Call 32-bit generator if range in 32-bit. */
if (use_masked) {
return off + buffered_bounded_masked_uint32(bitgen_state, rng, mask, NULL,
@@ -1592,7 +1592,7 @@ void random_bounded_uint64_fill(bitgen_t *bitgen_state, uint64_t off,
for (i = 0; i < cnt; i++) {
out[i] = off;
}
- } else if (rng < 0xFFFFFFFFUL) {
+ } else if (rng <= 0xFFFFFFFFUL) {
uint32_t buf = 0;
int bcnt = 0;
diff --git a/numpy/random/tests/test_randomstate_regression.py b/numpy/random/tests/test_randomstate_regression.py
index 29870534a..ae92319c4 100644
--- a/numpy/random/tests/test_randomstate_regression.py
+++ b/numpy/random/tests/test_randomstate_regression.py
@@ -181,3 +181,14 @@ class TestRegression(object):
assert c.dtype == np.dtype(int)
c = np.random.choice(10, replace=False, size=2)
assert c.dtype == np.dtype(int)
+
+ @pytest.mark.skipif(np.iinfo('l').max < 2**32,
+ reason='Cannot test with 32-bit C long')
+ def test_randint_117(self):
+ # GH 14189
+ random.seed(0)
+ expected = np.array([2357136044, 2546248239, 3071714933, 3626093760,
+ 2588848963, 3684848379, 2340255427, 3638918503,
+ 1819583497, 2678185683], dtype='int64')
+ actual = random.randint(2**32, size=10)
+ assert_array_equal(actual, expected) \ No newline at end of file