From 58daab21cd043e1dc37024a7f99b396788372918 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 9 Mar 2024 14:19:48 +0100 Subject: Merging upstream version 1.44.3. Signed-off-by: Daniel Baumann --- .../deps/mruby/mrbgems/mruby-random/src/random.c | 349 +++++++++++++++++++++ 1 file changed, 349 insertions(+) create mode 100644 web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/random.c (limited to 'web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/random.c') diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/random.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/random.c new file mode 100644 index 000000000..b865244cc --- /dev/null +++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/random.c @@ -0,0 +1,349 @@ +/* +** random.c - Random module +** +** See Copyright Notice in mruby.h +*/ + +#include +#include +#include +#include +#include +#include "mt19937ar.h" + +#include + +static char const MT_STATE_KEY[] = "$mrb_i_mt_state"; + +static const struct mrb_data_type mt_state_type = { + MT_STATE_KEY, mrb_free, +}; + +static mrb_value mrb_random_rand(mrb_state *mrb, mrb_value self); +static mrb_value mrb_random_srand(mrb_state *mrb, mrb_value self); + +static void +mt_srand(mt_state *t, unsigned long seed) +{ + mrb_random_init_genrand(t, seed); +} + +static unsigned long +mt_rand(mt_state *t) +{ + return mrb_random_genrand_int32(t); +} + +static double +mt_rand_real(mt_state *t) +{ + return mrb_random_genrand_real1(t); +} + +static mrb_value +mrb_random_mt_srand(mrb_state *mrb, mt_state *t, mrb_value seed) +{ + if (mrb_nil_p(seed)) { + seed = mrb_fixnum_value((mrb_int)(time(NULL) + mt_rand(t))); + if (mrb_fixnum(seed) < 0) { + seed = mrb_fixnum_value(0 - mrb_fixnum(seed)); + } + } + + mt_srand(t, (unsigned) mrb_fixnum(seed)); + + return seed; +} + +static mrb_value +mrb_random_mt_rand(mrb_state *mrb, mt_state *t, mrb_value max) +{ + mrb_value value; + + if (mrb_fixnum(max) == 0) { + value = mrb_float_value(mrb, mt_rand_real(t)); + } + else { + value = mrb_fixnum_value(mt_rand(t) % mrb_fixnum(max)); + } + + return value; +} + +static mrb_value +get_opt(mrb_state* mrb) +{ + mrb_value arg; + + arg = mrb_nil_value(); + mrb_get_args(mrb, "|o", &arg); + + if (!mrb_nil_p(arg)) { + arg = mrb_check_convert_type(mrb, arg, MRB_TT_FIXNUM, "Fixnum", "to_int"); + if (mrb_nil_p(arg)) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument type"); + } + if (mrb_fixnum(arg) < 0) { + arg = mrb_fixnum_value(0 - mrb_fixnum(arg)); + } + } + return arg; +} + +static mrb_value +get_random(mrb_state *mrb) { + return mrb_const_get(mrb, + mrb_obj_value(mrb_class_get(mrb, "Random")), + mrb_intern_lit(mrb, "DEFAULT")); +} + +static mt_state * +get_random_state(mrb_state *mrb) +{ + mrb_value random_val = get_random(mrb); + return DATA_GET_PTR(mrb, random_val, &mt_state_type, mt_state); +} + +static mrb_value +mrb_random_g_rand(mrb_state *mrb, mrb_value self) +{ + mrb_value random = get_random(mrb); + return mrb_random_rand(mrb, random); +} + +static mrb_value +mrb_random_g_srand(mrb_state *mrb, mrb_value self) +{ + mrb_value random = get_random(mrb); + return mrb_random_srand(mrb, random); +} + +static mrb_value +mrb_random_init(mrb_state *mrb, mrb_value self) +{ + mrb_value seed; + mt_state *t; + + seed = get_opt(mrb); + + /* avoid memory leaks */ + t = (mt_state*)DATA_PTR(self); + if (t) { + mrb_free(mrb, t); + } + mrb_data_init(self, NULL, &mt_state_type); + + t = (mt_state *)mrb_malloc(mrb, sizeof(mt_state)); + t->mti = N + 1; + + seed = mrb_random_mt_srand(mrb, t, seed); + if (mrb_nil_p(seed)) { + t->has_seed = FALSE; + } + else { + mrb_assert(mrb_fixnum_p(seed)); + t->has_seed = TRUE; + t->seed = mrb_fixnum(seed); + } + + mrb_data_init(self, t, &mt_state_type); + + return self; +} + +static void +mrb_random_rand_seed(mrb_state *mrb, mt_state *t) +{ + if (!t->has_seed) { + mrb_random_mt_srand(mrb, t, mrb_nil_value()); + } +} + +static mrb_value +mrb_random_rand(mrb_state *mrb, mrb_value self) +{ + mrb_value max; + mt_state *t = DATA_GET_PTR(mrb, self, &mt_state_type, mt_state); + + max = get_opt(mrb); + mrb_random_rand_seed(mrb, t); + return mrb_random_mt_rand(mrb, t, max); +} + +static mrb_value +mrb_random_srand(mrb_state *mrb, mrb_value self) +{ + mrb_value seed; + mrb_value old_seed; + mt_state *t = DATA_GET_PTR(mrb, self, &mt_state_type, mt_state); + + seed = get_opt(mrb); + seed = mrb_random_mt_srand(mrb, t, seed); + old_seed = t->has_seed? mrb_fixnum_value(t->seed) : mrb_nil_value(); + if (mrb_nil_p(seed)) { + t->has_seed = FALSE; + } + else { + mrb_assert(mrb_fixnum_p(seed)); + t->has_seed = TRUE; + t->seed = mrb_fixnum(seed); + } + + return old_seed; +} + +/* + * call-seq: + * ary.shuffle! -> ary + * + * Shuffles elements in self in place. + */ + +static mrb_value +mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary) +{ + mrb_int i; + mt_state *random = NULL; + + if (RARRAY_LEN(ary) > 1) { + mrb_get_args(mrb, "|d", &random, &mt_state_type); + + if (random == NULL) { + random = get_random_state(mrb); + } + mrb_random_rand_seed(mrb, random); + + mrb_ary_modify(mrb, mrb_ary_ptr(ary)); + + for (i = RARRAY_LEN(ary) - 1; i > 0; i--) { + mrb_int j; + mrb_value *ptr = RARRAY_PTR(ary); + mrb_value tmp; + + + j = mrb_fixnum(mrb_random_mt_rand(mrb, random, mrb_fixnum_value(RARRAY_LEN(ary)))); + + tmp = ptr[i]; + ptr[i] = ptr[j]; + ptr[j] = tmp; + } + } + + return ary; +} + +/* + * call-seq: + * ary.shuffle -> new_ary + * + * Returns a new array with elements of self shuffled. + */ + +static mrb_value +mrb_ary_shuffle(mrb_state *mrb, mrb_value ary) +{ + mrb_value new_ary = mrb_ary_new_from_values(mrb, RARRAY_LEN(ary), RARRAY_PTR(ary)); + mrb_ary_shuffle_bang(mrb, new_ary); + + return new_ary; +} + +/* + * call-seq: + * ary.sample -> obj + * ary.sample(n) -> new_ary + * + * Choose a random element or +n+ random elements from the array. + * + * The elements are chosen by using random and unique indices into the array + * in order to ensure that an element doesn't repeat itself unless the array + * already contained duplicate elements. + * + * If the array is empty the first form returns +nil+ and the second form + * returns an empty array. + */ + +static mrb_value +mrb_ary_sample(mrb_state *mrb, mrb_value ary) +{ + mrb_int n = 0; + mrb_bool given; + mt_state *random = NULL; + mrb_int len; + + mrb_get_args(mrb, "|i?d", &n, &given, &random, &mt_state_type); + if (random == NULL) { + random = get_random_state(mrb); + } + mrb_random_rand_seed(mrb, random); + mt_rand(random); + len = RARRAY_LEN(ary); + if (!given) { /* pick one element */ + switch (len) { + case 0: + return mrb_nil_value(); + case 1: + return RARRAY_PTR(ary)[0]; + default: + return RARRAY_PTR(ary)[mt_rand(random) % len]; + } + } + else { + mrb_value result; + mrb_int i, j; + + if (n < 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "negative sample number"); + if (n > len) n = len; + result = mrb_ary_new_capa(mrb, n); + for (i=0; iarray_class; + + mrb_define_method(mrb, mrb->kernel_module, "rand", mrb_random_g_rand, MRB_ARGS_OPT(1)); + mrb_define_method(mrb, mrb->kernel_module, "srand", mrb_random_g_srand, MRB_ARGS_OPT(1)); + + random = mrb_define_class(mrb, "Random", mrb->object_class); + MRB_SET_INSTANCE_TT(random, MRB_TT_DATA); + mrb_define_class_method(mrb, random, "rand", mrb_random_g_rand, MRB_ARGS_OPT(1)); + mrb_define_class_method(mrb, random, "srand", mrb_random_g_srand, MRB_ARGS_OPT(1)); + + mrb_define_method(mrb, random, "initialize", mrb_random_init, MRB_ARGS_OPT(1)); + mrb_define_method(mrb, random, "rand", mrb_random_rand, MRB_ARGS_OPT(1)); + mrb_define_method(mrb, random, "srand", mrb_random_srand, MRB_ARGS_OPT(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)); + mrb_define_method(mrb, array, "sample", mrb_ary_sample, MRB_ARGS_OPT(2)); + + mrb_const_set(mrb, mrb_obj_value(random), mrb_intern_lit(mrb, "DEFAULT"), + mrb_obj_new(mrb, random, 0, NULL)); +} + +void mrb_mruby_random_gem_final(mrb_state *mrb) +{ +} -- cgit v1.2.3