diff options
author | Robert Kern <robert.kern@gmail.com> | 2021-05-04 01:16:04 -0400 |
---|---|---|
committer | Robert Kern <robert.kern@gmail.com> | 2021-05-04 01:16:04 -0400 |
commit | 1cb1f67429997e894c32c3e7484c0bb29324390b (patch) | |
tree | ea43c05d8cdc4c6a4cf9342f1fa31f2bb29d2409 /numpy/random/src | |
parent | ccfd68d88fa356d7f097e216fb2c16b14da4052d (diff) | |
download | numpy-1cb1f67429997e894c32c3e7484c0bb29324390b.tar.gz |
ENH: Add PCG64DXSM implementation.
Diffstat (limited to 'numpy/random/src')
-rw-r--r-- | numpy/random/src/pcg64/pcg64.c | 18 | ||||
-rw-r--r-- | numpy/random/src/pcg64/pcg64.h | 56 |
2 files changed, 74 insertions, 0 deletions
diff --git a/numpy/random/src/pcg64/pcg64.c b/numpy/random/src/pcg64/pcg64.c index b15973aef..c623c809b 100644 --- a/numpy/random/src/pcg64/pcg64.c +++ b/numpy/random/src/pcg64/pcg64.c @@ -61,6 +61,10 @@ pcg_setseq_128_xsl_rr_64_boundedrand_r(pcg_state_setseq_128 *rng, uint64_t bound); extern inline void pcg_setseq_128_advance_r(pcg_state_setseq_128 *rng, pcg128_t delta); +extern inline uint64_t pcg_cm_random_r(pcg_state_setseq_128 *rng); +extern inline void pcg_cm_step_r(pcg_state_setseq_128 *rng); +extern inline uint64_t pcg_output_cm_128_64(pcg128_t state); +extern inline void pcg_cm_srandom_r(pcg_state_setseq_128 *rng, pcg128_t initstate, pcg128_t initseq); /* Multi-step advance functions (jump-ahead, jump-back) * @@ -117,6 +121,9 @@ pcg128_t pcg_advance_lcg_128(pcg128_t state, pcg128_t delta, pcg128_t cur_mult, extern inline uint64_t pcg64_next64(pcg64_state *state); extern inline uint32_t pcg64_next32(pcg64_state *state); +extern inline uint64_t pcg64_cm_next64(pcg64_state *state); +extern inline uint32_t pcg64_cm_next32(pcg64_state *state); + extern void pcg64_advance(pcg64_state *state, uint64_t *step) { pcg128_t delta; #ifndef PCG_EMULATED_128BIT_MATH @@ -128,6 +135,17 @@ extern void pcg64_advance(pcg64_state *state, uint64_t *step) { pcg64_advance_r(state->pcg_state, delta); } +extern void pcg64_cm_advance(pcg64_state *state, uint64_t *step) { + pcg128_t delta; +#ifndef PCG_EMULATED_128BIT_MATH + delta = (((pcg128_t)step[0]) << 64) | step[1]; +#else + delta.high = step[0]; + delta.low = step[1]; +#endif + pcg_cm_advance_r(state->pcg_state, delta); +} + extern void pcg64_set_seed(pcg64_state *state, uint64_t *seed, uint64_t *inc) { pcg128_t s, i; #ifndef PCG_EMULATED_128BIT_MATH diff --git a/numpy/random/src/pcg64/pcg64.h b/numpy/random/src/pcg64/pcg64.h index 31899cbc1..ea8264b01 100644 --- a/numpy/random/src/pcg64/pcg64.h +++ b/numpy/random/src/pcg64/pcg64.h @@ -104,6 +104,9 @@ typedef struct { , PCG_128BIT_CONSTANT(0x0000000000000001ULL, 0xda3e39cb94b95bdbULL) \ } +#define PCG_CHEAP_MULTIPLIER_128 (0xda942042e4dd58b5ULL) + + static inline uint64_t pcg_rotr_64(uint64_t value, unsigned int rot) { #ifdef _WIN32 return _rotr64(value, rot); @@ -209,6 +212,37 @@ static inline uint64_t pcg_output_xsl_rr_128_64(pcg128_t state) { state >> 122u); } +static inline void pcg_cm_step_r(pcg_state_setseq_128 *rng) { + rng-> state = rng->state * PCG_CHEAP_MULTIPLIER_128 + rng->inc; +} + +static inline uint64_t pcg_output_cm_128_64(pcg128_t state) { + uint64_t hi = state >> 64; + uint64_t lo = state; + + lo |= 1; + hi ^= hi >> 32; + hi *= 0xda942042e4dd58b5ULL; + hi ^= hi >> 48; + hi *= lo; + return hi; +} + +static inline void pcg_cm_srandom_r(pcg_state_setseq_128 *rng, pcg128_t initstate, pcg128_t initseq) { + rng->state = 0U; + rng->inc = (initseq << 1u) | 1u; + pcg_cm_step_r(rng); + rng->state += initstate; + pcg_cm_step_r(rng); +} + +static inline uint64_t pcg_cm_random_r(pcg_state_setseq_128* rng) +{ + uint64_t ret = pcg_output_cm_128_64(rng->state); + pcg_cm_step_r(rng); + return ret; +} + static inline uint64_t pcg_setseq_128_xsl_rr_64_random_r(pcg_state_setseq_128* rng) { @@ -248,6 +282,11 @@ static inline void pcg_setseq_128_advance_r(pcg_state_setseq_128 *rng, PCG_DEFAULT_MULTIPLIER_128, rng->inc); } +static inline void pcg_cm_advance_r(pcg_state_setseq_128 *rng, pcg128_t delta) { + rng->state = pcg_advance_lcg_128(rng->state, delta, + PCG_CHEAP_MULTIPLIER_128, rng->inc); +} + typedef pcg_state_setseq_128 pcg64_random_t; #define pcg64_random_r pcg_setseq_128_xsl_rr_64_random_r #define pcg64_boundedrand_r pcg_setseq_128_xsl_rr_64_boundedrand_r @@ -281,7 +320,24 @@ static inline uint32_t pcg64_next32(pcg64_state *state) { return (uint32_t)(next & 0xffffffff); } +static inline uint64_t pcg64_cm_next64(pcg64_state *state) { + return pcg_cm_random_r(state->pcg_state); +} + +static inline uint32_t pcg64_cm_next32(pcg64_state *state) { + uint64_t next; + if (state->has_uint32) { + state->has_uint32 = 0; + return state->uinteger; + } + next = pcg_cm_random_r(state->pcg_state); + state->has_uint32 = 1; + state->uinteger = (uint32_t)(next >> 32); + return (uint32_t)(next & 0xffffffff); +} + void pcg64_advance(pcg64_state *state, uint64_t *step); +void pcg64_cm_advance(pcg64_state *state, uint64_t *step); void pcg64_set_seed(pcg64_state *state, uint64_t *seed, uint64_t *inc); |