-
-
Notifications
You must be signed in to change notification settings - Fork 10.9k
memcpy-based fast, typed shuffle. #6933
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
File filter
Filter by extension
Conversatio 10000 ns
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ | |
import warnings | ||
|
||
|
||
|
||
class TestSeed(TestCase): | ||
def test_scalar(self): | ||
s = np.random.RandomState(0) | ||
|
@@ -40,6 +41,7 @@ def test_invalid_array(self): | |
assert_raises(ValueError, np.random.RandomState, [1, 2, 4294967296]) | ||
assert_raises(ValueError, np.random.RandomState, [1, -2, 4294967296]) | ||
|
||
|
||
class TestBinomial(TestCase): | ||
def test_n_zero(self): | ||
# Tests the corner case of n == 0 for the binomial distribution. | ||
|
@@ -130,6 +132,7 @@ def test_negative_binomial(self): | |
# arguments without truncation. | ||
self.prng.negative_binomial(0.5, 0.5) | ||
|
||
|
||
class TestRandint(TestCase): | ||
|
||
rfunc = np.random.randint | ||
|
@@ -368,40 +371,41 @@ def test_bytes(self): | |
np.testing.assert_equal(actual, desired) | ||
|
||
def test_shuffle(self): | ||
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. ISTR that we don't like generators like this for testing. @rgommers Do you remember what that was about? 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. From a comment by @pv scipy/scipy#3719 (comment) one reason is that it's harder to debug failing tests, for example import numpy as np
from numpy.testing import assert_allclose
def test_foo():
A = np.arange(100)
B = np.concatenate([A, A])
yield assert_allclose, A, B gives a failing test result that looks like this:
which looks messy. 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. You can set the
gives, IMO, a nice output:
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. The description is not the issue with debugging, it's the context when you enable 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. I don't see any context using either 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. I'm not sure what you mean, but I think you'll find that non-generator tests will drop you into the errored test, and you can 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. Oh, I see. I'll switch this out then. |
||
# Test lists, arrays, and multidimensional versions of both: | ||
for conv in [lambda x: x, | ||
np.asarray, | ||
# Test lists, arrays (of various dtypes), and multidimensional versions | ||
# of both, c-contiguous or not: | ||
for conv in [lambda x: np.array([]), | ||
lambda x: x, | ||
lambda x: np.asarray(x).astype(np.int8), | ||
lambda x: np.asarray(x).astype(np.float32), | ||
lambda x: np.asarray(x).astype(np.complex64), | ||
lambda x: np.asarray(x).astype(object), | ||
lambda x: [(i, i) for i in x], | ||
lambda x: np.asarray([(i, i) for i in x])]: | ||
lambda x: np.asarray([[i, i] for i in x]), | ||
lambda x: np.vstack([x, x]).T, | ||
# gh-4270 | ||
lambda x: np.asarray([(i, i) for i in x], | ||
[("a", object, 1), | ||
("b", np.int32, 1)])]: | ||
np.random.seed(self.seed) | ||
alist = conv([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]) | ||
np.random.shuffle(alist) | ||
actual = alist | ||
desired = conv([0, 1, 9, 6, 2, 4, 5, 8, 7, 3]) | ||
np.testing.assert_array_equal(actual, desired) | ||
|
||
def test_shuffle_flexible(self): | ||
# gh-4270 | ||
arr = [(0, 1), (2, 3)] | ||
dt = np.dtype([('a', np.int32, 1), ('b', np.int32, 1)]) | ||
nparr = np.array(arr, dtype=dt) | ||
a, b = nparr[0].copy(), nparr[1].copy() | ||
for i in range(50): | ||
np.random.shuffle(nparr) | ||
assert_(a in nparr) | ||
assert_(b in nparr) | ||
|
||
def test_shuffle_masked(self): | ||
# gh-3263 | ||
a = np.ma.masked_values(np.reshape(range(20), (5,4)) % 3 - 1, -1) | ||
b = np.ma.masked_values(np.arange(20) % 3 - 1, -1) | ||
ma = np.ma.count_masked(a) | ||
mb = np.ma.count_masked(b) | ||
a_orig = a.copy() | ||
b_orig = b.copy() | ||
for i in range(50): | ||
np.random.shuffle(a) | ||
self.assertEqual(ma, np.ma.count_masked(a)) | ||
assert_equal( | ||
sorted(a.data[~a.mask]), sorted(a_orig.data[~a_orig.mask])) | ||
np.random.shuffle(b) | ||
self.assertEqual(mb, np.ma.count_masked(b)) | ||
assert_equal( | ||
sorted(b.data[~b.mask]), sorted(b_orig.data[~b_orig.mask])) | ||
|
||
def test_beta(self): | ||
np.random.seed(self.seed) | ||
|
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.
Why the cast to
size_t
?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.
Because Cython interprets
<char*>python_object
as casting a bytes object (not an object supporting the buffer protocol) to achar*
, but<char*>c_object
as a C-style cast. (If you try it you'll get "TypeError: expected bytes, int (or whatever you pass in) found")