diff options
author | Robert Kern <robert.kern@gmail.com> | 2019-06-28 17:30:33 -0700 |
---|---|---|
committer | Matti Picus <matti.picus@gmail.com> | 2019-06-28 17:30:33 -0700 |
commit | e7383b5d5dff636ed92667a28751ce18f7086097 (patch) | |
tree | b4028266c847b8f06a30b090d07033954258a9fd | |
parent | ad84b69bda8eb5e2998370148b9e830d40099d5c (diff) | |
download | numpy-e7383b5d5dff636ed92667a28751ce18f7086097.tar.gz |
BUG: Ensure consistent interpretation of uint64 states. (#13861)
* BUG: test, fix for big-endian systems
-rw-r--r-- | numpy/random/bit_generator.pyx | 4 | ||||
-rw-r--r-- | numpy/random/generator.pyx | 4 | ||||
-rw-r--r-- | numpy/random/mtrand.pyx | 5 | ||||
-rw-r--r-- | numpy/random/tests/test_seed_sequence.py | 16 |
4 files changed, 25 insertions, 4 deletions
diff --git a/numpy/random/bit_generator.pyx b/numpy/random/bit_generator.pyx index cd1b628eb..6694e5e4d 100644 --- a/numpy/random/bit_generator.pyx +++ b/numpy/random/bit_generator.pyx @@ -438,7 +438,9 @@ cdef class SeedSequence(): data_val ^= data_val >> XSHIFT state[i_dst] = data_val if out_dtype == np.dtype(np.uint64): - state = state.view(np.uint64) + # For consistency across different endiannesses, view first as + # little-endian then convert the values to the native endianness. + state = state.astype('<u4').view('<u8').astype(np.uint64) return state def spawn(self, n_children): diff --git a/numpy/random/generator.pyx b/numpy/random/generator.pyx index e6b70f176..0e51f411e 100644 --- a/numpy/random/generator.pyx +++ b/numpy/random/generator.pyx @@ -498,8 +498,10 @@ cdef class Generator: """ cdef Py_ssize_t n_uint32 = ((length - 1) // 4 + 1) + # Interpret the uint32s as little-endian to convert them to bytes + # consistently. return self.integers(0, 4294967296, size=n_uint32, - dtype=np.uint32).tobytes()[:length] + dtype=np.uint32).astype('<u4').tobytes()[:length] def randint(self, low, high=None, size=None, dtype=np.int64, endpoint=False): """ diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index 5d34368a6..46b6b3388 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -671,7 +671,10 @@ cdef class RandomState: """ cdef Py_ssize_t n_uint32 = ((length - 1) // 4 + 1) - return self.randint(0, 4294967296, size=n_uint32, dtype=np.uint32).tobytes()[:length] + # Interpret the uint32s as little-endian to convert them to bytes + # consistently. + return self.randint(0, 4294967296, size=n_uint32, + dtype=np.uint32).astype('<u4').tobytes()[:length] @cython.wraparound(True) def choice(self, a, size=None, replace=True, p=None): diff --git a/numpy/random/tests/test_seed_sequence.py b/numpy/random/tests/test_seed_sequence.py index 34278375a..8d6d604a2 100644 --- a/numpy/random/tests/test_seed_sequence.py +++ b/numpy/random/tests/test_seed_sequence.py @@ -33,8 +33,22 @@ def test_reference_data(): [3978441347, 432478529, 3223635119, 138903045], [296367413, 4262059219, 13109864, 3283683422], ] - for seed, expected in zip(inputs, outputs): + outputs64 = [ + [2477551240072187391, 9577394838764454085], + [15854241394484835714, 11398914698975566411], + [13708282465491374871, 16007308345579681096], + [15424829579845884309, 1898028439751125927], + [9411697742461147792, 15714068361935982142], + [10079222287618677782, 12870437757549876199], + [17326737873898640088, 729039288628699544], + [16644868984619524261, 1544825456798124994], + [1857481142255628931, 596584038813451439], + [18305404959516669237, 14103312907920476776], + ] + for seed, expected, expected64 in zip(inputs, outputs, outputs64): expected = np.array(expected, dtype=np.uint32) ss = SeedSequence(seed) state = ss.generate_state(len(expected)) assert_array_equal(state, expected) + state64 = ss.generate_state(len(expected64), dtype=np.uint64) + assert_array_equal(state64, expected64) |