diff options
Diffstat (limited to 'mrbgems/mruby-random/src/random.c')
| -rw-r--r-- | mrbgems/mruby-random/src/random.c | 91 |
1 files changed, 37 insertions, 54 deletions
diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index 9712fbd7e..ae917d33e 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -11,6 +11,7 @@ #include <mruby/array.h> #include <mruby/istruct.h> #include <mruby/presym.h> +#include <mruby/string.h> #include <time.h> @@ -22,8 +23,6 @@ worldwide. This software is distributed without any warranty. See <https://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 @@ -60,12 +59,17 @@ rand_init(rand_state *t) #endif } +static uint32_t rand_uint32(rand_state *state); + static uint32_t rand_seed(rand_state *t, uint32_t seed) { uint32_t old_seed = t->seed[SEEDPOS]; rand_init(t); t->seed[SEEDPOS] = seed; + for (int i = 0; i < 10; i++) { + rand_uint32(t); + } return old_seed; } @@ -151,14 +155,6 @@ get_opt(mrb_state* mrb) return arg; } -static void -random_check(mrb_state *mrb, mrb_value random) { - struct RClass *c = mrb_class_get_id(mrb, MRB_SYM(Random)); - if (!mrb_obj_is_kind_of(mrb, random, c) || !mrb_istruct_p(random)) { - mrb_raise(mrb, E_TYPE_ERROR, "Random instance required"); - } -} - static mrb_value random_default(mrb_state *mrb) { struct RClass *c = mrb_class_get_id(mrb, MRB_SYM(Random)); @@ -218,6 +214,23 @@ random_m_srand(mrb_state *mrb, mrb_value self) return mrb_int_value(mrb, (mrb_int)old_seed); } +static mrb_value +random_m_bytes(mrb_state *mrb, mrb_value self) +{ + rand_state *t = random_ptr(self); + + mrb_int i; + mrb_get_args(mrb, "i", &i); + + mrb_value bytes = mrb_str_new(mrb, NULL, i); + uint8_t *p = (uint8_t*)RSTRING_PTR(bytes); + for (; i > 0; i--, p++) { + *p = (uint8_t)rand_uint32(t); + } + + return bytes; +} + /* * call-seq: * ary.shuffle! -> ary @@ -229,47 +242,13 @@ static mrb_value mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary) { mrb_int i, max; - mrb_value r = mrb_nil_value(); rand_state *random; - /* - * MSC compiler bug generating invalid instructions with optimization - * enabled. MSC errantly uses a hardcoded value with optimizations on - * when using a fixed value from a union. - * Creating a temp volatile variable and reassigning back to the original - * value tricks the compiler to not perform this optimization; - */ -#if defined _MSC_VER && _MSC_VER >= 1923 - /* C++ will not cast away volatile easily, so we cannot do something like - * volatile mrb_value rr = r; r = (mrb_value)rr; with C++. - * That cast does work with C. - * We also have to trick the compiler to not optimize away the const_cast entirely - * by creating and manipulating an intermediate volatile pointer. - */ - volatile mrb_value *v_r; - volatile mrb_int ii; - mrb_value *p_r; - v_r = &r; - ii = 2; - v_r = v_r + 2; -#if defined __cplusplus - p_r = const_cast<mrb_value*>(v_r - ii); -#else - p_r = (mrb_value*)v_r - ii; -#endif - r = *p_r; -#endif - if (RARRAY_LEN(ary) > 1) { - mrb_get_args(mrb, "|o", &r); - - if (mrb_nil_p(r)) { + struct RClass *c = mrb_class_get_id(mrb, MRB_SYM(Random)); + if (mrb_get_args(mrb, "|I", &random, c) == 0) { random = random_default_state(mrb); } - else { - random_check(mrb, r); - random = random_ptr(r); - } mrb_ary_modify(mrb, mrb_ary_ptr(ary)); max = RARRAY_LEN(ary); for (i = RARRAY_LEN(ary) - 1; i > 0; i--) { @@ -324,18 +303,13 @@ mrb_ary_sample(mrb_state *mrb, mrb_value ary) { mrb_int n = 0; mrb_bool given; - mrb_value r = mrb_nil_value(); rand_state *random; mrb_int len; + struct RClass *c = mrb_class_get_id(mrb, MRB_SYM(Random)); - mrb_get_args(mrb, "|i?o", &n, &given, &r); - if (mrb_nil_p(r)) { + if (mrb_get_args(mrb, "|i?I", &n, &given, &random, c) < 2) { random = random_default_state(mrb); } - else { - random_check(mrb, r); - random = random_ptr(r); - } len = RARRAY_LEN(ary); if (!given) { /* pick one element */ switch (len) { @@ -393,13 +367,20 @@ random_f_srand(mrb_state *mrb, mrb_value self) return random_m_srand(mrb, random); } +static mrb_value +random_f_bytes(mrb_state *mrb, mrb_value self) +{ + mrb_value random = random_default(mrb); + return random_m_bytes(mrb, random); +} + void mrb_mruby_random_gem_init(mrb_state *mrb) { struct RClass *random; struct RClass *array = mrb->array_class; - mrb_static_assert1(sizeof(rand_state) <= ISTRUCT_DATA_SIZE); + mrb_static_assert(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)); @@ -408,10 +389,12 @@ void mrb_mruby_random_gem_init(mrb_state *mrb) MRB_SET_INSTANCE_TT(random, MRB_TT_ISTRUCT); mrb_define_class_method(mrb, random, "rand", random_f_rand, MRB_ARGS_OPT(1)); mrb_define_class_method(mrb, random, "srand", random_f_srand, MRB_ARGS_OPT(1)); + mrb_define_class_method(mrb, random, "bytes", random_f_bytes, MRB_ARGS_REQ(1)); mrb_define_method(mrb, random, "initialize", random_m_init, MRB_ARGS_OPT(1)); mrb_define_method(mrb, random, "rand", random_m_rand, MRB_ARGS_OPT(1)); mrb_define_method(mrb, random, "srand", random_m_srand, MRB_ARGS_OPT(1)); + mrb_define_method(mrb, random, "bytes", random_m_bytes, MRB_ARGS_REQ(1)); mrb_define_method(mrb, array, "shuffle", mrb_ary_shuffle, MRB_ARGS_OPT(1)); mrb_define_method(mrb, array, "shuffle!", mrb_ary_shuffle_bang, MRB_ARGS_OPT(1)); |
