- Timestamp:
- Jul 9, 2020, 8:51:43 AM (4 years ago)
- 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 10 10 #include <mruby/data.h> 11 11 #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) 13 20 14 21 #include <time.h> 15 22 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); 23 typedef struct rand_state { 24 uint32_t seed[NSEEDS]; 25 } rand_state; 24 26 25 27 static 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 28 rand_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 38 static uint32_t 39 rand_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 48 static uint32_t 49 rand_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 */ 66 static uint32_t 67 rand_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 37 89 static 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) 90 rand_real(rand_state *t) 91 { 92 uint32_t x = rand_uint32(t); 93 return x*(1.0/4294967295.0); 94 } 95 #endif 96 97 static mrb_value 98 random_rand(mrb_state *mrb, rand_state *t, mrb_value max) 60 99 { 61 100 mrb_value value; 62 101 63 102 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)); 68 111 } 69 112 … … 80 123 81 124 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); 88 131 } 89 132 } … … 91 134 } 92 135 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) 136 static void 137 random_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 144 static mrb_value 145 random_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 157 static mrb_value 158 random_m_init(mrb_state *mrb, mrb_value self) 123 159 { 124 160 mrb_value seed; 125 mt_state *t;161 rand_state *t; 126 162 127 163 seed = get_opt(mrb); 128 129 164 /* 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); 140 166 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 } 150 172 151 173 return self; 152 174 } 153 175 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) 176 static mrb_value 177 random_m_rand(mrb_state *mrb, mrb_value self) 164 178 { 165 179 mrb_value max; 166 mt_state *t = DATA_GET_PTR(mrb, self, &mt_state_type, mt_state);180 rand_state *t = random_ptr(self); 167 181 168 182 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 186 static mrb_value 187 random_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); 193 204 } 194 205 … … 204 215 { 205 216 mrb_int i; 206 mt_state *random = NULL; 217 mrb_value max; 218 mrb_value r = mrb_nil_value(); 219 rand_state *random; 207 220 208 221 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 } 216 231 mrb_ary_modify(mrb, mrb_ary_ptr(ary)); 217 232 max = mrb_fixnum_value(RARRAY_LEN(ary)); 218 233 for (i = RARRAY_LEN(ary) - 1; i > 0; i--) { 219 234 mrb_int j; 235 mrb_value *ptr = RARRAY_PTR(ary); 220 236 mrb_value tmp; 221 237 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; 227 243 } 228 244 } … … 267 283 mrb_int n = 0; 268 284 mrb_bool given; 269 mt_state *random = NULL; 285 mrb_value r = mrb_nil_value(); 286 rand_state *random; 270 287 mrb_int len; 271 288 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 } 278 297 len = RARRAY_LEN(ary); 279 298 if (!given) { /* pick one element */ … … 284 303 return RARRAY_PTR(ary)[0]; 285 304 default: 286 return RARRAY_PTR(ary)[ mt_rand(random) % len];305 return RARRAY_PTR(ary)[rand_uint32(random) % len]; 287 306 } 288 307 } … … 299 318 for (;;) { 300 319 retry: 301 r = mt_rand(random) % len;320 r = (mrb_int)(rand_uint32(random) % len); 302 321 303 322 for (j=0; j<i; j++) { … … 317 336 } 318 337 338 static mrb_value 339 random_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 345 static mrb_value 346 random_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 319 352 320 353 void mrb_mruby_random_gem_init(mrb_state *mrb) … … 323 356 struct RClass *array = mrb->array_class; 324 357 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)); 327 362 328 363 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)); 336 371 337 372 mrb_define_method(mrb, array, "shuffle", mrb_ary_shuffle, MRB_ARGS_OPT(1));
Note:
See TracChangeset
for help on using the changeset viewer.