diff options
Diffstat (limited to 'numpy/random/src')
-rw-r--r-- | numpy/random/src/sfc64/LICENSE.md | 27 | ||||
-rw-r--r-- | numpy/random/src/sfc64/sfc64.c | 39 | ||||
-rw-r--r-- | numpy/random/src/sfc64/sfc64.h | 60 |
3 files changed, 126 insertions, 0 deletions
diff --git a/numpy/random/src/sfc64/LICENSE.md b/numpy/random/src/sfc64/LICENSE.md new file mode 100644 index 000000000..21dd604af --- /dev/null +++ b/numpy/random/src/sfc64/LICENSE.md @@ -0,0 +1,27 @@ +# SFC64 + +## The MIT License + +Adapted from a C++ implementation of Chris Doty-Humphrey's SFC PRNG. + +https://gist.github.com/imneme/f1f7821f07cf76504a97f6537c818083 + +Copyright (c) 2018 Melissa E. O'Neill + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/numpy/random/src/sfc64/sfc64.c b/numpy/random/src/sfc64/sfc64.c new file mode 100644 index 000000000..5546fff08 --- /dev/null +++ b/numpy/random/src/sfc64/sfc64.c @@ -0,0 +1,39 @@ +#include "sfc64.h" + +extern void sfc64_set_seed(sfc64_state *state, uint64_t *seed) { + /* Conservatively stick with the original formula. With SeedSequence, it + * might be fine to just set the state with 4 uint64s and be done. + */ + int i; + + state->s[0] = seed[0]; + state->s[1] = seed[1]; + state->s[2] = seed[2]; + state->s[3] = 1; + + for (i=0; i<12; i++) { + (void)sfc64_next(state->s); + } +} + +extern void sfc64_get_state(sfc64_state *state, uint64_t *state_arr, int *has_uint32, + uint32_t *uinteger) { + int i; + + for (i=0; i<4; i++) { + state_arr[i] = state->s[i]; + } + has_uint32[0] = state->has_uint32; + uinteger[0] = state->uinteger; +} + +extern void sfc64_set_state(sfc64_state *state, uint64_t *state_arr, int has_uint32, + uint32_t uinteger) { + int i; + + for (i=0; i<4; i++) { + state->s[i] = state_arr[i]; + } + state->has_uint32 = has_uint32; + state->uinteger = uinteger; +} diff --git a/numpy/random/src/sfc64/sfc64.h b/numpy/random/src/sfc64/sfc64.h new file mode 100644 index 000000000..6674ae69c --- /dev/null +++ b/numpy/random/src/sfc64/sfc64.h @@ -0,0 +1,60 @@ +#ifndef _RANDOMDGEN__SFC64_H_ +#define _RANDOMDGEN__SFC64_H_ + +#include <inttypes.h> +#ifdef _WIN32 +#include <stdlib.h> +#endif +#include "numpy/npy_common.h" + +typedef struct s_sfc64_state { + uint64_t s[4]; + int has_uint32; + uint32_t uinteger; +} sfc64_state; + + +static NPY_INLINE uint64_t rotl(const uint64_t value, unsigned int rot) { +#ifdef _WIN32 + return _rotl64(value, rot); +#else + return (value << rot) | (value >> ((-rot) & 63)); +#endif +} + +static NPY_INLINE uint64_t sfc64_next(uint64_t *s) { + const uint64_t tmp = s[0] + s[1] + s[3]++; + + s[0] = s[1] ^ (s[1] >> 11); + s[1] = s[2] + (s[2] << 3); + s[2] = rotl(s[2], 24) + tmp; + + return tmp; +} + + +static NPY_INLINE uint64_t sfc64_next64(sfc64_state *state) { + return sfc64_next(&state->s[0]); +} + +static NPY_INLINE uint32_t sfc64_next32(sfc64_state *state) { + uint64_t next; + if (state->has_uint32) { + state->has_uint32 = 0; + return state->uinteger; + } + next = sfc64_next(&state->s[0]); + state->has_uint32 = 1; + state->uinteger = (uint32_t)(next >> 32); + return (uint32_t)(next & 0xffffffff); +} + +void sfc64_set_seed(sfc64_state *state, uint64_t *seed); + +void sfc64_get_state(sfc64_state *state, uint64_t *state_arr, int *has_uint32, + uint32_t *uinteger); + +void sfc64_set_state(sfc64_state *state, uint64_t *state_arr, int has_uint32, + uint32_t uinteger); + +#endif |