diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2020-08-17 11:04:43 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2020-10-12 16:21:41 +0900 |
| commit | 44a07393f43223d693a8c4763b7d6dcf68ccb5fc (patch) | |
| tree | 4377d40d8ebfb6fe2a0deedc8ebe23f37a4dc2a8 /mrbgems/mruby-random | |
| parent | 0b22bf4a8926c7987aee63d634be4de8ce9b8e18 (diff) | |
| download | mruby-44a07393f43223d693a8c4763b7d6dcf68ccb5fc.tar.gz mruby-44a07393f43223d693a8c4763b7d6dcf68ccb5fc.zip | |
Use xoshiro128++ instead of xorshift96/128.
Diffstat (limited to 'mrbgems/mruby-random')
| -rw-r--r-- | mrbgems/mruby-random/src/random.c | 92 |
1 files changed, 43 insertions, 49 deletions
diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index 406738374..39c72ac9e 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -10,18 +10,37 @@ #include <mruby/data.h> #include <mruby/array.h> #include <mruby/istruct.h> -#if INT32_MAX <= INTPTR_MAX -# define XORSHIFT96 -# define NSEEDS 3 -#else -# define NSEEDS 4 -#endif -#define LASTSEED (NSEEDS-1) #include <time.h> +/* Written in 2019 by David Blackman and Sebastiano Vigna ([email protected]) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See <http://creativecommons.org/publicdomain/zero/1.0/>. */ + +#include <stdint.h> + +/* This is xoshiro128++ 1.0, one of our 32-bit all-purpose, rock-solid + generators. It has excellent speed, a state size (128 bits) that is + large enough for mild parallelism, and it passes all tests we are aware + of. + + For generating just single-precision (i.e., 32-bit) floating-point + numbers, xoshiro128+ is even faster. + + The state must be seeded so that it is not everywhere zero. */ + + +static inline uint32_t +rotl(const uint32_t x, int k) { + return (x << k) | (x >> (32 - k)); +} + typedef struct rand_state { - uint32_t seed[NSEEDS]; + uint32_t seed[4]; } rand_state; static void @@ -30,60 +49,35 @@ rand_init(rand_state *t) t->seed[0] = 123456789; t->seed[1] = 362436069; t->seed[2] = 521288629; -#ifndef XORSHIFT96 t->seed[3] = 88675123; -#endif } static uint32_t rand_seed(rand_state *t, uint32_t seed) { - uint32_t old_seed = t->seed[LASTSEED]; + uint32_t old_seed = t->seed[0]; rand_init(t); - t->seed[LASTSEED] = seed; + t->seed[0] = seed; return old_seed; } -#ifdef XORSHIFT96 -static uint32_t -rand_uint32(rand_state *state) -{ - uint32_t *seed = state->seed; - uint32_t x = seed[0]; - uint32_t y = seed[1]; - uint32_t z = seed[2]; - uint32_t t; - - t = (x ^ (x << 3)) ^ (y ^ (y >> 19)) ^ (z ^ (z << 6)); - x = y; y = z; z = t; - seed[0] = x; - seed[1] = y; - seed[2] = z; - - return z; -} -#else /* XORSHIFT96 */ static uint32_t rand_uint32(rand_state *state) { - uint32_t *seed = state->seed; - uint32_t x = seed[0]; - uint32_t y = seed[1]; - uint32_t z = seed[2]; - uint32_t w = seed[3]; - uint32_t t; - - t = x ^ (x << 11); - x = y; y = z; z = w; - w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); - seed[0] = x; - seed[1] = y; - seed[2] = z; - seed[3] = w; - - return w; + uint32_t *s = state->seed; + const uint32_t result = rotl(s[0] + s[3], 7) + s[0]; + const uint32_t t = s[1] << 9; + + s[2] ^= s[0]; + s[3] ^= s[1]; + s[1] ^= s[2]; + s[0] ^= s[3]; + + s[2] ^= t; + s[3] = rotl(s[3], 11); + + return result; } -#endif /* XORSHIFT96 */ #ifndef MRB_NO_FLOAT static double @@ -385,7 +379,7 @@ void mrb_mruby_random_gem_init(mrb_state *mrb) struct RClass *random; struct RClass *array = mrb->array_class; - mrb_assert(sizeof(rand_state) <= ISTRUCT_DATA_SIZE); + mrb_static_assert1(sizeof(rand_state) <= ISTRUCT_DATA_SIZE); mrb_define_method(mrb, mrb->kernel_module, "rand", random_f_rand, MRB_ARGS_OPT(1)); mrb_define_method(mrb, mrb->kernel_module, "srand", random_f_srand, MRB_ARGS_OPT(1)); |
