Ignore:
Timestamp:
Jul 9, 2020, 8:51:43 AM (4 years ago)
Author:
coas-nagasima
Message:

mrubyを2.1.1に更新

Location:
EcnlProtoTool/trunk/mruby-2.1.1
Files:
1 edited
1 moved

Legend:

Unmodified
Added
Removed
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-random/src/random.c

    r331 r439  
    1010#include <mruby/data.h>
    1111#include <mruby/array.h>
    12 #include "mt19937ar.h"
     12#include <mruby/istruct.h>
     13#if INT32_MAX <= INTPTR_MAX
     14# define XORSHIFT96
     15# define NSEEDS 3
     16#else
     17# define NSEEDS 4
     18#endif
     19#define LASTSEED (NSEEDS-1)
    1320
    1421#include <time.h>
    1522
    16 static char const MT_STATE_KEY[] = "$mrb_i_mt_state";
    17 
    18 static const struct mrb_data_type mt_state_type = {
    19   MT_STATE_KEY, mrb_free,
    20 };
    21 
    22 static mrb_value mrb_random_rand(mrb_state *mrb, mrb_value self);
    23 static mrb_value mrb_random_srand(mrb_state *mrb, mrb_value self);
     23typedef struct rand_state {
     24  uint32_t seed[NSEEDS];
     25} rand_state;
    2426
    2527static void
    26 mt_srand(mt_state *t, unsigned long seed)
    27 {
    28   mrb_random_init_genrand(t, seed);
    29 }
    30 
    31 static unsigned long
    32 mt_rand(mt_state *t)
    33 {
    34   return mrb_random_genrand_int32(t);
    35 }
    36 
     28rand_init(rand_state *t)
     29{
     30  t->seed[0] = 123456789;
     31  t->seed[1] = 362436069;
     32  t->seed[2] = 521288629;
     33#ifndef XORSHIFT96
     34  t->seed[3] = 88675123;
     35#endif
     36}
     37
     38static uint32_t
     39rand_seed(rand_state *t, uint32_t seed)
     40{
     41  uint32_t old_seed = t->seed[LASTSEED];
     42  rand_init(t);
     43  t->seed[LASTSEED] = seed;
     44  return old_seed;
     45}
     46
     47#ifdef XORSHIFT96
     48static uint32_t
     49rand_uint32(rand_state *state)
     50{
     51  uint32_t *seed = state->seed;
     52  uint32_t x = seed[0];
     53  uint32_t y = seed[1];
     54  uint32_t z = seed[2];
     55  uint32_t t;
     56
     57  t = (x ^ (x << 3)) ^ (y ^ (y >> 19)) ^ (z ^ (z << 6));
     58  x = y; y = z; z = t;
     59  seed[0] = x;
     60  seed[1] = y;
     61  seed[2] = z;
     62
     63  return z;
     64}
     65#else  /* XORSHIFT96 */
     66static uint32_t
     67rand_uint32(rand_state *state)
     68{
     69  uint32_t *seed = state->seed;
     70  uint32_t x = seed[0];
     71  uint32_t y = seed[1];
     72  uint32_t z = seed[2];
     73  uint32_t w = seed[3];
     74  uint32_t t;
     75
     76  t = x ^ (x << 11);
     77  x = y; y = z; z = w;
     78  w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
     79  seed[0] = x;
     80  seed[1] = y;
     81  seed[2] = z;
     82  seed[3] = w;
     83
     84  return w;
     85}
     86#endif  /* XORSHIFT96 */
     87
     88#ifndef MRB_WITHOUT_FLOAT
    3789static double
    38 mt_rand_real(mt_state *t)
    39 {
    40   return mrb_random_genrand_real1(t);
    41 }
    42 
    43 static mrb_value
    44 mrb_random_mt_srand(mrb_state *mrb, mt_state *t, mrb_value seed)
    45 {
    46   if (mrb_nil_p(seed)) {
    47     seed = mrb_fixnum_value((mrb_int)(time(NULL) + mt_rand(t)));
    48     if (mrb_fixnum(seed) < 0) {
    49       seed = mrb_fixnum_value(0 - mrb_fixnum(seed));
    50     }
    51   }
    52 
    53   mt_srand(t, (unsigned) mrb_fixnum(seed));
    54 
    55   return seed;
    56 }
    57 
    58 static mrb_value
    59 mrb_random_mt_rand(mrb_state *mrb, mt_state *t, mrb_value max)
     90rand_real(rand_state *t)
     91{
     92  uint32_t x = rand_uint32(t);
     93  return x*(1.0/4294967295.0);
     94}
     95#endif
     96
     97static mrb_value
     98random_rand(mrb_state *mrb, rand_state *t, mrb_value max)
    6099{
    61100  mrb_value value;
    62101
    63102  if (mrb_fixnum(max) == 0) {
    64     value = mrb_float_value(mrb, mt_rand_real(t));
    65   }
    66   else {
    67     value = mrb_fixnum_value(mt_rand(t) % mrb_fixnum(max));
     103#ifndef MRB_WITHOUT_FLOAT
     104    value = mrb_float_value(mrb, rand_real(t));
     105#else
     106    mrb_raise(mrb, E_ARGUMENT_ERROR, "Float not supported");
     107#endif
     108  }
     109  else {
     110    value = mrb_fixnum_value(rand_uint32(t) % mrb_fixnum(max));
    68111  }
    69112
     
    80123
    81124  if (!mrb_nil_p(arg)) {
    82     arg = mrb_check_convert_type(mrb, arg, MRB_TT_FIXNUM, "Fixnum", "to_int");
    83     if (mrb_nil_p(arg)) {
    84       mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument type");
    85     }
    86     if (mrb_fixnum(arg) < 0) {
    87       arg = mrb_fixnum_value(0 - mrb_fixnum(arg));
     125    mrb_int i;
     126
     127    arg = mrb_to_int(mrb, arg);
     128    i = mrb_fixnum(arg);
     129    if (i < 0) {
     130      arg = mrb_fixnum_value(0 - i);
    88131    }
    89132  }
     
    91134}
    92135
    93 static mrb_value
    94 get_random(mrb_state *mrb) {
    95   return mrb_const_get(mrb,
    96              mrb_obj_value(mrb_class_get(mrb, "Random")),
    97              mrb_intern_lit(mrb, "DEFAULT"));
    98 }
    99 
    100 static mt_state *
    101 get_random_state(mrb_state *mrb)
    102 {
    103   mrb_value random_val = get_random(mrb);
    104   return DATA_GET_PTR(mrb, random_val, &mt_state_type, mt_state);
    105 }
    106 
    107 static mrb_value
    108 mrb_random_g_rand(mrb_state *mrb, mrb_value self)
    109 {
    110   mrb_value random = get_random(mrb);
    111   return mrb_random_rand(mrb, random);
    112 }
    113 
    114 static mrb_value
    115 mrb_random_g_srand(mrb_state *mrb, mrb_value self)
    116 {
    117   mrb_value random = get_random(mrb);
    118   return mrb_random_srand(mrb, random);
    119 }
    120 
    121 static mrb_value
    122 mrb_random_init(mrb_state *mrb, mrb_value self)
     136static void
     137random_check(mrb_state *mrb, mrb_value random) {
     138  struct RClass *c = mrb_class_get(mrb, "Random");
     139  if (!mrb_obj_is_kind_of(mrb, random, c) || !mrb_istruct_p(random)) {
     140    mrb_raise(mrb, E_TYPE_ERROR, "Random instance required");
     141  }
     142}
     143
     144static mrb_value
     145random_default(mrb_state *mrb) {
     146  struct RClass *c = mrb_class_get(mrb, "Random");
     147  mrb_value d = mrb_const_get(mrb, mrb_obj_value(c), mrb_intern_lit(mrb, "DEFAULT"));
     148  if (!mrb_obj_is_kind_of(mrb, d, c)) {
     149    mrb_raise(mrb, E_TYPE_ERROR, "Random::DEFAULT replaced");
     150  }
     151  return d;
     152}
     153
     154#define random_ptr(v) (rand_state*)mrb_istruct_ptr(v)
     155#define random_default_state(mrb) random_ptr(random_default(mrb))
     156
     157static mrb_value
     158random_m_init(mrb_state *mrb, mrb_value self)
    123159{
    124160  mrb_value seed;
    125   mt_state *t;
     161  rand_state *t;
    126162
    127163  seed = get_opt(mrb);
    128 
    129164  /* avoid memory leaks */
    130   t = (mt_state*)DATA_PTR(self);
    131   if (t) {
    132     mrb_free(mrb, t);
    133   }
    134   mrb_data_init(self, NULL, &mt_state_type);
    135 
    136   t = (mt_state *)mrb_malloc(mrb, sizeof(mt_state));
    137   t->mti = N + 1;
    138 
    139   seed = mrb_random_mt_srand(mrb, t, seed);
     165  t = random_ptr(self);
    140166  if (mrb_nil_p(seed)) {
    141     t->has_seed = FALSE;
    142   }
    143   else {
    144     mrb_assert(mrb_fixnum_p(seed));
    145     t->has_seed = TRUE;
    146     t->seed = mrb_fixnum(seed);
    147   }
    148 
    149   mrb_data_init(self, t, &mt_state_type);
     167    rand_init(t);
     168  }
     169  else {
     170    rand_seed(t, (uint32_t)mrb_fixnum(seed));
     171  }
    150172
    151173  return self;
    152174}
    153175
    154 static void
    155 mrb_random_rand_seed(mrb_state *mrb, mt_state *t)
    156 {
    157   if (!t->has_seed) {
    158     mrb_random_mt_srand(mrb, t, mrb_nil_value());
    159   }
    160 }
    161 
    162 static mrb_value
    163 mrb_random_rand(mrb_state *mrb, mrb_value self)
     176static mrb_value
     177random_m_rand(mrb_state *mrb, mrb_value self)
    164178{
    165179  mrb_value max;
    166   mt_state *t = DATA_GET_PTR(mrb, self, &mt_state_type, mt_state);
     180  rand_state *t = random_ptr(self);
    167181
    168182  max = get_opt(mrb);
    169   mrb_random_rand_seed(mrb, t);
    170   return mrb_random_mt_rand(mrb, t, max);
    171 }
    172 
    173 static mrb_value
    174 mrb_random_srand(mrb_state *mrb, mrb_value self)
    175 {
    176   mrb_value seed;
    177   mrb_value old_seed;
    178   mt_state *t = DATA_GET_PTR(mrb, self, &mt_state_type, mt_state);
    179 
    180   seed = get_opt(mrb);
    181   seed = mrb_random_mt_srand(mrb, t, seed);
    182   old_seed = t->has_seed? mrb_fixnum_value(t->seed) : mrb_nil_value();
    183   if (mrb_nil_p(seed)) {
    184     t->has_seed = FALSE;
    185   }
    186   else {
    187     mrb_assert(mrb_fixnum_p(seed));
    188     t->has_seed = TRUE;
    189     t->seed = mrb_fixnum(seed);
    190   }
    191 
    192   return old_seed;
     183  return random_rand(mrb, t, max);
     184}
     185
     186static mrb_value
     187random_m_srand(mrb_state *mrb, mrb_value self)
     188{
     189  uint32_t seed;
     190  uint32_t old_seed;
     191  mrb_value sv;
     192  rand_state *t = random_ptr(self);
     193
     194  sv = get_opt(mrb);
     195  if (mrb_nil_p(sv)) {
     196    seed = (uint32_t)time(NULL) + rand_uint32(t);
     197  }
     198  else {
     199    seed = (uint32_t)mrb_fixnum(sv);
     200  }
     201  old_seed = rand_seed(t, seed);
     202
     203  return mrb_fixnum_value((mrb_int)old_seed);
    193204}
    194205
     
    204215{
    205216  mrb_int i;
    206   mt_state *random = NULL;
     217  mrb_value max;
     218  mrb_value r = mrb_nil_value();
     219  rand_state *random;
    207220
    208221  if (RARRAY_LEN(ary) > 1) {
    209     mrb_get_args(mrb, "|d", &random, &mt_state_type);
    210 
    211     if (random == NULL) {
    212       random = get_random_state(mrb);
    213     }
    214     mrb_random_rand_seed(mrb, random);
    215 
     222    mrb_get_args(mrb, "|o", &r);
     223
     224    if (mrb_nil_p(r)) {
     225      random = random_default_state(mrb);
     226    }
     227    else {
     228      random_check(mrb, r);
     229      random = random_ptr(r);
     230    }
    216231    mrb_ary_modify(mrb, mrb_ary_ptr(ary));
    217 
     232    max = mrb_fixnum_value(RARRAY_LEN(ary));
    218233    for (i = RARRAY_LEN(ary) - 1; i > 0; i--)  {
    219234      mrb_int j;
     235      mrb_value *ptr = RARRAY_PTR(ary);
    220236      mrb_value tmp;
    221237
    222       j = mrb_fixnum(mrb_random_mt_rand(mrb, random, mrb_fixnum_value(RARRAY_LEN(ary))));
    223 
    224       tmp = RARRAY_PTR(ary)[i];
    225       mrb_ary_ptr(ary)->ptr[i] = RARRAY_PTR(ary)[j];
    226       mrb_ary_ptr(ary)->ptr[j] = tmp;
     238      j = mrb_fixnum(random_rand(mrb, random, max));
     239
     240      tmp = ptr[i];
     241      ptr[i] = ptr[j];
     242      ptr[j] = tmp;
    227243    }
    228244  }
     
    267283  mrb_int n = 0;
    268284  mrb_bool given;
    269   mt_state *random = NULL;
     285  mrb_value r = mrb_nil_value();
     286  rand_state *random;
    270287  mrb_int len;
    271288
    272   mrb_get_args(mrb, "|i?d", &n, &given, &random, &mt_state_type);
    273   if (random == NULL) {
    274     random = get_random_state(mrb);
    275   }
    276   mrb_random_rand_seed(mrb, random);
    277   mt_rand(random);
     289  mrb_get_args(mrb, "|i?o", &n, &given, &r);
     290  if (mrb_nil_p(r)) {
     291    random = random_default_state(mrb);
     292  }
     293  else {
     294    random_check(mrb, r);
     295    random = random_ptr(r);
     296  }
    278297  len = RARRAY_LEN(ary);
    279298  if (!given) {                 /* pick one element */
     
    284303      return RARRAY_PTR(ary)[0];
    285304    default:
    286       return RARRAY_PTR(ary)[mt_rand(random) % len];
     305      return RARRAY_PTR(ary)[rand_uint32(random) % len];
    287306    }
    288307  }
     
    299318      for (;;) {
    300319      retry:
    301         r = mt_rand(random) % len;
     320        r = (mrb_int)(rand_uint32(random) % len);
    302321
    303322        for (j=0; j<i; j++) {
     
    317336}
    318337
     338static mrb_value
     339random_f_rand(mrb_state *mrb, mrb_value self)
     340{
     341  rand_state *t = random_default_state(mrb);
     342  return random_rand(mrb, t, get_opt(mrb));
     343}
     344
     345static mrb_value
     346random_f_srand(mrb_state *mrb, mrb_value self)
     347{
     348  mrb_value random = random_default(mrb);
     349  return random_m_srand(mrb, random);
     350}
     351
    319352
    320353void mrb_mruby_random_gem_init(mrb_state *mrb)
     
    323356  struct RClass *array = mrb->array_class;
    324357
    325   mrb_define_method(mrb, mrb->kernel_module, "rand", mrb_random_g_rand, MRB_ARGS_OPT(1));
    326   mrb_define_method(mrb, mrb->kernel_module, "srand", mrb_random_g_srand, MRB_ARGS_OPT(1));
     358  mrb_assert(sizeof(rand_state) <= ISTRUCT_DATA_SIZE);
     359
     360  mrb_define_method(mrb, mrb->kernel_module, "rand", random_f_rand, MRB_ARGS_OPT(1));
     361  mrb_define_method(mrb, mrb->kernel_module, "srand", random_f_srand, MRB_ARGS_OPT(1));
    327362
    328363  random = mrb_define_class(mrb, "Random", mrb->object_class);
    329   MRB_SET_INSTANCE_TT(random, MRB_TT_DATA);
    330   mrb_define_class_method(mrb, random, "rand", mrb_random_g_rand, MRB_ARGS_OPT(1));
    331   mrb_define_class_method(mrb, random, "srand", mrb_random_g_srand, MRB_ARGS_OPT(1));
    332 
    333   mrb_define_method(mrb, random, "initialize", mrb_random_init, MRB_ARGS_OPT(1));
    334   mrb_define_method(mrb, random, "rand", mrb_random_rand, MRB_ARGS_OPT(1));
    335   mrb_define_method(mrb, random, "srand", mrb_random_srand, MRB_ARGS_OPT(1));
     364  MRB_SET_INSTANCE_TT(random, MRB_TT_ISTRUCT);
     365  mrb_define_class_method(mrb, random, "rand", random_f_rand, MRB_ARGS_OPT(1));
     366  mrb_define_class_method(mrb, random, "srand", random_f_srand, MRB_ARGS_OPT(1));
     367
     368  mrb_define_method(mrb, random, "initialize", random_m_init, MRB_ARGS_OPT(1));
     369  mrb_define_method(mrb, random, "rand", random_m_rand, MRB_ARGS_OPT(1));
     370  mrb_define_method(mrb, random, "srand", random_m_srand, MRB_ARGS_OPT(1));
    336371
    337372  mrb_define_method(mrb, array, "shuffle", mrb_ary_shuffle, MRB_ARGS_OPT(1));
Note: See TracChangeset for help on using the changeset viewer.