| # Authors: Arnaud Joly | |
| # | |
| # License: BSD 3 clause | |
| import numpy as np | |
| cimport numpy as np | |
| ctypedef np.npy_uint32 UINT32_t | |
| cdef inline UINT32_t DEFAULT_SEED = 1 | |
| cdef enum: | |
| # Max value for our rand_r replacement (near the bottom). | |
| # We don't use RAND_MAX because it's different across platforms and | |
| # particularly tiny on Windows/MSVC. | |
| RAND_R_MAX = 0x7FFFFFFF | |
| cpdef sample_without_replacement(np.int_t n_population, | |
| np.int_t n_samples, | |
| method=*, | |
| random_state=*) | |
| # rand_r replacement using a 32bit XorShift generator | |
| # See http://www.jstatsoft.org/v08/i14/paper for details | |
| cdef inline UINT32_t our_rand_r(UINT32_t* seed) nogil: | |
| """Generate a pseudo-random np.uint32 from a np.uint32 seed""" | |
| # seed shouldn't ever be 0. | |
| if (seed[0] == 0): seed[0] = DEFAULT_SEED | |
| seed[0] ^= <UINT32_t>(seed[0] << 13) | |
| seed[0] ^= <UINT32_t>(seed[0] >> 17) | |
| seed[0] ^= <UINT32_t>(seed[0] << 5) | |
| # Note: we must be careful with the final line cast to np.uint32 so that | |
| # the function behaves consistently across platforms. | |
| # | |
| # The following cast might yield different results on different platforms: | |
| # wrong_cast = <UINT32_t> RAND_R_MAX + 1 | |
| # | |
| # We can use: | |
| # good_cast = <UINT32_t>(RAND_R_MAX + 1) | |
| # or: | |
| # cdef np.uint32_t another_good_cast = <UINT32_t>RAND_R_MAX + 1 | |
| return seed[0] % <UINT32_t>(RAND_R_MAX + 1) | |