summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-random/src/random.c
diff options
context:
space:
mode:
Diffstat (limited to 'mrbgems/mruby-random/src/random.c')
-rw-r--r--mrbgems/mruby-random/src/random.c91
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));