def _check_get_set_state(self, ptr): state = _helperlib.rnd_get_state(ptr) i, ints = state self.assertIsInstance(i, int) self.assertIsInstance(ints, list) self.assertEqual(len(ints), N) j = (i * 100007) % N ints = [i * 3 for i in range(N)] # Roundtrip _helperlib.rnd_set_state(ptr, (j, ints)) self.assertEqual(_helperlib.rnd_get_state(ptr), (j, ints))
def _put_back_random_state(self): # This uses a trick by Alexandre Gramfort, # see https://github.com/numba/numba/issues/3249 if self._random_state >= 0: if self._using_numba: ptr = self._ptr r = self._r index, ints = _helperlib.rnd_get_state(ptr) r.set_state(("MT19937", ints, index, 0, 0.0))
def _check_perturb(self, ptr): states = [] for i in range(10): # Initialize with known state _helperlib.rnd_seed(ptr, 0) # Perturb with entropy _helperlib.rnd_seed(ptr, os.urandom(512)) states.append(tuple(_helperlib.rnd_get_state(ptr)[1])) # No two identical states self.assertEqual(len(set(states)), len(states))
def _check_shuffle(self, ptr): # We test shuffling against CPython r = random.Random() ints, index = _copy_py_state(r, ptr) # Force shuffling in CPython generator for i in range(index, N + 1, 2): r.random() _helperlib.rnd_shuffle(ptr) # Check new integer keys mt = r.getstate()[1] ints, index = mt[:-1], mt[-1] self.assertEqual(_helperlib.rnd_get_state(ptr)[1], list(ints))
def _check_init(self, ptr): # We use the same integer seeding as Numpy # (CPython is different: it treats the integer as a byte array) r = np.random.RandomState() for i in [0, 1, 125, 2**32 - 5]: # Need to cast to a C-sized int (for Numpy <= 1.7) r.seed(np.uint32(i)) st = r.get_state() ints = list(st[1]) index = st[2] assert index == N # sanity check _helperlib.rnd_seed(ptr, i) self.assertEqual(_helperlib.rnd_get_state(ptr), (index, ints))
def box_random_state(typ, val, c): """Convert a native `RandomStateNumbaModel` structure to an `RandomState` object using Numba's internal state array. Note that `RandomStateNumbaModel` is just a placeholder structure with no inherent information about Numba internal random state, all that information is instead retrieved from Numba using ``_helperlib.rnd_get_state()`` and a new `RandomState` is constructed using the Numba's current internal state. """ pos, state_list = _helperlib.rnd_get_state( _helperlib.rnd_get_np_state_ptr()) rng = RandomState() rng.set_state(("MT19937", state_list, pos)) class_obj = c.pyapi.unserialize(c.pyapi.serialize_object(rng)) return class_obj
def get_random_state(): """Get the random state as a tuple. Get the random state from a tuple in the form returned by :func:`numba._helperlib.rnd_get_state`. This tuple contains the necessary information for resuming a checkpoint from the exact same random number generator state. .. important:: You probably do not need to use this function. Be sure you know *exactly* how you are affecting the random number generator state before using this function, or you are likely to create a model that cannot be peproduced. See also :func:`set_random_seed`. Returns ------- state : :obj:`tuple` Random number generator state as a tuple. """ ptr = _helperlib.rnd_get_np_state_ptr() return _helperlib.rnd_get_state(ptr)
def _copyback_np_state(r, ptr): """ Copy state of of Numba state *ptr* to Numpy random *r* """ index, ints = _helperlib.rnd_get_state(ptr) r.set_state(('MT19937', ints, index, 0, 0.0))