diff --git a/.github/workflows/cron-build-and-test.yml b/.github/workflows/cron-build-and-test.yml index b4ccd084d..593e0254b 100644 --- a/.github/workflows/cron-build-and-test.yml +++ b/.github/workflows/cron-build-and-test.yml @@ -19,12 +19,12 @@ jobs: fail-fast: false matrix: python: [cp312] - os: [ubuntu-latest, windows-latest, macos-latest] + os: [ubuntu-latest, windows-latest, macos-latest, macos-13] env: BUILD_COMMIT: "main" CIBW_BUILD: ${{ matrix.python }}-* CIBW_ARCHS_LINUX: "x86_64" - CIBW_ARCHS_MACOS: "arm64" + CIBW_ARCHS_MACOS: "auto" CIBW_SKIP: "pp* *-musllinux_* *-win32" CIBW_TEST_REQUIRES: pytest pytest-xdist CIBW_TEST_COMMAND: python -c "import randomgen; randomgen.test(['--skip-slow','-n','2'])" diff --git a/doc/source/change-log.rst b/doc/source/change-log.rst index e4b73dce6..36f124e41 100644 --- a/doc/source/change-log.rst +++ b/doc/source/change-log.rst @@ -5,6 +5,8 @@ Change Log v2.1.0 ====== +- Fixed a bug in :class:`~randomgen.pcg64.LCG128Mix` that resultsed in ``inc`` + not being correctly set when initialized without a user-provided ``inc``. - Added the :class:`~randomgen.tyche.Tyche` PRNG of Neves and Araujo. Supports two variants. One is the original implementation in the 2012 paper. The second matches the version in ``OpenRand``. diff --git a/randomgen/_seed_sequence.pxd b/randomgen/_seed_sequence.pxd index 1a3334335..3ef9c6047 100644 --- a/randomgen/_seed_sequence.pxd +++ b/randomgen/_seed_sequence.pxd @@ -1,4 +1,4 @@ -# cython: binding=True, language_level=3 + cimport numpy as np from libc.stdint cimport uint32_t diff --git a/randomgen/aes.pxd b/randomgen/aes.pxd index ac68f758f..ebe6679e2 100644 --- a/randomgen/aes.pxd +++ b/randomgen/aes.pxd @@ -1,4 +1,4 @@ -# cython: binding=True, language_level=3 + cimport numpy as np from libc.stdint cimport uint8_t, uint32_t, uint64_t diff --git a/randomgen/aes.pyx b/randomgen/aes.pyx index 3d19c998b..8832b4470 100644 --- a/randomgen/aes.pyx +++ b/randomgen/aes.pyx @@ -180,10 +180,7 @@ cdef class AESCounter(BitGenerator): aesctr_use_aesni(bool(value)) def _seed_from_seq(self, counter=None): - try: - state = self.seed_seq.generate_state(2, np.uint64) - except AttributeError: - state = self._seed_seq.generate_state(2, np.uint64) + state = self._get_seed_seq().generate_state(2, np.uint64) self.seed(key=state, counter=counter) self._reset_state_variables() diff --git a/randomgen/bounded_integers.pyx.in b/randomgen/bounded_integers.pyx.in index 0ad7d6c7f..a5bd4d51d 100644 --- a/randomgen/bounded_integers.pyx.in +++ b/randomgen/bounded_integers.pyx.in @@ -1,5 +1,5 @@ #!python -#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True +# cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True import numpy as np @@ -44,7 +44,7 @@ cdef object _rand_{{nptype}}_broadcast(np.ndarray low, np.ndarray high, object s this type for checking and the recast to {{nptype}} when producing the random integers. """ - cdef {{utype}}_t rng, last_rng, off, val, mask, out_val, is_open + cdef {{utype}}_t rng, last_rng, off, mask, is_open cdef uint32_t buf cdef {{utype}}_t *out_data cdef {{nptype_up}}_t low_v, high_v @@ -131,7 +131,7 @@ cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, cdef uint64_t *out_data cdef {{nptype}}_t *highm1_data cdef {{nptype}}_t low_v, high_v - cdef uint64_t rng, last_rng, val, mask, off, out_val + cdef uint64_t rng, last_rng, mask, off low_arr = low high_arr = high @@ -264,7 +264,7 @@ cdef object _rand_{{nptype}}(object low, object high, object size, cdef np.ndarray out_arr, low_arr, high_arr cdef {{utype}}_t rng, off, out_val cdef {{utype}}_t *out_data - cdef np.npy_intp i, n, cnt + cdef np.npy_intp cnt if size is not None: if (np.prod(size) == 0): diff --git a/randomgen/broadcasting.pyx b/randomgen/broadcasting.pyx index 0e0f31a67..a335b6029 100644 --- a/randomgen/broadcasting.pyx +++ b/randomgen/broadcasting.pyx @@ -44,7 +44,6 @@ cdef int check_array_constraint(np.ndarray val, object name, constraint_type con cdef int check_constraint(double val, object name, constraint_type cons) except -1: - cdef bint is_nan if cons == CONS_NON_NEGATIVE: if not np.isnan(val) and np.signbit(val): raise ValueError(name + " < 0") @@ -81,7 +80,6 @@ cdef int check_constraint(double val, object name, constraint_type cons) except cdef validate_output_shape(iter_shape, np.ndarray output): cdef np.npy_intp *dims cdef np.npy_intp ndim, i - cdef bint error dims = np.PyArray_DIMS(output) ndim = np.PyArray_NDIM(output) output_shape = tuple((dims[i] for i in range(ndim))) @@ -135,7 +133,7 @@ cdef object double_fill(void *func, bitgen_t *state, object size, object lock, o cdef double out_val cdef double *out_array_data cdef np.ndarray out_array - cdef np.npy_intp i, n + cdef np.npy_intp n if size is None and out is None: with lock: @@ -515,7 +513,7 @@ cdef object discrete_broadcast_di(void *func, void *state, object size, object l for i in range(n): a_val = (np.PyArray_MultiIter_DATA(it, 1))[0] b_val = (np.PyArray_MultiIter_DATA(it, 2))[0] - (np.PyArray_MultiIter_DATA(it, 0))[0] = f(state, a_val, b_val) + randoms_data[i] = f(state, a_val, b_val) np.PyArray_MultiIter_NEXT(it) @@ -641,6 +639,11 @@ cdef object disc(void *func, void *state, object size, object lock, return discrete_broadcast_di(func, state, size, lock, a_arr, a_name, a_constraint, b_arr, b_name, b_constraint) + elif narg_int64 == 3: + return discrete_broadcast_iii(func, state, size, lock, + a_arr, a_name, a_constraint, + b_arr, b_name, b_constraint, + c_arr, c_name, c_constraint) else: raise NotImplementedError("No vector path available") @@ -773,7 +776,7 @@ cdef object cont_f(void *func, bitgen_t *state, object size, object lock, object a, object a_name, constraint_type a_constraint, object out): - cdef np.ndarray a_arr, b_arr, c_arr + cdef np.ndarray a_arr cdef float _a cdef bint is_scalar = True cdef int requirements = api.NPY_ARRAY_ALIGNED | api.NPY_ARRAY_FORCECAST diff --git a/randomgen/chacha.pxd b/randomgen/chacha.pxd index 74c81bfde..21553cf9d 100644 --- a/randomgen/chacha.pxd +++ b/randomgen/chacha.pxd @@ -1,4 +1,4 @@ -# cython: binding=True, language_level=3 + cimport numpy as np from libc.stdint cimport uint32_t, uint64_t diff --git a/randomgen/chacha.pyx b/randomgen/chacha.pyx index ced400372..87d63b906 100644 --- a/randomgen/chacha.pyx +++ b/randomgen/chacha.pyx @@ -156,10 +156,7 @@ cdef class ChaCha(BitGenerator): PyArray_free_aligned(self.rng_state) def _seed_from_seq(self, counter=None): - try: - state = self.seed_seq.generate_state(4, np.uint64) - except AttributeError: - state = self._seed_seq.generate_state(4, np.uint64) + state = self._get_seed_seq().generate_state(4, np.uint64) self.seed(key=state, counter=counter) @property diff --git a/randomgen/common.pyx b/randomgen/common.pyx index c7da9d65f..99aaa1c9f 100644 --- a/randomgen/common.pyx +++ b/randomgen/common.pyx @@ -58,6 +58,13 @@ cdef class BitGenerator(_BitGenerator): def _supported_modes(self): return ("sequence",) + def _get_seed_seq(self): + try: + return self.seed_seq + except AttributeError: + # Older versions of numpy have _seed_seq + return self._seed_seq + def _seed_from_seq(self): raise NotImplementedError("Subclass must override") diff --git a/randomgen/distributions.pxd b/randomgen/distributions.pxd index 73bedc748..d49e277a7 100644 --- a/randomgen/distributions.pxd +++ b/randomgen/distributions.pxd @@ -1,4 +1,4 @@ -#cython: language_level=3 +# cython: language_level=3 from libc.stdint cimport ( int8_t, diff --git a/randomgen/dsfmt.pxd b/randomgen/dsfmt.pxd index 24d1bf47c..41f5fc3f3 100644 --- a/randomgen/dsfmt.pxd +++ b/randomgen/dsfmt.pxd @@ -1,4 +1,4 @@ -# cython: binding=True, language_level=3 + cimport numpy as np from libc.stdint cimport uint32_t, uint64_t diff --git a/randomgen/dsfmt.pyx b/randomgen/dsfmt.pyx index 36ffaeea7..9506c3d14 100644 --- a/randomgen/dsfmt.pyx +++ b/randomgen/dsfmt.pyx @@ -139,10 +139,7 @@ cdef class DSFMT(BitGenerator): self.rng_state.buffer_loc = DSFMT_N64 def _seed_from_seq(self): - try: - state = self.seed_seq.generate_state(2 * DSFMT_N64, np.uint32) - except AttributeError: - state = self._seed_seq.generate_state(2 * DSFMT_N64, np.uint32) + state = self._get_seed_seq().generate_state(2 * DSFMT_N64, np.uint32) dsfmt_init_by_array(self.rng_state.state, np.PyArray_DATA(state), diff --git a/randomgen/efiix64.pxd b/randomgen/efiix64.pxd index b9e968098..831d37dcd 100644 --- a/randomgen/efiix64.pxd +++ b/randomgen/efiix64.pxd @@ -1,4 +1,4 @@ -# cython: binding=True, language_level=3 + cimport numpy as np from libc.stdint cimport uint32_t, uint64_t diff --git a/randomgen/efiix64.pyx b/randomgen/efiix64.pyx index 127b7d0a3..92cae6df0 100644 --- a/randomgen/efiix64.pyx +++ b/randomgen/efiix64.pyx @@ -117,10 +117,7 @@ cdef class EFIIX64(BitGenerator): def _seed_from_seq(self): cdef uint64_t *state_arr - try: - state = self.seed_seq.generate_state(4, np.uint64) - except AttributeError: - state = self._seed_seq.generate_state(4, np.uint64) + state = self._get_seed_seq().generate_state(4, np.uint64) state_arr = np.PyArray_DATA(state) efiix64_seed(&self.rng_state, state_arr) self._reset_state_variables() diff --git a/randomgen/entropy.pyx b/randomgen/entropy.pyx index 41e88a3b5..999ff4d6a 100644 --- a/randomgen/entropy.pyx +++ b/randomgen/entropy.pyx @@ -1,5 +1,5 @@ #!python -# cython: binding=True, language_level=3 + cimport numpy as np import numpy as np diff --git a/randomgen/examples/cython/extending.pyx b/randomgen/examples/cython/extending.pyx index 4187d76cd..8ce6719d5 100644 --- a/randomgen/examples/cython/extending.pyx +++ b/randomgen/examples/cython/extending.pyx @@ -1,4 +1,4 @@ -#cython: language_level=3 +# cython: language_level=3 from cpython.pycapsule cimport PyCapsule_GetPointer, PyCapsule_IsValid from libc.stdint cimport uint32_t diff --git a/randomgen/examples/cython/extending_distributions.pyx b/randomgen/examples/cython/extending_distributions.pyx index 2d1ae7014..e6ea5fcd7 100644 --- a/randomgen/examples/cython/extending_distributions.pyx +++ b/randomgen/examples/cython/extending_distributions.pyx @@ -1,4 +1,4 @@ -#cython: language_level=3 +# cython: language_level=3 import numpy as np cimport cython diff --git a/randomgen/examples/cython/low_level.pyx b/randomgen/examples/cython/low_level.pyx index 281e6fb7c..d2c7bb5d1 100644 --- a/randomgen/examples/cython/low_level.pyx +++ b/randomgen/examples/cython/low_level.pyx @@ -1,4 +1,4 @@ -#cython: language_level=3, boundscheck=False, wraparound=False +# cython: language_level=3, boundscheck=False, wraparound=False from cpython.pycapsule cimport PyCapsule_GetPointer, PyCapsule_IsValid from libc.stdint cimport uint32_t diff --git a/randomgen/generator.pyx b/randomgen/generator.pyx index b5e3967cb..7c7bf5a31 100644 --- a/randomgen/generator.pyx +++ b/randomgen/generator.pyx @@ -1,5 +1,5 @@ #!python -#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True, language_level=3, binding=True +# cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True import warnings from libc.math cimport sqrt @@ -336,8 +336,8 @@ cdef class ExtendedGenerator: 0.47108547995356098 # random >>> type(randomgen.generator.random()) - >>> randomgen.generator.random((5,)) - array([ 0.30220482, 0.86820401, 0.1654503 , 0.11659149, 0.54323428]) # random + >>> randomgen.generator.random((3,)) + array([ 0.30220482, 0.86820401, 0.1654503]) # random Three-by-two array of random numbers from [-5, 0): @@ -628,7 +628,9 @@ cdef class ExtendedGenerator: relation, np.NPY_COMPLEX128, api.NPY_ARRAY_ALIGNED ) - if np.PyArray_NDIM(ogamma) == np.PyArray_NDIM(orelation) == np.PyArray_NDIM(oloc) == 0: + if (np.PyArray_NDIM(ogamma) == + np.PyArray_NDIM(orelation) == + np.PyArray_NDIM(oloc) == 0): floc_r = PyComplex_RealAsDouble(loc) floc_i = PyComplex_ImagAsDouble(loc) fgamma_r = PyComplex_RealAsDouble(gamma) @@ -727,7 +729,7 @@ cdef class ExtendedGenerator: self, int64_t df, np.npy_intp dim, np.npy_intp num, object n ): double_fill(&random_standard_normal_fill, &self._bitgen, None, self.lock, n) - return np.matmul(np.transpose(n,(0, 2, 1)), n) + return np.matmul(np.transpose(n, (0, 2, 1)), n) def standard_wishart(self, int64_t df, np.npy_intp dim, size=None, rescale=True): """ diff --git a/randomgen/hc128.pxd b/randomgen/hc128.pxd index dd0bf72e4..57add013c 100644 --- a/randomgen/hc128.pxd +++ b/randomgen/hc128.pxd @@ -1,4 +1,4 @@ -# cython: binding=True, language_level=3 + # coding=utf-8 cimport numpy as np from libc.stdint cimport uint32_t, uint64_t diff --git a/randomgen/hc128.pyx b/randomgen/hc128.pyx index 23f4fe0d0..b14ec794d 100644 --- a/randomgen/hc128.pyx +++ b/randomgen/hc128.pyx @@ -122,10 +122,7 @@ cdef class HC128(BitGenerator): self._bitgen.next_raw = &hc128_uint64 def _seed_from_seq(self): - try: - state = self.seed_seq.generate_state(4, np.uint64) - except AttributeError: - state = self._seed_seq.generate_state(4, np.uint64) + state = self._get_seed_seq().generate_state(4, np.uint64) self.seed(key=state) def seed(self, seed=None, key=None): diff --git a/randomgen/jsf.pxd b/randomgen/jsf.pxd index 79417a333..522d94a3d 100644 --- a/randomgen/jsf.pxd +++ b/randomgen/jsf.pxd @@ -1,4 +1,4 @@ -# cython: binding=True, language_level=3 + cimport numpy as np from libc.stdint cimport uint32_t, uint64_t diff --git a/randomgen/jsf.pyx b/randomgen/jsf.pyx index d2b1274d8..4576efcdd 100644 --- a/randomgen/jsf.pyx +++ b/randomgen/jsf.pyx @@ -231,10 +231,7 @@ cdef class JSF(BitGenerator): def _seed_from_seq(self): dtype = np.uint64 if self.size == 64 else np.uint32 - try: - state = self.seed_seq.generate_state(self.seed_size, dtype) - except AttributeError: - state = self._seed_seq.generate_state(self.seed_size, dtype) + state = self._get_seed_seq().generate_state(self.seed_size, dtype) if self.size == 64: jsf64_seed(&self.rng_state, np.PyArray_DATA(state), diff --git a/randomgen/legacy/bounded_integers.pyx.in b/randomgen/legacy/bounded_integers.pyx.in index 1286a11c4..9b73f2f03 100644 --- a/randomgen/legacy/bounded_integers.pyx.in +++ b/randomgen/legacy/bounded_integers.pyx.in @@ -1,5 +1,5 @@ #!python -#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True +# cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True import numpy as np diff --git a/randomgen/legacy/distributions.pxd b/randomgen/legacy/distributions.pxd index a1cc342cf..d37fe00e2 100644 --- a/randomgen/legacy/distributions.pxd +++ b/randomgen/legacy/distributions.pxd @@ -1,4 +1,4 @@ -#cython: language_level=3 +# cython: language_level=3 from libc.stdint cimport ( int8_t, diff --git a/randomgen/lxm.pxd b/randomgen/lxm.pxd index 4a4a7d1cd..bb3217aae 100644 --- a/randomgen/lxm.pxd +++ b/randomgen/lxm.pxd @@ -1,4 +1,4 @@ -# cython: binding=True, language_level=3 + cimport numpy as np from libc.stdint cimport uint32_t, uint64_t diff --git a/randomgen/lxm.pyx b/randomgen/lxm.pyx index 2396445a6..f92787717 100644 --- a/randomgen/lxm.pyx +++ b/randomgen/lxm.pyx @@ -144,15 +144,10 @@ cdef class LXM(BitGenerator): def _seed_from_seq(self): cdef int i cdef uint64_t bits = 0 - cdef uint64_t *state_arr # Protect against negligible prob of all 0 in Xorshift while bits == 0: - try: - state = self.seed_seq.generate_state(5, np.uint64) - except: - state = self._seed_seq.generate_state(5, np.uint64) - state_arr = np.PyArray_DATA(state) + state = self._get_seed_seq().generate_state(5, np.uint64) for i in range(4): self.rng_state.x[i] = state[i] bits |= state[i] diff --git a/randomgen/mt19937.pyx b/randomgen/mt19937.pyx index 86a95eb7c..2f14d4d34 100644 --- a/randomgen/mt19937.pyx +++ b/randomgen/mt19937.pyx @@ -1,9 +1,6 @@ #!python -#cython: binding=True # coding=utf-8 -import operator - import numpy as np from randomgen._deprecated_value import _DeprecatedValue @@ -133,20 +130,14 @@ cdef class MT19937(BitGenerator): return "sequence", "numpy" def _seed_from_seq(self): - try: - state = self.seed_seq.generate_state(RK_STATE_LEN, np.uint32) - except AttributeError: - state = self._seed_seq.generate_state(RK_STATE_LEN, np.uint32) + state = self._get_seed_seq().generate_state(RK_STATE_LEN, np.uint32) mt19937_init_by_array(&self.rng_state, np.PyArray_DATA(state), RK_STATE_LEN) def _seed_from_seq_numpy_compat(self, inc=None): # MSB is 1; assuring non-zero initial array - try: - val = self.seed_seq.generate_state(RK_STATE_LEN, np.uint32) - except AttributeError: - val = self._seed_seq.generate_state(RK_STATE_LEN, np.uint32) + val = self._get_seed_seq().generate_state(RK_STATE_LEN, np.uint32) # MSB is 1; assuring non-zero initial array self.rng_state.key[0] = 0x80000000UL for i in range(1, RK_STATE_LEN): diff --git a/randomgen/mt64.pxd b/randomgen/mt64.pxd index 791b7bd38..44a46e210 100644 --- a/randomgen/mt64.pxd +++ b/randomgen/mt64.pxd @@ -1,4 +1,4 @@ -# cython: binding=True, language_level=3 + cimport numpy as np from libc.stdint cimport uint32_t, uint64_t diff --git a/randomgen/mt64.pyx b/randomgen/mt64.pyx index 84727e2bb..2dbaf5a59 100644 --- a/randomgen/mt64.pyx +++ b/randomgen/mt64.pyx @@ -1,8 +1,6 @@ #!python # coding=utf-8 -import operator - import numpy as np from randomgen._deprecated_value import _DeprecatedValue @@ -108,10 +106,7 @@ cdef class MT64(BitGenerator): self.rng_state.uinteger = 0 def _seed_from_seq(self): - try: - state = self.seed_seq.generate_state(312, np.uint64) - except AttributeError: - state = self._seed_seq.generate_state(312, np.uint64) + state = self._get_seed_seq().generate_state(312, np.uint64) mt64_init_by_array(&self.rng_state, np.PyArray_DATA(state), 312) diff --git a/randomgen/mtrand.pyx b/randomgen/mtrand.pyx index 96a927331..943c450ad 100644 --- a/randomgen/mtrand.pyx +++ b/randomgen/mtrand.pyx @@ -1,5 +1,5 @@ #!python -#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True, language_level=3 +# cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True from typing import Any, Callable @@ -22,7 +22,7 @@ cdef class RandomState: """ -def _removed(name: str) -> Callable[[Any,...],None]: +def _removed(name: str) -> Callable[[Any, ...], None]: def f(*args, **kwargs): raise NotImplementedError( f"{name} has been removed. Use NumPy's Generator" @@ -79,7 +79,7 @@ wald = _removed("wald") weibull = _removed("weibull") zipf = _removed("zipf") sample = _removed("sample") -ranf = _removed("ranf") +ranf = _removed("ranf") __all__ = [ diff --git a/randomgen/pcg32.pyx b/randomgen/pcg32.pyx index 506b19cab..a6c3cfd1c 100644 --- a/randomgen/pcg32.pyx +++ b/randomgen/pcg32.pyx @@ -1,5 +1,4 @@ #!python -#cython: binding=True import numpy as np @@ -113,18 +112,8 @@ cdef class PCG32(BitGenerator): def _seed_from_seq(self, inc=None): cdef uint64_t _inc - if inc is None: - try: - state = self.seed_seq.generate_state(2, np.uint64) - except AttributeError: - state = self._seed_seq.generate_state(2, np.uint64) - _inc = state[1] - else: - try: - state = self.seed_seq.generate_state(1, np.uint64) - except AttributeError: - state = self._seed_seq.generate_state(1, np.uint64) - _inc = inc + state = self._get_seed_seq().generate_state(2, np.uint64) + _inc = state[1] if inc is None else inc pcg32_set_seed(&self.rng_state, state[0], _inc) def seed(self, seed=None, inc=None): diff --git a/randomgen/pcg64.pyx b/randomgen/pcg64.pyx index 75e19dc8c..3bd70b6cd 100644 --- a/randomgen/pcg64.pyx +++ b/randomgen/pcg64.pyx @@ -1,5 +1,4 @@ #!python -#cython: binding=True import numpy as np @@ -40,7 +39,7 @@ cdef double lcg128mix_double(void* st) noexcept nogil: cdef class PCG64(BitGenerator): - """ + r""" PCG64(seed=None, inc=0, *, variant="xsl-rr", numpy_seed=False, mode="sequence") Container for the PCG-64 pseudo-random number generator. @@ -155,26 +154,41 @@ cdef class PCG64(BitGenerator): .. [2] O'Neill, Melissa E. "PCG: A Family of Simple Fast Space-Efficient Statistically Good Algorithms for Random Number Generation" """ - def __init__(self, seed=None, inc=None, *, variant="xsl-rr", numpy_seed=False, mode=_DeprecatedValue): + def __init__( + self, + seed=None, + inc=None, + *, + variant="xsl-rr", + numpy_seed=False, + mode=_DeprecatedValue + ): BitGenerator.__init__(self, seed, mode=mode, numpy_seed=numpy_seed) - self.rng_state.pcg_state = PyArray_malloc_aligned(sizeof(pcg64_random_t)) + self.rng_state.pcg_state = PyArray_malloc_aligned( + sizeof(pcg64_random_t) + ) inc = None if seed is None else inc variant = "dxsm" if variant is None else variant - if not (isinstance(variant, (str,int, np.integer))): + if not (isinstance(variant, (str, int, np.integer))): raise TypeError("variant must be a string") orig_variant = variant = str(variant) variant = variant.lower().replace("-", "") - if variant not in ("xslrr", "1.0", "1", "cmdxsm", "dxsm", "dxsm128", "2.0", "2"): + if variant not in ( + "xslrr", "1.0", "1", "cmdxsm", "dxsm", "dxsm128", "2.0", "2" + ): raise ValueError(f"variant {orig_variant} is not known.") if self.mode == "numpy": if orig_variant != "xsl-rr": raise ValueError( - f"variant must be 'xsl-rr' when using numpy-matching seeding. Got '{orig_variant}'" + "variant must be 'xsl-rr' when using numpy-matching seeding. " + f"Got '{orig_variant}'." ) if inc is not None: - raise ValueError("inc much be none when using numpy-matching seeding.") + raise ValueError( + "inc much be none when using numpy-matching seeding." + ) self.variant = variant self._setup_rng_state() @@ -225,10 +239,7 @@ cdef class PCG64(BitGenerator): def _seed_from_seq(self, inc=0): size = 4 if inc is None else 2 - try: - state = self.seed_seq.generate_state(size, np.uint64) - except AttributeError: - state = self._seed_seq.generate_state(size, np.uint64) + state = self._get_seed_seq().generate_state(size, np.uint64) if inc is None: _inc = state[2:] else: @@ -317,7 +328,7 @@ cdef class PCG64(BitGenerator): @state.setter def state(self, value): cdef np.ndarray state_vec - cdef int has_uint32, use_dxsm + cdef int has_uint32 cdef uint32_t uinteger if not isinstance(value, dict): raise TypeError("state must be a dict") @@ -383,7 +394,9 @@ cdef class PCG64(BitGenerator): cdef np.ndarray d = np.empty(2, dtype=np.uint64) d[0] = delta // 2**64 d[1] = delta % 2**64 - pcg64_advance(&self.rng_state, np.PyArray_DATA(d), self.cheap_multiplier) + pcg64_advance( + &self.rng_state, np.PyArray_DATA(d), self.cheap_multiplier + ) self._reset_state_variables() return self @@ -469,14 +482,16 @@ cdef class PCG64(BitGenerator): cdef PCG64 bit_generator kwargs = {"numpy_seed": True} if self.mode == "numpy" else {} - bit_generator = self.__class__(seed=self._copy_seed(), variant=self.variant, **kwargs) + bit_generator = self.__class__( + seed=self._copy_seed(), variant=self.variant, **kwargs + ) bit_generator.state = self.state bit_generator.jump_inplace(iter) return bit_generator cdef class LCG128Mix(BitGenerator): - """ + r""" LCG128Mix(seed=None, inc=None, *, multiplier=47026247687942121848144207491837523525, output="xsl-rr", dxsm_multiplier=15750249268501108917, post=True) Customizable 128-bit LCG bit generator with output mixing @@ -626,7 +641,9 @@ cdef class LCG128Mix(BitGenerator): self._inv_output_lookup = {v: k for k, v in self._output_lookup.items()} self._cfunc = None BitGenerator.__init__(self, seed) - self.rng_state.pcg_state = PyArray_malloc_aligned(sizeof(lcg128mix_random_t)) + self.rng_state.pcg_state = PyArray_malloc_aligned( + sizeof(lcg128mix_random_t) + ) if hasattr(output, "argtypes") and hasattr(output, "restype"): from ctypes import c_ulonglong if output.argtypes != (c_ulonglong, c_ulonglong): @@ -659,9 +676,13 @@ cdef class LCG128Mix(BitGenerator): else: import ctypes self.output_function = -1 - self.output_function_address = ctypes.cast(self._cfunc, ctypes.c_void_p).value + self.output_function_address = ctypes.cast( + self._cfunc, ctypes.c_void_p + ).value self.rng_state.pcg_state.output_idx = -1 - self.rng_state.pcg_state.output_func = self.output_function_address + self.rng_state.pcg_state.output_func = ( + self.output_function_address + ) self._bitgen.state = &self.rng_state self._bitgen.next_uint64 = &lcg128mix_uint64 @@ -702,10 +723,7 @@ cdef class LCG128Mix(BitGenerator): cdef np.ndarray mult_vec, state, _inc size = 4 if inc is None else 2 - try: - state = np.array(self.seed_seq.generate_state(2, np.uint64)) - except AttributeError: - state = np.array(self._seed_seq.generate_state(2, np.uint64)) + state = np.array(self._get_seed_seq().generate_state(size, np.uint64)) mult_vec = np.empty(2, dtype=np.uint64) mult_vec[0] = self.multiplier >> 64 mult_vec[1] = self.multiplier & 0xFFFFFFFFFFFFFFFF @@ -716,9 +734,10 @@ cdef class LCG128Mix(BitGenerator): _inc[0] = int(inc) // 2**64 _inc[1] = int(inc) % 2**64 lcg128mix_seed(self.rng_state.pcg_state, - np.PyArray_DATA(state), - np.PyArray_DATA(_inc), - np.PyArray_DATA(mult_vec)) + np.PyArray_DATA(state), + np.PyArray_DATA(_inc), + np.PyArray_DATA(mult_vec) + ) self._reset_state_variables() def seed(self, seed=None, inc=None): @@ -759,7 +778,7 @@ cdef class LCG128Mix(BitGenerator): state of the PRNG """ cdef np.ndarray state_vec, inc_vec, mult_vec - cdef int has_uint32, post, output_func + cdef int has_uint32, post cdef uint64_t dxsm_multiplier cdef uint32_t uinteger @@ -768,14 +787,16 @@ cdef class LCG128Mix(BitGenerator): inc_vec = np.empty(2, dtype=np.uint64) mult_vec = np.empty(2, dtype=np.uint64) lcg128mix_get_state(self.rng_state.pcg_state, - np.PyArray_DATA(state_vec), - np.PyArray_DATA(inc_vec), - np.PyArray_DATA(mult_vec), - ) + np.PyArray_DATA(state_vec), + np.PyArray_DATA(inc_vec), + np.PyArray_DATA(mult_vec) + ) dxsm_multiplier = self.rng_state.pcg_state.dxsm_multiplier post = self.rng_state.pcg_state.post if self._cfunc is None: - output_function = self._inv_output_lookup[self.rng_state.pcg_state.output_idx] + output_function = self._inv_output_lookup[ + self.rng_state.pcg_state.output_idx + ] else: output_function = self._cfunc has_uint32 = self.rng_state.has_uint32 @@ -788,8 +809,8 @@ cdef class LCG128Mix(BitGenerator): "state": {"state": state, "inc": inc, "multiplier": mult, - "dxsm_multiplier":dxsm_multiplier, - "post":bool(post), + "dxsm_multiplier": dxsm_multiplier, + "post": bool(post), "output_func": output_function, }, "has_uint32": has_uint32, @@ -821,9 +842,10 @@ cdef class LCG128Mix(BitGenerator): # Default False for backward compat lcg128mix_set_state(self.rng_state.pcg_state, - np.PyArray_DATA(state_vec), - np.PyArray_DATA(inc_vec), - np.PyArray_DATA(mult_vec)) + np.PyArray_DATA(state_vec), + np.PyArray_DATA(inc_vec), + np.PyArray_DATA(mult_vec) + ) self.rng_state.has_uint32 = has_uint32 self.rng_state.uinteger = uinteger self.rng_state.pcg_state.dxsm_multiplier = value["state"]["dxsm_multiplier"] @@ -836,9 +858,13 @@ cdef class LCG128Mix(BitGenerator): self._cfunc = output_func self.output_function = -1 - self.output_function_address = ctypes.cast(self._cfunc, ctypes.c_void_p).value + self.output_function_address = ( + ctypes.cast(self._cfunc, ctypes.c_void_p).value + ) self.rng_state.pcg_state.output_idx = -1 - self.rng_state.pcg_state.output_func = self.output_function_address + self.rng_state.pcg_state.output_func = ( + self.output_function_address + ) def advance(self, delta): """ @@ -940,7 +966,7 @@ cdef class LCG128Mix(BitGenerator): cdef class PCG64DXSM(PCG64): - """ + r""" PCG64DXSM(seed=None, inc=None) Container for the PCG-64 updated with a 64-bit mult using DXSM output func. @@ -1073,7 +1099,7 @@ cdef class PCG64DXSM(PCG64): @state.setter def state(self, value): cdef np.ndarray state_vec - cdef int has_uint32, use_dxsm + cdef int has_uint32 cdef uint32_t uinteger if not isinstance(value, dict): raise TypeError("state must be a dict") diff --git a/randomgen/philox.pyx b/randomgen/philox.pyx index 9578659dc..c70d58432 100644 --- a/randomgen/philox.pyx +++ b/randomgen/philox.pyx @@ -1,5 +1,4 @@ #!python -#cython: binding=True import numpy as np @@ -233,10 +232,7 @@ cdef class Philox(BitGenerator): def _seed_from_seq(self, counter=None): seed_seq_size = max(self.n * self.w // 128, 1) - try: - state = self.seed_seq.generate_state(seed_seq_size, np.uint64) - except AttributeError: - state = self._seed_seq.generate_state(seed_seq_size, np.uint64) + state = self._get_seed_seq().generate_state(seed_seq_size, np.uint64) # Special case 2x32 which needs max 32 bits if self.n == 2 and self.w == 32: state %= np.uint64(2**32) @@ -248,7 +244,6 @@ cdef class Philox(BitGenerator): raise ValueError("n must be 4 and w must br 64 when using mode='numpy'") return self._seed_from_seq() - def seed(self, seed=None, counter=None, key=None): """ seed(seed=None, counter=None, key=None) @@ -297,7 +292,6 @@ cdef class Philox(BitGenerator): key = object_to_int(key, self.n // 2 * self.w, "key") counter = object_to_int(counter, self.n * self.w, "counter") - cdef int u32_size = (self.n // 2) * (self.w // 32) _seed = int_to_array(key, "key", self.n // 2 * self.w, self.w) dtype = np.uint64 if self.w==64 else np.uint32 _seed = view_little_endian(_seed, dtype) @@ -548,16 +542,23 @@ cdef class Philox(BitGenerator): cdef np.ndarray delta_a delta_a = int_to_array(delta, "step", (self.n + 1) * self.w, self.w) - orig_buffer_pos = self.rng_state.buffer_pos if self.n == 2 and self.w == 32: - philox2x32_advance(&self.rng_state, np.PyArray_DATA(delta_a), not counter) + philox2x32_advance( + &self.rng_state, np.PyArray_DATA(delta_a), not counter + ) elif self.n == 4 and self.w == 32: - philox4x32_advance(&self.rng_state, np.PyArray_DATA(delta_a), not counter) + philox4x32_advance( + &self.rng_state, np.PyArray_DATA(delta_a), not counter + ) elif self.n == 2 and self.w == 64: - philox2x64_advance(&self.rng_state, np.PyArray_DATA(delta_a), not counter) + philox2x64_advance( + &self.rng_state, np.PyArray_DATA(delta_a), not counter + ) else: # self.n == 4 and self.w == 64: - philox4x64_advance(&self.rng_state, np.PyArray_DATA(delta_a), not counter) + philox4x64_advance( + &self.rng_state, np.PyArray_DATA(delta_a), not counter + ) # Reset uint32 so if needed is drawn from the advanced state self.rng_state.uinteger = 0 self.rng_state.has_uint32 = 0 diff --git a/randomgen/rdrand.pyx b/randomgen/rdrand.pyx index 9fd602471..f27f5a764 100644 --- a/randomgen/rdrand.pyx +++ b/randomgen/rdrand.pyx @@ -1,5 +1,4 @@ #!python -#cython: binding=True import numpy as np @@ -27,7 +26,7 @@ increase the number of retries to slow down the generation on contested CPUs. cdef uint64_t rdrand_uint64(void* st) noexcept nogil: cdef PyObject *err cdef rdrand_state *state - cdef int status, prev_status + cdef int status cdef uint64_t val state = st status = 1 @@ -83,10 +82,6 @@ cdef class RaisingLock: return self.lock.acquire(blocking, timeout) def release(self): - cdef PyObject *typ - cdef PyObject *val - cdef PyObject *tb - self.err = PyErr_Occurred() if self.err != NULL: try: @@ -241,8 +236,8 @@ cdef class RDRAND(BitGenerator): Available at: [Accessed 10 July 2020]. - .. [2] Intel. 2020. IntelĀ® Digital Random Number Generator (DRNG) Software Implementation. - (online) Available at: + .. [2] Intel. 2020. IntelĀ® Digital Random Number Generator (DRNG) + Software Implementation. (online) Available at: [Accessed 10 July 2020]. """ @@ -255,7 +250,9 @@ cdef class RDRAND(BitGenerator): BitGenerator.__init__(self, seed) self.lock = RaisingLock() if not rdrand_capable(): - raise RuntimeError("The RDRAND instruction is not available") # pragma: no cover + raise RuntimeError( # pragma: no cover + "The RDRAND instruction is not available" # pragma: no cover + ) # pragma: no cover self.rng_state.status = 1 if retries < 0: raise ValueError("retries must be a non-negative integer.") @@ -275,25 +272,25 @@ cdef class RDRAND(BitGenerator): def _seed_from_seq(self): pass - + @property def success(self): """ Gets the flag indicating that all calls to RDRAND succeeded - + Returns ------- bool True indicates success, false indicates failure - + Notes ----- Once status is set to 0, it remains 0 unless manually reset. This happens to ensure that it is possible to manually verify - the status flag. + the status flag. """ return bool(self.rng_state.status) - + def _reset(self): """ Not part of the public API @@ -315,7 +312,6 @@ cdef class RDRAND(BitGenerator): """ self._seed_seq = seed_seq - def seed(self, seed=None): """ seed(seed=None) diff --git a/randomgen/romu.pyx b/randomgen/romu.pyx index 2e02dc078..9ca65f971 100644 --- a/randomgen/romu.pyx +++ b/randomgen/romu.pyx @@ -1,5 +1,4 @@ #!python -#cython: binding=True import numpy as np @@ -128,10 +127,7 @@ cdef class Romu(BitGenerator): self._setup_bitgen() - try: - state = self.seed_seq.generate_state(4, np.uint64) - except: - state = self._seed_seq.generate_state(4, np.uint64) + state = self._get_seed_seq().generate_state(4, np.uint64) if (state == 0).all(): # Ensure at least one non-zero, exceedingly unlikely state[3] |= np.uint64(0x1) @@ -174,9 +170,9 @@ cdef class Romu(BitGenerator): """ return {"bit_generator": fully_qualified_name(self), "state": {"w": self.rng_state.w, - "x":self.rng_state.x, - "y":self.rng_state.y, - "z":self.rng_state.z, + "x": self.rng_state.x, + "y": self.rng_state.y, + "z": self.rng_state.z, "variant": self.variant }, "has_uint32": self.rng_state.has_uint32, diff --git a/randomgen/sfc.pyx b/randomgen/sfc.pyx index 00baf3340..e16d8eb6f 100644 --- a/randomgen/sfc.pyx +++ b/randomgen/sfc.pyx @@ -1,5 +1,4 @@ #!python -#cython: binding=True import warnings @@ -129,7 +128,6 @@ cdef class SFC64(BitGenerator): self.k = k self.seed(seed) - self._bitgen.state = &self.rng_state self._bitgen.next_uint64 = &sfc_uint64 self._bitgen.next_uint32 = &sfc_uint32 @@ -144,15 +142,12 @@ cdef class SFC64(BitGenerator): return "sequence", "numpy" def _seed_from_seq(self): - cdef int i, loc, cnt + cdef int loc, cnt cdef uint64_t *state_arr cdef uint64_t k, w cnt = 3 + (self.k is None) + (self.w is None) - try: - state = self.seed_seq.generate_state(cnt, np.uint64) - except: - state = self._seed_seq.generate_state(cnt, np.uint64) + state = self._get_seed_seq().generate_state(cnt, np.uint64) state_arr = np.PyArray_DATA(state) w = self.w if self.w is not None else state[3] loc = 3 if self.w is not None else 4 @@ -253,7 +248,6 @@ cdef class SFC64(BitGenerator): cdef int8_t *bits_arr cdef int8_t nonzero_bits cdef int _min_bits - cdef bint inverse cdef set values = set() min_bits = min_bits if min_bits is not None else max_bits @@ -281,7 +275,6 @@ cdef class SFC64(BitGenerator): ) _min_bits = min_bits nbits = max_bits - _min_bits + 1 - table = np.zeros((nbits, 2), dtype=np.uint64) bits = np.arange(_min_bits, max_bits+1, dtype=np.int8) bits_arr = np.PyArray_DATA(bits) cum_count = np.zeros(nbits, dtype=np.uint64) @@ -350,10 +343,10 @@ cdef class SFC64(BitGenerator): """ return {"bit_generator": fully_qualified_name(self), "state": {"a": self.rng_state.a, - "b":self.rng_state.b, - "c":self.rng_state.c, - "w":self.rng_state.w, - "k":self.rng_state.k + "b": self.rng_state.b, + "c": self.rng_state.c, + "w": self.rng_state.w, + "k": self.rng_state.k }, "has_uint32": self.rng_state.has_uint32, "uinteger": self.rng_state.uinteger} diff --git a/randomgen/sfmt.pyx b/randomgen/sfmt.pyx index 902d314ce..300c4fcc4 100644 --- a/randomgen/sfmt.pyx +++ b/randomgen/sfmt.pyx @@ -1,5 +1,4 @@ #!python -#cython: binding=True import numpy as np @@ -117,7 +116,9 @@ cdef class SFMT(BitGenerator): def __init__(self, seed=None, *, mode=_DeprecatedValue): BitGenerator.__init__(self, seed, mode=mode) self.rng_state.state = PyArray_malloc_aligned(sizeof(sfmt_t)) - self.rng_state.buffered_uint64 = PyArray_calloc_aligned(SFMT_N64, sizeof(uint64_t)) + self.rng_state.buffered_uint64 = PyArray_calloc_aligned( + SFMT_N64, sizeof(uint64_t) + ) self.rng_state.buffer_loc = SFMT_N64 self.seed(seed) @@ -139,10 +140,7 @@ cdef class SFMT(BitGenerator): self.rng_state.uinteger = 0 def _seed_from_seq(self): - try: - state = self.seed_seq.generate_state(2 * SFMT_N64, np.uint32) - except AttributeError: - state = self._seed_seq.generate_state(2 * SFMT_N64, np.uint32) + state = self._get_seed_seq().generate_state(2 * SFMT_N64, np.uint32) sfmt_init_by_array(self.rng_state.state, np.PyArray_DATA(state), 2 * SFMT_N64) diff --git a/randomgen/speck128.pyx b/randomgen/speck128.pyx index 32c61c06e..95efd0a33 100644 --- a/randomgen/speck128.pyx +++ b/randomgen/speck128.pyx @@ -1,5 +1,4 @@ #!python -#cython: binding=True import numpy as np @@ -139,10 +138,20 @@ cdef class SPECK128(BitGenerator): National Security Agency. January 15, 2019. from https://nsacyber.github.io/simon-speck/implementations/ImplementationGuide1.1.pdf """ - def __init__(self, seed=None, *, counter=None, key=None, rounds=SPECK_MAX_ROUNDS, mode=_DeprecatedValue): + def __init__( + self, + seed=None, + *, + counter=None, + key=None, + rounds=SPECK_MAX_ROUNDS, + mode=_DeprecatedValue + ): BitGenerator.__init__(self, seed, mode=mode) # Calloc since ctr needs to be 0 - self.rng_state = PyArray_calloc_aligned(sizeof(speck_state_t), 1) + self.rng_state = PyArray_calloc_aligned( + sizeof(speck_state_t), 1 + ) if (rounds <= 0) or rounds > SPECK_MAX_ROUNDS or int(rounds) != rounds: raise ValueError("rounds must be an integer in [1, 34]") self.rng_state.rounds = int(rounds) @@ -163,10 +172,7 @@ cdef class SPECK128(BitGenerator): self.rng_state.uinteger = 0 def _seed_from_seq(self, counter=None): - try: - state = self.seed_seq.generate_state(4, np.uint64) - except AttributeError: - state = self._seed_seq.generate_state(4, np.uint64) + state = self._get_seed_seq().generate_state(4, np.uint64) self.seed(key=state, counter=counter) self._reset_state_variables() @@ -263,7 +269,7 @@ cdef class SPECK128(BitGenerator): Dictionary containing the information required to describe the state of the PRNG """ - cdef int i, j + cdef int i cdef uint8_t *arr8 cdef uint64_t *arr diff --git a/randomgen/squares.pxd b/randomgen/squares.pxd index f706f99af..f1c03573c 100644 --- a/randomgen/squares.pxd +++ b/randomgen/squares.pxd @@ -1,4 +1,4 @@ -# cython: binding=True, language_level=3 + cimport numpy as np from libc.stdint cimport uint32_t, uint64_t diff --git a/randomgen/squares.pyx b/randomgen/squares.pyx index 8afc717a2..1f0ef88eb 100644 --- a/randomgen/squares.pyx +++ b/randomgen/squares.pyx @@ -1,7 +1,5 @@ #!python -# cython: binding=True, language_level=3, boundscheck=False, wraparound=False, nonecheck=False, cdivision=True -import os - +# cython: boundscheck=False, wraparound=False, nonecheck=False, cdivision=True from numpy.random.bit_generator import ISeedSequence from libc.stdint cimport intptr_t, uint8_t, uint32_t, uint64_t @@ -26,7 +24,7 @@ cdef class _TestSeninal: return self.testing def set_testing(self, bint value): - self.testing = value + self.testing = value _test_sentinal = _TestSeninal() @@ -40,9 +38,11 @@ cdef void _reset_words(): for i in range(16): WORDS[i] = i + def _get_words(): return np.asarray(WORDS) + cdef uint64_t squares_uint64(void* st) noexcept nogil: return squares_next64(st) @@ -75,7 +75,9 @@ cdef class _SequenceSampler: def __init__(self, seed_seq: SeedSequence, int initial_draw=10): self.seed_seq = seed_seq self.randoms_drawm = initial_draw - self.random_well = self.seed_seq.generate_state(self.randoms_drawm, dtype=np.uint64) + self.random_well = self.seed_seq.generate_state( + self.randoms_drawm, dtype=np.uint64 + ) self.bit_well = 0 self.bit_well_loc = 0 self.index = 0 @@ -88,7 +90,9 @@ cdef class _SequenceSampler: self.index += 1 if self.index > self.randoms_drawm: self.randoms_drawm *= 2 - self.random_well = self.seed_seq.generate_state(self.randoms_drawm, dtype=np.uint64) + self.random_well = self.seed_seq.generate_state( + self.randoms_drawm, dtype=np.uint64 + ) cdef uint64_t gen_bits(self, int nbits): """Generate a fixed number of bits from the bit well""" @@ -147,10 +151,9 @@ cdef uint64_t generate_key(_SequenceSampler seq_sampler): """ The core key generation implementation """ - cdef intptr_t pos - cdef uint64_t out, first, i + cdef uint64_t out, i cdef uint8_t[::1] tmp = WORDS - cdef uint8_t last_value, next_value, k, old + cdef uint8_t last_value, next_value, old out = 0 _reset_words() @@ -158,7 +161,7 @@ cdef uint64_t generate_key(_SequenceSampler seq_sampler): if not (tmp[0] & 0x1): old = tmp[0] tmp[0] += 1 - for i in range(1,8): + for i in range(1, 8): if tmp[i] == tmp[0]: tmp[i] = old for i in range(8): @@ -185,7 +188,7 @@ cdef uint64_t generate_key(_SequenceSampler seq_sampler): def generate_keys(seed=None, intptr_t n=1, bint unique=False): - """ + r""" generate_keys(seed=None, n=1, unique=False) Pre-generate keys for use with Squares @@ -265,7 +268,7 @@ def generate_keys(seed=None, intptr_t n=1, bint unique=False): """ cdef intptr_t i, nunique, iter, start = 0 cdef uint64_t[::1] out, tmp, index - cdef np.ndarray out_arr, tmp_arr, index_arr + cdef np.ndarray out_arr, index_arr cdef _TestSeninal _internal_senintal = _test_sentinal cdef _SequenceSampler seq_sampler cdef bint incomplete = True @@ -291,7 +294,6 @@ def generate_keys(seed=None, intptr_t n=1, bint unique=False): index = index_arr = index_arr.astype(np.uint64) nunique = index_arr.shape[0] if iter < 2 and _internal_senintal.testing: - orig = nunique nunique = nunique - max(min(10, nunique // 2), 1) if nunique == n: @@ -409,7 +411,9 @@ cdef class Squares(BitGenerator): ``counter`` values. >>> from randomgen import SeedSequence - >>> bit_gens = [Squares(SeedSequence(entropy), counter=1_000_000_000 * i) for i in range(1024)] + >>> bit_gens = [] + >>> for i in range(1024): + ... bit_gens.append(Squares(SeedSequence(entropy), counter=1_000_000_000 * i)) See also -------- @@ -465,12 +469,7 @@ cdef class Squares(BitGenerator): return val def _seed_from_seq(self, uint64_t counter=0): - cdef uint64_t key - - try: - seed_seq = self.seed_seq - except AttributeError: - seed_seq = self._seed_seq + seed_seq = self._get_seed_seq() self.rng_state.key = generate_key(_SequenceSampler(seed_seq)) self.rng_state.counter = counter diff --git a/randomgen/src/tyche/tyche-gen-test-data.cpp b/randomgen/src/tyche/tyche-gen-test-data.cpp index 66e958141..506af6cbd 100644 --- a/randomgen/src/tyche/tyche-gen-test-data.cpp +++ b/randomgen/src/tyche/tyche-gen-test-data.cpp @@ -27,7 +27,7 @@ int main() { clock_t t1, t2; uint64_t store[N]; uint64_t seedval = 15793235383387715774ULL; - uint32_t idx = 2968811710UL; + uint32_t idx = 745650761UL; auto tyche = openrand::Tyche(seedval, idx); std::ofstream ofile; ofile.open (OUTPUT_FILE "-testset-1.csv"); @@ -40,7 +40,7 @@ int main() { cout << std::endl; seedval = 5778446405158232650ULL; - idx = 3575046730UL; + idx = 3393510519UL; tyche = openrand::Tyche(seedval, idx); ofile.open (OUTPUT_FILE "-testset-2.csv"); ofile << "seed, " << 0xDEADBEAF <np.PyArray_DATA(delta_a), not counter) + threefry2x32_advance( + &self.rng_state, np.PyArray_DATA(delta_a), not counter + ) elif self.n == 4 and self.w == 32: - threefry4x32_advance(&self.rng_state, np.PyArray_DATA(delta_a), not counter) + threefry4x32_advance( + &self.rng_state, np.PyArray_DATA(delta_a), not counter + ) elif self.n == 2 and self.w == 64: - threefry2x64_advance(&self.rng_state, np.PyArray_DATA(delta_a), not counter) + threefry2x64_advance( + &self.rng_state, np.PyArray_DATA(delta_a), not counter + ) else: # self.n == 4 and self.w == 64: - threefry4x64_advance(&self.rng_state, np.PyArray_DATA(delta_a), not counter) + threefry4x64_advance( + &self.rng_state, np.PyArray_DATA(delta_a), not counter + ) # Reset uint32 so if needed is drawn from the advanced state self.rng_state.uinteger = 0 self.rng_state.has_uint32 = 0 diff --git a/randomgen/tyche.pxd b/randomgen/tyche.pxd index b5c220898..f1ec7edb0 100644 --- a/randomgen/tyche.pxd +++ b/randomgen/tyche.pxd @@ -1,4 +1,4 @@ -# cython: binding=True, language_level=3 + cimport numpy as np from libc.stdint cimport uint32_t, uint64_t diff --git a/randomgen/tyche.pyx b/randomgen/tyche.pyx index c30b52098..078f367fd 100644 --- a/randomgen/tyche.pyx +++ b/randomgen/tyche.pyx @@ -126,18 +126,14 @@ cdef class Tyche(BitGenerator): self._bitgen.next_double = &tyche_openrand_double self._bitgen.next_raw = &tyche_openrand_uint64 - def _seed_from_seq(self, idx=None): cdef uint64_t state cdef uint32_t _idx - try: - seed_seq = self.seed_seq - except AttributeError: - seed_seq = self._seed_seq - state = seed_seq.generate_state(1, np.uint64)[0] + full_state = self._get_seed_seq().generate_state(3, np.uint32) + state = full_state[:2].view(np.uint64)[0] if idx is None: - _idx = seed_seq.generate_state(1, np.uint32)[0] + _idx = full_state[2] else: if not 0 <= idx <= np.iinfo(np.uint32).max: raise ValueError("idx must be in the interval [0, 2**32).") @@ -204,4 +200,3 @@ cdef class Tyche(BitGenerator): self.rng_state.c = state["c"] self.rng_state.d = state["d"] self._setup_bitgen() - diff --git a/randomgen/wrapper.pyx b/randomgen/wrapper.pyx index 936fa9157..6ee7cf48e 100644 --- a/randomgen/wrapper.pyx +++ b/randomgen/wrapper.pyx @@ -1,7 +1,6 @@ #!python -#cython: binding=True -from libc.stdint cimport uint32_t, uint64_t +from libc.stdint cimport uint32_t from randomgen.common cimport BitGenerator from randomgen.distributions cimport next_double_t, next_uint32_t, next_uint64_t @@ -118,7 +117,7 @@ cdef class UserBitGenerator(BitGenerator): self.state_setter = state_setter self.next_64_ptr = self.next_32_ptr = 0 - self.next_raw_ptr = self.next_double_ptr = 0 + self.next_raw_ptr = self.next_double_ptr = 0 self.state_ptr = 0 self.input_type = "Python" @@ -172,7 +171,8 @@ cdef class UserBitGenerator(BitGenerator): return self.next_raw if self.funcs["next_64"] is None: self.funcs["next_64"] = raw_32_to_64(self.funcs["next_raw"]) - return ctypes.CFUNCTYPE(ctypes.c_uint64, ctypes.c_void_p)(self.funcs["next_64"]) + c_func_type = ctypes.CFUNCTYPE(ctypes.c_uint64, ctypes.c_void_p) + return c_func_type(self.funcs["next_64"]) cdef _setup_32(self): if self.bits == 32 and self.funcs["next_32"] is None: @@ -180,7 +180,8 @@ cdef class UserBitGenerator(BitGenerator): return self.next_raw if self.funcs["next_32"] is None: self.funcs["next_32"] = raw_64_to_32(self.funcs["next_raw"]) - return ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_void_p)(self.funcs["next_32"]) + c_func_type = ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_void_p) + return c_func_type(self.funcs["next_32"]) cdef _setup_double(self): if self.funcs["next_double"] is None: @@ -188,7 +189,8 @@ cdef class UserBitGenerator(BitGenerator): self.funcs["next_double"] = raw_64_to_double(self.funcs["next_raw"]) else: self.funcs["next_double"] = raw_32_to_double(self.funcs["next_raw"]) - return ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_void_p)(self.funcs["next_double"]) + c_func_type = ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_void_p) + return c_func_type(self.funcs["next_double"]) @classmethod def from_cfunc(cls, next_raw, next_64, next_32, next_double, state, @@ -298,7 +300,7 @@ cdef class UserBitGenerator(BitGenerator): """ input_names = ("next_raw", "next_64", "next_32", "next_double") inputs = (next_raw, next_64, next_32, next_double) - restypes = (ctypes.c_uint64,ctypes.c_uint64,ctypes.c_uint32,ctypes.c_double) + restypes = (ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint32, ctypes.c_double) for i_n, inp, r in zip(input_names, inputs, restypes): valid = hasattr(inp, "argtypes") valid = valid and hasattr(inp, "restype") diff --git a/randomgen/xoroshiro128.pyx b/randomgen/xoroshiro128.pyx index baf9ce383..9c7227946 100644 --- a/randomgen/xoroshiro128.pyx +++ b/randomgen/xoroshiro128.pyx @@ -1,5 +1,4 @@ #!python -#cython: binding=True import numpy as np @@ -154,13 +153,8 @@ cdef class Xoroshiro128(BitGenerator): def _seed_from_seq(self): cdef int i - cdef uint64_t *state_arr - try: - state = self.seed_seq.generate_state(2, np.uint64) - except AttributeError: - state = self._seed_seq.generate_state(2, np.uint64) - state_arr = np.PyArray_DATA(state) + state = self._get_seed_seq().generate_state(2, np.uint64) for i in range(2): self.rng_state.s[i] = state[i] self._reset_state_variables() diff --git a/randomgen/xorshift1024.pyx b/randomgen/xorshift1024.pyx index af17078a0..ffcb768ae 100644 --- a/randomgen/xorshift1024.pyx +++ b/randomgen/xorshift1024.pyx @@ -1,5 +1,4 @@ #!python -#cython: binding=True import numpy as np @@ -132,13 +131,8 @@ cdef class Xorshift1024(BitGenerator): def _seed_from_seq(self): cdef int i - cdef uint64_t *state_arr - try: - state = self.seed_seq.generate_state(16, np.uint64) - except AttributeError: - state = self._seed_seq.generate_state(16, np.uint64) - state_arr = np.PyArray_DATA(state) + state = self._get_seed_seq().generate_state(16, np.uint64) for i in range(16): self.rng_state.s[i] = state[i] self._reset_state_variables() diff --git a/randomgen/xoshiro256.pyx b/randomgen/xoshiro256.pyx index efb12816f..b8657ad95 100644 --- a/randomgen/xoshiro256.pyx +++ b/randomgen/xoshiro256.pyx @@ -1,5 +1,4 @@ #!python -#cython: binding=True import numpy as np @@ -132,13 +131,8 @@ cdef class Xoshiro256(BitGenerator): def _seed_from_seq(self): cdef int i - cdef uint64_t *state_arr - try: - state = self.seed_seq.generate_state(4, np.uint64) - except AttributeError: - state = self._seed_seq.generate_state(4, np.uint64) - state_arr = np.PyArray_DATA(state) + state = self._get_seed_seq().generate_state(4, np.uint64) for i in range(4): self.rng_state.s[i] = state[i] self._reset_state_variables() diff --git a/randomgen/xoshiro512.pyx b/randomgen/xoshiro512.pyx index 4f8a6b92c..142559fdf 100644 --- a/randomgen/xoshiro512.pyx +++ b/randomgen/xoshiro512.pyx @@ -1,5 +1,4 @@ #!python -#cython: binding=True import numpy as np @@ -129,13 +128,8 @@ cdef class Xoshiro512(BitGenerator): def _seed_from_seq(self): cdef int i - cdef uint64_t *state_arr - try: - state = self.seed_seq.generate_state(8, np.uint64) - except AttributeError: - state = self._seed_seq.generate_state(8, np.uint64) - state_arr = np.PyArray_DATA(state) + state = self._get_seed_seq().generate_state(8, np.uint64) for i in range(8): self.rng_state.s[i] = state[i] self._reset_state_variables() @@ -229,7 +223,6 @@ cdef class Xoshiro512(BitGenerator): bit_generator : Xoshiro512 New instance of generator jumped iter times """ - import copy cdef Xoshiro512 bit_generator bit_generator = self.__class__(seed=self._copy_seed()) diff --git a/setup.py b/setup.py index 1c9757439..34adeb62a 100644 --- a/setup.py +++ b/setup.py @@ -354,7 +354,11 @@ def is_pure(self): classifiers=classifiers, ext_modules=cythonize( extensions, - compiler_directives={"language_level": "3", "linetrace": CYTHON_COVERAGE}, + compiler_directives={ + "language_level": "3", + "binding": True, + "linetrace": CYTHON_COVERAGE, + }, force=CYTHON_COVERAGE or DEBUG, gdb_debug=DEBUG, ),