diff options
| author | MATSUMOTO Ryosuke <[email protected]> | 2013-03-27 10:39:11 +0900 |
|---|---|---|
| committer | MATSUMOTO Ryosuke <[email protected]> | 2013-03-27 10:39:11 +0900 |
| commit | 07dc11cae31a8148310c598770d687a1eaa91491 (patch) | |
| tree | 17c17cd440ac0bdf52fad03ab8a6ce093695788f /mrbgems/mruby-random/src | |
| parent | 1abe678e1c0a5fd153c07d71634f262fd51b7668 (diff) | |
| download | mruby-07dc11cae31a8148310c598770d687a1eaa91491.tar.gz mruby-07dc11cae31a8148310c598770d687a1eaa91491.zip | |
Support mt instance valiables
Diffstat (limited to 'mrbgems/mruby-random/src')
| -rw-r--r-- | mrbgems/mruby-random/src/mt19937ar.c | 59 | ||||
| -rw-r--r-- | mrbgems/mruby-random/src/mt19937ar.h | 15 | ||||
| -rw-r--r-- | mrbgems/mruby-random/src/random.c | 115 |
3 files changed, 169 insertions, 20 deletions
diff --git a/mrbgems/mruby-random/src/mt19937ar.c b/mrbgems/mruby-random/src/mt19937ar.c index 211aefde9..8e3295a82 100644 --- a/mrbgems/mruby-random/src/mt19937ar.c +++ b/mrbgems/mruby-random/src/mt19937ar.c @@ -47,7 +47,7 @@ #include "mt19937ar.h" /* Period parameters */ -#define N 624 +//#define N 624 #define M 397 #define MATRIX_A 0x9908b0dfUL /* constant vector a */ #define UPPER_MASK 0x80000000UL /* most significant w-r bits */ @@ -56,6 +56,63 @@ static unsigned long mt[N]; /* the array for the state vector */ static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */ +void mrb_random_init_genrand(mt_state *t, unsigned long s) +{ + t->mt[0]= s & 0xffffffffUL; + for (t->mti=1; t->mti<N; t->mti++) { + t->mt[t->mti] = + (1812433253UL * (t->mt[t->mti-1] ^ (t->mt[t->mti-1] >> 30)) + t->mti); + t->mt[t->mti] &= 0xffffffffUL; + } +} + +unsigned long mrb_random_genrand_int32(mt_state *t) +{ + unsigned long y; + static unsigned long mag01[2]={0x0UL, MATRIX_A}; + /* mag01[x] = x * MATRIX_A for x=0,1 */ + + if (t->mti >= N) { /* generate N words at one time */ + int kk; + + if (t->mti == N+1) /* if init_genrand() has not been called, */ + mrb_random_init_genrand(t, 5489UL); /* a default initial seed is used */ + + for (kk=0;kk<N-M;kk++) { + y = (t->mt[kk]&UPPER_MASK)|(t->mt[kk+1]&LOWER_MASK); + t->mt[kk] = t->mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL]; + } + for (;kk<N-1;kk++) { + y = (t->mt[kk]&UPPER_MASK)|(t->mt[kk+1]&LOWER_MASK); + t->mt[kk] = t->mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL]; + } + y = (t->mt[N-1]&UPPER_MASK)|(t->mt[0]&LOWER_MASK); + t->mt[N-1] = t->mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; + + t->mti = 0; + } + + y = t->mt[t->mti++]; + + /* Tempering */ + y ^= (y >> 11); + y ^= (y << 7) & 0x9d2c5680UL; + y ^= (y << 15) & 0xefc60000UL; + y ^= (y >> 18); + + t->gen_int = y; + + return y; +} + +double mrb_random_genrand_real1(mt_state *t) +{ + mrb_random_genrand_int32(t); + t->gen_dbl = t->gen_int*(1.0/4294967295.0); + return t->gen_dbl; + /* divided by 2^32-1 */ +} + /* initializes mt[N] with a seed */ void init_genrand(unsigned long s) { diff --git a/mrbgems/mruby-random/src/mt19937ar.h b/mrbgems/mruby-random/src/mt19937ar.h index 8b98b8a5b..3f36cb1ff 100644 --- a/mrbgems/mruby-random/src/mt19937ar.h +++ b/mrbgems/mruby-random/src/mt19937ar.h @@ -43,6 +43,21 @@ email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) */ +#define N 624 + +typedef struct { + unsigned long mt[N]; + int mti; + union { + unsigned long gen_int; + double gen_dbl; + }; +} mt_state; + +void mrb_random_init_genrand(mt_state *, unsigned long); +unsigned long mrb_random_genrand_int32(mt_state *); +double mrb_random_genrand_real1(mt_state *t); + /* initializes mt[N] with a seed */ void init_genrand(unsigned long s); diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index 599dcc381..1e3d02ab3 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -6,50 +6,115 @@ #include "mruby.h" #include "mruby/variable.h" +#include "mruby/data.h" #include "mt19937ar.h" #include <time.h> #define GLOBAL_RAND_SEED_KEY "$mrb_g_rand_seed" #define INSTANCE_RAND_SEED_KEY "$mrb_i_rand_seed" - -static void mt_srand(unsigned long seed) +#define MT_STATE_KEY "$mrb_i_mt_state" + +static void mt_state_free(mrb_state *mrb, void *p) +{ +} + +static const struct mrb_data_type mt_state_type = { + MT_STATE_KEY, mt_state_free, +}; + +static mt_state *mrb_mt_get_context(mrb_state *mrb, mrb_value self) +{ + mt_state *t; + mrb_value context; + + context = mrb_iv_get(mrb, self, mrb_intern(mrb, MT_STATE_KEY)); + Data_Get_Struct(mrb, context, &mt_state_type, t); + if (!t) + mrb_raise(mrb, E_RUNTIME_ERROR, "mt_state get from mrb_iv_get failed"); + + return t; +} + +static void mt_g_srand(unsigned long seed) { init_genrand(seed); -} +} -static unsigned long mt_rand() +static unsigned long mt_g_rand() { return genrand_int32(); -} +} -static double mt_rand_real() +static double mt_g_rand_real() { return genrand_real1(); +} + +static mrb_value mrb_random_mt_g_srand(mrb_state *mrb, mrb_value seed) +{ + if (mrb_nil_p(seed)) { + seed = mrb_fixnum_value(time(NULL) + mt_g_rand()); + if (mrb_fixnum(seed) < 0) { + seed = mrb_fixnum_value( 0 - mrb_fixnum(seed)); + } + } + + mt_g_srand((unsigned) mrb_fixnum(seed)); + + return seed; +} + +static mrb_value mrb_random_mt_g_rand(mrb_state *mrb, mrb_value max) +{ + mrb_value value; + + if (mrb_fixnum(max) == 0) { + value = mrb_float_value(mt_g_rand_real()); + } else { + value = mrb_fixnum_value(mt_g_rand() % mrb_fixnum(max)); + } + + return value; +} + +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 mrb_value mrb_random_mt_srand(mrb_state *mrb, mrb_value seed) +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(time(NULL) + mt_rand()); + seed = mrb_fixnum_value(time(NULL) + mt_rand(t)); if (mrb_fixnum(seed) < 0) { seed = mrb_fixnum_value( 0 - mrb_fixnum(seed)); } } - mt_srand((unsigned) mrb_fixnum(seed)); + mt_srand(t, (unsigned) mrb_fixnum(seed)); return seed; } -static mrb_value mrb_random_mt_rand(mrb_state *mrb, mrb_value max) +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(mt_rand_real()); + value = mrb_float_value(mt_rand_real(t)); } else { - value = mrb_fixnum_value(mt_rand() % mrb_fixnum(max)); + value = mrb_fixnum_value(mt_rand(t) % mrb_fixnum(max)); } return value; @@ -82,9 +147,9 @@ static mrb_value mrb_random_g_rand(mrb_state *mrb, mrb_value self) max = get_opt(mrb); seed = mrb_gv_get(mrb, mrb_intern(mrb, GLOBAL_RAND_SEED_KEY)); if (mrb_nil_p(seed)) { - mrb_random_mt_srand(mrb, mrb_nil_value()); + mrb_random_mt_g_srand(mrb, mrb_nil_value()); } - return mrb_random_mt_rand(mrb, max); + return mrb_random_mt_g_rand(mrb, max); } static mrb_value mrb_random_g_srand(mrb_state *mrb, mrb_value self) @@ -93,7 +158,7 @@ static mrb_value mrb_random_g_srand(mrb_state *mrb, mrb_value self) mrb_value old_seed; seed = get_opt(mrb); - seed = mrb_random_mt_srand(mrb, seed); + seed = mrb_random_mt_g_srand(mrb, seed); old_seed = mrb_gv_get(mrb, mrb_intern(mrb, GLOBAL_RAND_SEED_KEY)); mrb_gv_set(mrb, mrb_intern(mrb, GLOBAL_RAND_SEED_KEY), seed); return old_seed; @@ -103,32 +168,44 @@ static mrb_value mrb_random_init(mrb_state *mrb, mrb_value self) { mrb_value seed; + + mt_state *t = (mt_state *)mrb_malloc(mrb, sizeof(mt_state)); + t->mti = N + 1; + seed = get_opt(mrb); - seed = mrb_random_mt_srand(mrb, seed); + seed = mrb_random_mt_srand(mrb, t, seed); mrb_iv_set(mrb, self, mrb_intern(mrb, INSTANCE_RAND_SEED_KEY), seed); + mrb_iv_set(mrb, self, mrb_intern(mrb, MT_STATE_KEY), + mrb_obj_value(Data_Wrap_Struct(mrb, mrb->object_class, &mt_state_type, (void*) t))); return self; } static mrb_value mrb_random_rand(mrb_state *mrb, mrb_value self) { mrb_value max; + mt_state *t = mrb_mt_get_context(mrb, self); max = get_opt(mrb); mrb_value seed = mrb_iv_get(mrb, self, mrb_intern(mrb, INSTANCE_RAND_SEED_KEY)); if (mrb_nil_p(seed)) { - mrb_random_mt_srand(mrb, mrb_nil_value()); + mrb_random_mt_srand(mrb, t, mrb_nil_value()); } - return mrb_random_mt_rand(mrb, max); + mrb_iv_set(mrb, self, mrb_intern(mrb, MT_STATE_KEY), + mrb_obj_value(Data_Wrap_Struct(mrb, mrb->object_class, &mt_state_type, (void*) t))); + return mrb_random_mt_rand(mrb, t, max); } static mrb_value mrb_random_srand(mrb_state *mrb, mrb_value self) { mrb_value seed; + mt_state *t = mrb_mt_get_context(mrb, self); seed = get_opt(mrb); - seed = mrb_random_mt_srand(mrb, seed); + seed = mrb_random_mt_srand(mrb, t, seed); mrb_value old_seed = mrb_iv_get(mrb, self, mrb_intern(mrb, INSTANCE_RAND_SEED_KEY)); mrb_iv_set(mrb, self, mrb_intern(mrb, INSTANCE_RAND_SEED_KEY), seed); + mrb_iv_set(mrb, self, mrb_intern(mrb, MT_STATE_KEY), + mrb_obj_value(Data_Wrap_Struct(mrb, mrb->object_class, &mt_state_type, (void*) t))); return old_seed; } |
