diff options
| -rw-r--r-- | include/mruby/numeric.h | 4 | ||||
| -rw-r--r-- | mrbgems/mruby-complex/src/complex.c | 8 | ||||
| -rw-r--r-- | mrbgems/mruby-math/src/math.c | 2 | ||||
| -rw-r--r-- | mrbgems/mruby-random/src/mt19937ar.c | 224 | ||||
| -rw-r--r-- | mrbgems/mruby-random/src/mt19937ar.h | 80 | ||||
| -rw-r--r-- | mrbgems/mruby-random/src/random.c | 226 | ||||
| -rw-r--r-- | mrbgems/mruby-time/include/mruby/time.h | 2 | ||||
| -rw-r--r-- | mrbgems/mruby-time/src/time.c | 91 | ||||
| -rw-r--r-- | src/numeric.c | 1 | ||||
| -rw-r--r-- | src/string.c | 9 |
10 files changed, 185 insertions, 462 deletions
diff --git a/include/mruby/numeric.h b/include/mruby/numeric.h index 34707e441..07266aa10 100644 --- a/include/mruby/numeric.h +++ b/include/mruby/numeric.h @@ -23,8 +23,12 @@ MRB_BEGIN_DECL #define NEGFIXABLE(f) TYPED_NEGFIXABLE(f,mrb_int) #define FIXABLE(f) TYPED_FIXABLE(f,mrb_int) #ifndef MRB_WITHOUT_FLOAT +#ifdef MRB_INT64 +#define FIXABLE_FLOAT(f) ((f)>=-9223372036854775808.0 && (f)<9223372036854775808.0) +#else #define FIXABLE_FLOAT(f) TYPED_FIXABLE(f,mrb_float) #endif +#endif #ifndef MRB_WITHOUT_FLOAT MRB_API mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value val); diff --git a/mrbgems/mruby-complex/src/complex.c b/mrbgems/mruby-complex/src/complex.c index 8a0569d68..d6414a5e1 100644 --- a/mrbgems/mruby-complex/src/complex.c +++ b/mrbgems/mruby-complex/src/complex.c @@ -2,6 +2,10 @@ #include <mruby/class.h> #include <mruby/numeric.h> +#ifdef MRB_WITHOUT_FLOAT +# error Complex conflicts 'MRB_WITHOUT_FLOAT' configuration in your 'build_config.rb' +#endif + struct mrb_complex { mrb_float real; mrb_float imaginary; @@ -91,7 +95,6 @@ complex_s_rect(mrb_state *mrb, mrb_value self) return complex_new(mrb, real, imaginary); } -#ifndef MRB_WITHOUT_FLOAT static mrb_value complex_to_f(mrb_state *mrb, mrb_value self) { @@ -103,7 +106,6 @@ complex_to_f(mrb_state *mrb, mrb_value self) return mrb_float_value(mrb, p->real); } -#endif static mrb_value complex_to_i(mrb_state *mrb, mrb_value self) @@ -137,9 +139,7 @@ void mrb_mruby_complex_gem_init(mrb_state *mrb) mrb_define_method(mrb, mrb->kernel_module, "Complex", complex_s_rect, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); mrb_define_method(mrb, comp, "real", complex_real, MRB_ARGS_NONE()); mrb_define_method(mrb, comp, "imaginary", complex_imaginary, MRB_ARGS_NONE()); -#ifndef MRB_WITHOUT_FLOAT mrb_define_method(mrb, comp, "to_f", complex_to_f, MRB_ARGS_NONE()); -#endif mrb_define_method(mrb, comp, "to_i", complex_to_i, MRB_ARGS_NONE()); mrb_define_method(mrb, comp, "to_c", complex_to_c, MRB_ARGS_NONE()); } diff --git a/mrbgems/mruby-math/src/math.c b/mrbgems/mruby-math/src/math.c index 35fcd0fa6..c6d4ca414 100644 --- a/mrbgems/mruby-math/src/math.c +++ b/mrbgems/mruby-math/src/math.c @@ -5,7 +5,7 @@ */ #ifdef MRB_WITHOUT_FLOAT -# error Conflict 'MRB_WITHOUT_FLOAT' configuration in your 'build_config.rb' +# error Math conflicts 'MRB_WITHOUT_FLOAT' configuration in your 'build_config.rb' #endif #include <mruby.h> diff --git a/mrbgems/mruby-random/src/mt19937ar.c b/mrbgems/mruby-random/src/mt19937ar.c deleted file mode 100644 index 405bd5c20..000000000 --- a/mrbgems/mruby-random/src/mt19937ar.c +++ /dev/null @@ -1,224 +0,0 @@ -/* -** mt19937ar.c - MT Random functions -** -** Copyright (C) 1997 - 2016, Makoto Matsumoto and Takuji Nishimura, -** All rights reserved. -** -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -** -** [ MIT license: http://www.opensource.org/licenses/mit-license.php ] -** -** Any feedback is very welcome. -** http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html -** email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) -** -** This version is modified by mruby developers. If you see any problem, -** contact us first at https://github.com/mruby/mruby/issues -*/ - -#include <mruby.h> -#include "mt19937ar.h" - -/* Period parameters */ -/* #define N 624 */ -#define M 397 -#define MATRIX_A 0x9908b0dfUL /* constant vector a */ -#define UPPER_MASK 0x80000000UL /* most significant w-r bits */ -#define LOWER_MASK 0x7fffffffUL /* least significant r bits */ - -#if 0 /* dead_code */ -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 */ -#endif /* dead_code */ - -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 const 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.double_ = t->gen.int_*(1.0/4294967295.0); - return t->gen.double_; - /* divided by 2^32-1 */ -} - -#if 0 /* dead_code */ -/* initializes mt[N] with a seed */ -void init_genrand(unsigned long s) -{ - mt[0]= s & 0xffffffffUL; - for (mti=1; mti<N; mti++) { - mt[mti] = (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); - /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ - /* In the previous versions, MSBs of the seed affect */ - /* only MSBs of the array mt[]. */ - /* 2002/01/09 modified by Makoto Matsumoto */ - mt[mti] &= 0xffffffffUL; - /* for >32 bit machines */ - } -} - -/* initialize by an array with array-length */ -/* init_key is the array for initializing keys */ -/* key_length is its length */ -/* slight change for C++, 2004/2/26 */ -void init_by_array(unsigned long init_key[], int key_length) -{ - int i, j, k; - init_genrand(19650218UL); - i=1; j=0; - k = (N>key_length ? N : key_length); - for (; k; k--) { - mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) - + init_key[j] + j; /* non linear */ - mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ - i++; j++; - if (i>=N) { mt[0] = mt[N-1]; i=1; } - if (j>=key_length) j=0; - } - for (k=N-1; k; k--) { - mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) - - i; /* non linear */ - mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ - i++; - if (i>=N) { mt[0] = mt[N-1]; i=1; } - } - - mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ -} - -/* generates a random number on [0,0xffffffff]-interval */ -unsigned long genrand_int32(void) -{ - unsigned long y; - static const unsigned long mag01[2]={0x0UL, MATRIX_A}; - /* mag01[x] = x * MATRIX_A for x=0,1 */ - - if (mti >= N) { /* generate N words at one time */ - int kk; - - if (mti == N+1) /* if init_genrand() has not been called, */ - init_genrand(5489UL); /* a default initial seed is used */ - - for (kk=0;kk<N-M;kk++) { - y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); - mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL]; - } - for (;kk<N-1;kk++) { - y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); - mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL]; - } - y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); - mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; - - mti = 0; - } - - y = mt[mti++]; - - /* Tempering */ - y ^= (y >> 11); - y ^= (y << 7) & 0x9d2c5680UL; - y ^= (y << 15) & 0xefc60000UL; - y ^= (y >> 18); - - return y; -} - -/* generates a random number on [0,0x7fffffff]-interval */ -long genrand_int31(void) -{ - return (long)(genrand_int32()>>1); -} - -/* generates a random number on [0,1]-real-interval */ -double genrand_real1(void) -{ - return genrand_int32()*(1.0/4294967295.0); - /* divided by 2^32-1 */ -} - -/* generates a random number on [0,1)-real-interval */ -double genrand_real2(void) -{ - return genrand_int32()*(1.0/4294967296.0); - /* divided by 2^32 */ -} - -/* generates a random number on (0,1)-real-interval */ -double genrand_real3(void) -{ - return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0); - /* divided by 2^32 */ -} - -/* generates a random number on [0,1) with 53-bit resolution*/ -double genrand_res53(void) -{ - unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6; - return(a*67108864.0+b)*(1.0/9007199254740992.0); -} -/* These real versions are due to Isaku Wada, 2002/01/09 added */ -#endif /* dead_code */ diff --git a/mrbgems/mruby-random/src/mt19937ar.h b/mrbgems/mruby-random/src/mt19937ar.h deleted file mode 100644 index 7d382320d..000000000 --- a/mrbgems/mruby-random/src/mt19937ar.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -** mt19937ar.h - MT Random functions -** -** Copyright (C) 1997 - 2016, Makoto Matsumoto and Takuji Nishimura, -** All rights reserved. -** -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -** -** [ MIT license: http://www.opensource.org/licenses/mit-license.php ] -** -** Any feedback is very welcome. -** http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html -** email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) -** -** This version is modified by mruby developers. If you see any problem, -** contact us first at https://github.com/mruby/mruby/issues -*/ - -#define N 624 - -typedef struct { - unsigned long mt[N]; - int mti; - union { - unsigned long int_; - double double_; - } gen; - - mrb_int seed; - mrb_bool has_seed : 1; -} 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); - -/* initialize by an array with array-length */ -/* init_key is the array for initializing keys */ -/* key_length is its length */ -/* slight change for C++, 2004/2/26 */ -void init_by_array(unsigned long init_key[], int key_length); - -/* generates a random number on [0,0xffffffff]-interval */ -unsigned long genrand_int32(void); - -/* generates a random number on [0,0x7fffffff]-interval */ -long genrand_int31(void); - -/* These real versions are due to Isaku Wada, 2002/01/09 added */ -/* generates a random number on [0,1]-real-interval */ -double genrand_real1(void); - -/* generates a random number on [0,1)-real-interval */ -double genrand_real2(void); - -/* generates a random number on (0,1)-real-interval */ -double genrand_real3(void); - -/* generates a random number on [0,1) with 53-bit resolution*/ -double genrand_res53(void); diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index 99f2b02e4..bca565b17 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -4,71 +4,86 @@ ** See Copyright Notice in mruby.h */ -#ifdef MRB_WITHOUT_FLOAT -# error Conflict 'MRB_WITHOUT_FLOAT' configuration in your 'build_config.rb' -#endif - #include <mruby.h> #include <mruby/variable.h> #include <mruby/class.h> #include <mruby/data.h> #include <mruby/array.h> -#include "mt19937ar.h" #include <time.h> -static char const MT_STATE_KEY[] = "$mrb_i_mt_state"; +static char const RAND_STATE_KEY[] = "$mrb_i_rand_state"; -static const struct mrb_data_type mt_state_type = { - MT_STATE_KEY, mrb_free, +static const struct mrb_data_type rand_state_type = { + RAND_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); +typedef struct rand_state { + uint32_t seed[4]; +} rand_state; static void -mt_srand(mt_state *t, unsigned long seed) +rand_init(rand_state *t) { - mrb_random_init_genrand(t, seed); + t->seed[0] = 123456789; + t->seed[1] = 362436069; + t->seed[2] = 521288629; + t->seed[3] = 88675123; } -static unsigned long -mt_rand(mt_state *t) +static uint32_t +rand_seed(rand_state *t, uint32_t seed) { - return mrb_random_genrand_int32(t); + uint32_t old_seed = t->seed[3]; + rand_init(t); + t->seed[3] = seed; + return old_seed; } -static double -mt_rand_real(mt_state *t) +static uint32_t +rand_uint32(rand_state *state) { - return mrb_random_genrand_real1(t); + uint32_t *seed = state->seed; + uint32_t x = seed[0]; + uint32_t y = seed[1]; + uint32_t z = seed[2]; + uint32_t w = seed[3]; + uint32_t t; + + t = x ^ (x << 11); + x = y; y = z; z = w; + w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); + seed[0] = x; + seed[1] = y; + seed[2] = z; + seed[3] = w; + + return w; } -static mrb_value -mrb_random_mt_srand(mrb_state *mrb, mt_state *t, mrb_value seed) +#ifndef MRB_WITHOUT_FLOAT +static double +rand_real(rand_state *t) { - 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; + uint32_t x = rand_uint32(t); + return x*(1.0/4294967295.0); } +#endif static mrb_value -mrb_random_mt_rand(mrb_state *mrb, mt_state *t, mrb_value max) +random_rand(mrb_state *mrb, rand_state *t, mrb_value max) { mrb_value value; if (mrb_fixnum(max) == 0) { - value = mrb_float_value(mrb, mt_rand_real(t)); +#ifndef MRB_WITHOUT_FLOAT + value = mrb_float_value(mrb, rand_real(t)); +#else + mrb_raise(mrb, E_ARGUMENT_ERROR, "Float not supported"); +#endif } else { - value = mrb_fixnum_value(mt_rand(t) % mrb_fixnum(max)); + value = mrb_fixnum_value(rand_uint32(t) % mrb_fixnum(max)); } return value; @@ -95,105 +110,70 @@ get_opt(mrb_state* mrb) } static mrb_value -get_random(mrb_state *mrb) { +random_default(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) +static rand_state * +random_state(mrb_state *mrb) { - mrb_value random = get_random(mrb); - return mrb_random_srand(mrb, random); + mrb_value random_val = random_default(mrb); + return DATA_GET_PTR(mrb, random_val, &rand_state_type, rand_state); } static mrb_value -mrb_random_init(mrb_state *mrb, mrb_value self) +random_m_init(mrb_state *mrb, mrb_value self) { mrb_value seed; - mt_state *t; + rand_state *t; seed = get_opt(mrb); - /* avoid memory leaks */ - t = (mt_state*)DATA_PTR(self); - if (t) { - mrb_free(mrb, t); + t = (rand_state*)DATA_PTR(self); + if (t == NULL) { + t = (rand_state *)mrb_malloc(mrb, sizeof(rand_state)); + mrb_data_init(self, t, &rand_state_type); } - 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; + rand_init(t); } else { - mrb_assert(mrb_fixnum_p(seed)); - t->has_seed = TRUE; - t->seed = mrb_fixnum(seed); + rand_seed(t, (uint32_t)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) +random_m_rand(mrb_state *mrb, mrb_value self) { mrb_value max; - mt_state *t = DATA_GET_PTR(mrb, self, &mt_state_type, mt_state); + rand_state *t = DATA_GET_PTR(mrb, self, &rand_state_type, rand_state); max = get_opt(mrb); - mrb_random_rand_seed(mrb, t); - return mrb_random_mt_rand(mrb, t, max); + return random_rand(mrb, t, max); } static mrb_value -mrb_random_srand(mrb_state *mrb, mrb_value self) +random_m_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; + uint32_t seed; + uint32_t old_seed; + mrb_value sv; + rand_state *t = DATA_GET_PTR(mrb, self, &rand_state_type, rand_state); + + sv = get_opt(mrb); + if (mrb_nil_p(sv)) { + seed = (uint32_t)time(NULL) + rand_uint32(t); } else { - mrb_assert(mrb_fixnum_p(seed)); - t->has_seed = TRUE; - t->seed = mrb_fixnum(seed); + seed = (uint32_t)mrb_fixnum(sv); } + old_seed = rand_seed(t, seed); - return old_seed; + return mrb_fixnum_value((mrb_int)old_seed); } /* @@ -207,25 +187,23 @@ static mrb_value mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary) { mrb_int i; - mt_state *random = NULL; + mrb_value max; + rand_state *random = NULL; if (RARRAY_LEN(ary) > 1) { - mrb_get_args(mrb, "|d", &random, &mt_state_type); + mrb_get_args(mrb, "|d", &random, &rand_state_type); if (random == NULL) { - random = get_random_state(mrb); + random = random_state(mrb); } - mrb_random_rand_seed(mrb, random); - mrb_ary_modify(mrb, mrb_ary_ptr(ary)); - + max = mrb_fixnum_value(RARRAY_LEN(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)))); + j = mrb_fixnum(random_rand(mrb, random, max)); tmp = ptr[i]; ptr[i] = ptr[j]; @@ -272,15 +250,13 @@ mrb_ary_sample(mrb_state *mrb, mrb_value ary) { mrb_int n = 0; mrb_bool given; - mt_state *random = NULL; + rand_state *random = NULL; mrb_int len; - mrb_get_args(mrb, "|i?d", &n, &given, &random, &mt_state_type); + mrb_get_args(mrb, "|i?d", &n, &given, &random, &rand_state_type); if (random == NULL) { - random = get_random_state(mrb); + random = random_state(mrb); } - mrb_random_rand_seed(mrb, random); - mt_rand(random); len = RARRAY_LEN(ary); if (!given) { /* pick one element */ switch (len) { @@ -289,7 +265,7 @@ mrb_ary_sample(mrb_state *mrb, mrb_value ary) case 1: return RARRAY_PTR(ary)[0]; default: - return RARRAY_PTR(ary)[mt_rand(random) % len]; + return RARRAY_PTR(ary)[rand_uint32(random) % len]; } } else { @@ -304,7 +280,7 @@ mrb_ary_sample(mrb_state *mrb, mrb_value ary) for (;;) { retry: - r = mt_rand(random) % len; + r = (mrb_int)rand_uint32(random) % len; for (j=0; j<i; j++) { if (mrb_fixnum(RARRAY_PTR(result)[j]) == r) { @@ -322,23 +298,37 @@ mrb_ary_sample(mrb_state *mrb, mrb_value ary) } } +static mrb_value +random_f_rand(mrb_state *mrb, mrb_value self) +{ + rand_state *t = random_state(mrb); + return random_rand(mrb, t, get_opt(mrb)); +} + +static mrb_value +random_f_srand(mrb_state *mrb, mrb_value self) +{ + mrb_value random = random_default(mrb); + return random_m_srand(mrb, random); +} + void mrb_mruby_random_gem_init(mrb_state *mrb) { struct RClass *random; struct RClass *array = mrb->array_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)); + 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)); 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_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_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, 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, array, "shuffle", mrb_ary_shuffle, MRB_ARGS_OPT(1)); mrb_define_method(mrb, array, "shuffle!", mrb_ary_shuffle_bang, MRB_ARGS_OPT(1)); diff --git a/mrbgems/mruby-time/include/mruby/time.h b/mrbgems/mruby-time/include/mruby/time.h index d71f4ccd3..9b1cdfacd 100644 --- a/mrbgems/mruby-time/include/mruby/time.h +++ b/mrbgems/mruby-time/include/mruby/time.h @@ -18,7 +18,7 @@ typedef enum mrb_timezone { MRB_TIMEZONE_LAST = 3 } mrb_timezone; -MRB_API mrb_value mrb_time_at(mrb_state *mrb, double sec, double usec, mrb_timezone timezone); +MRB_API mrb_value mrb_time_at(mrb_state *mrb, mrb_int sec, mrb_int usec, mrb_timezone timezone); MRB_END_DECL diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c index 4f0afd6c6..3c0ab6ca0 100644 --- a/mrbgems/mruby-time/src/time.c +++ b/mrbgems/mruby-time/src/time.c @@ -4,10 +4,6 @@ ** See Copyright Notice in mruby.h */ -#ifdef MRB_WITHOUT_FLOAT -# error Conflict 'MRB_WITHOUT_FLOAT' configuration in your 'build_config.rb' -#endif - #include <math.h> #include <time.h> #include <mruby.h> @@ -202,6 +198,18 @@ struct mrb_time { static const struct mrb_data_type mrb_time_type = { "Time", mrb_free }; +#ifndef MRB_WITHOUT_FLOAT +void mrb_check_num_exact(mrb_state *mrb, mrb_float num); +typedef mrb_float mrb_sec; +#define time_sec_args(mrb, v) mrb_get_args(mrb, "f", v); +#define mrb_sec_value(mrb, sec) mrb_float_value(mrb, sec) +#else +#define mrb_check_num_exact(mrb, num) +typedef mrb_int mrb_sec; +#define time_sec_args(mrb, v) mrb_get_args(mrb, "i", v); +#define mrb_sec_value(mrb, sec) mrb_fixnum_value(sec) +#endif + /** Updates the datetime of a mrb_time based on it's timezone and seconds setting. Returns self on success, NULL of failure. if `dealloc` is set `true`, it frees `self` on error. */ @@ -218,10 +226,10 @@ time_update_datetime(mrb_state *mrb, struct mrb_time *self, int dealloc) aid = localtime_r(&t, &self->datetime); } if (!aid) { - mrb_float sec = (mrb_float)t; + mrb_sec sec = (mrb_sec)t; if (dealloc) mrb_free(mrb, self); - mrb_raisef(mrb, E_ARGUMENT_ERROR, "%S out of Time range", mrb_float_value(mrb, sec)); + mrb_raisef(mrb, E_ARGUMENT_ERROR, "%S out of Time range", mrb_sec_value(mrb, sec)); /* not reached */ return NULL; } @@ -238,36 +246,33 @@ mrb_time_wrap(mrb_state *mrb, struct RClass *tc, struct mrb_time *tm) return mrb_obj_value(Data_Wrap_Struct(mrb, tc, &mrb_time_type, tm)); } -void mrb_check_num_exact(mrb_state *mrb, mrb_float num); - /* Allocates a mrb_time object and initializes it. */ static struct mrb_time* -time_alloc(mrb_state *mrb, double sec, double usec, enum mrb_timezone timezone) +time_alloc(mrb_state *mrb, mrb_sec sec, mrb_int usec, enum mrb_timezone timezone) { struct mrb_time *tm; time_t tsec = 0; - mrb_check_num_exact(mrb, (mrb_float)sec); - mrb_check_num_exact(mrb, (mrb_float)usec); + mrb_check_num_exact(mrb, sec); #ifndef MRB_TIME_T_UINT - if (sizeof(time_t) == 4 && (sec > (double)INT32_MAX || (double)INT32_MIN > sec)) { + if (sizeof(time_t) == 4 && (sec > (mrb_sec)INT32_MAX || (mrb_sec)INT32_MIN > sec)) { goto out_of_range; } - if (sizeof(time_t) == 8 && (sec > (double)INT64_MAX || (double)INT64_MIN > sec)) { + if (sizeof(time_t) == 8 && (sec > (mrb_sec)INT64_MAX || (mrb_sec)INT64_MIN > sec)) { goto out_of_range; } #else - if (sizeof(time_t) == 4 && (sec > (double)UINT32_MAX || (double)0 > sec)) { + if (sizeof(time_t) == 4 && (sec > (mrb_sec)UINT32_MAX || (mrb_sec)0 > sec)) { goto out_of_range; } - if (sizeof(time_t) == 8 && (sec > (double)UINT64_MAX || (double)0 > sec)) { + if (sizeof(time_t) == 8 && (sec > (mrb_sec)UINT64_MAX || (mrb_sec)0 > sec)) { goto out_of_range; } #endif tsec = (time_t)sec; - if ((sec > 0 && tsec < 0) || (sec < 0 && (double)tsec > sec)) { + if ((sec > 0 && tsec < 0) || (sec < 0 && (mrb_sec)tsec > sec)) { out_of_range: - mrb_raisef(mrb, E_ARGUMENT_ERROR, "%S out of Time range", mrb_float_value(mrb, sec)); + mrb_raisef(mrb, E_ARGUMENT_ERROR, "%S out of Time range", mrb_sec_value(mrb, sec)); } tm = (struct mrb_time *)mrb_malloc(mrb, sizeof(struct mrb_time)); tm->sec = tsec; @@ -289,7 +294,7 @@ time_alloc(mrb_state *mrb, double sec, double usec, enum mrb_timezone timezone) } static mrb_value -mrb_time_make(mrb_state *mrb, struct RClass *c, double sec, double usec, enum mrb_timezone timezone) +mrb_time_make(mrb_state *mrb, struct RClass *c, mrb_sec sec, mrb_int usec, enum mrb_timezone timezone) { return mrb_time_wrap(mrb, c, time_alloc(mrb, sec, usec, timezone)); } @@ -351,7 +356,7 @@ mrb_time_now(mrb_state *mrb, mrb_value self) } MRB_API mrb_value -mrb_time_at(mrb_state *mrb, double sec, double usec, enum mrb_timezone zone) +mrb_time_at(mrb_state *mrb, mrb_int sec, mrb_int usec, enum mrb_timezone zone) { return mrb_time_make(mrb, mrb_class_get(mrb, "Time"), sec, usec, zone); } @@ -361,10 +366,16 @@ mrb_time_at(mrb_state *mrb, double sec, double usec, enum mrb_timezone zone) static mrb_value mrb_time_at_m(mrb_state *mrb, mrb_value self) { - mrb_float f, f2 = 0; + mrb_sec sec; + mrb_int usec = 0; - mrb_get_args(mrb, "f|f", &f, &f2); - return mrb_time_make(mrb, mrb_class_ptr(self), f, f2, MRB_TIMEZONE_LOCAL); +#ifndef MRB_WITHOUT_FLOAT + mrb_get_args(mrb, "f|i", &sec, &usec); +#else + mrb_get_args(mrb, "i|i", &sec, &usec); +#endif + + return mrb_time_make(mrb, mrb_class_ptr(self), sec, usec, MRB_TIMEZONE_LOCAL); } static struct mrb_time* @@ -401,7 +412,7 @@ time_mktime(mrb_state *mrb, mrb_int ayear, mrb_int amonth, mrb_int aday, mrb_raise(mrb, E_ARGUMENT_ERROR, "Not a valid time."); } - return time_alloc(mrb, (double)nowsecs, (double)ausec, timezone); + return time_alloc(mrb, (mrb_sec)nowsecs, ausec, timezone); } /* 15.2.19.6.2 */ @@ -487,18 +498,18 @@ mrb_time_cmp(mrb_state *mrb, mrb_value self) static mrb_value mrb_time_plus(mrb_state *mrb, mrb_value self) { - mrb_float f; + mrb_sec f; struct mrb_time *tm; - mrb_get_args(mrb, "f", &f); + time_sec_args(mrb, &f); tm = time_get_ptr(mrb, self); - return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec+f, (double)tm->usec, tm->timezone); + return mrb_time_make(mrb, mrb_obj_class(mrb, self), (mrb_sec)tm->sec+f, (mrb_int)tm->usec, tm->timezone); } static mrb_value mrb_time_minus(mrb_state *mrb, mrb_value self) { - mrb_float f; + mrb_sec f; mrb_value other; struct mrb_time *tm, *tm2; @@ -506,13 +517,19 @@ mrb_time_minus(mrb_state *mrb, mrb_value self) tm = time_get_ptr(mrb, self); tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time); if (tm2) { - f = (mrb_float)(tm->sec - tm2->sec) - + (mrb_float)(tm->usec - tm2->usec) / 1.0e6; +#ifndef MRB_WITHOUT_FLOAT + f = (mrb_sec)(tm->sec - tm2->sec) + + (mrb_sec)(tm->usec - tm2->usec) / 1.0e6; return mrb_float_value(mrb, f); +#else + f = tm->sec - tm2->sec; + if (tm->usec < tm2->usec) f--; + return mrb_fixnum_value(f); +#endif } else { - mrb_get_args(mrb, "f", &f); - return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec-f, (double)tm->usec, tm->timezone); + time_sec_args(mrb, &f); + return mrb_time_make(mrb, mrb_obj_class(mrb, self), (mrb_sec)tm->sec-f, (mrb_int)tm->usec, tm->timezone); } } @@ -769,6 +786,7 @@ mrb_time_sec(mrb_state *mrb, mrb_value self) return mrb_fixnum_value(tm->datetime.tm_sec); } +#ifndef MRB_WITHOUT_FLOAT /* 15.2.19.7.24 */ /* Returns a Float with the time since the epoch in seconds. */ static mrb_value @@ -779,32 +797,37 @@ mrb_time_to_f(mrb_state *mrb, mrb_value self) tm = time_get_ptr(mrb, self); return mrb_float_value(mrb, (mrb_float)tm->sec + (mrb_float)tm->usec/1.0e6); } +#endif /* 15.2.19.7.25 */ -/* Returns a Fixnum with the time since the epoch in seconds. */ +/* Returns an Integer with the time since the epoch in seconds. */ static mrb_value mrb_time_to_i(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; tm = time_get_ptr(mrb, self); +#ifndef MRB_WITHOUT_FLOAT if (tm->sec > MRB_INT_MAX || tm->sec < MRB_INT_MIN) { return mrb_float_value(mrb, (mrb_float)tm->sec); } +#endif return mrb_fixnum_value((mrb_int)tm->sec); } /* 15.2.19.7.26 */ -/* Returns a Float with the time since the epoch in microseconds. */ +/* Returns an Integer with the time since the epoch in microseconds. */ static mrb_value mrb_time_usec(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; tm = time_get_ptr(mrb, self); +#ifndef MRB_WITHOUT_FLOAT if (tm->usec > MRB_INT_MAX || tm->usec < MRB_INT_MIN) { return mrb_float_value(mrb, (mrb_float)tm->usec); } +#endif return mrb_fixnum_value((mrb_int)tm->usec); } @@ -882,7 +905,9 @@ mrb_mruby_time_gem_init(mrb_state* mrb) mrb_define_method(mrb, tc, "sec" , mrb_time_sec, MRB_ARGS_NONE()); /* 15.2.19.7.23 */ mrb_define_method(mrb, tc, "to_i", mrb_time_to_i, MRB_ARGS_NONE()); /* 15.2.19.7.25 */ +#ifndef MRB_WITHOUT_FLOAT mrb_define_method(mrb, tc, "to_f", mrb_time_to_f, MRB_ARGS_NONE()); /* 15.2.19.7.24 */ +#endif mrb_define_method(mrb, tc, "usec", mrb_time_usec, MRB_ARGS_NONE()); /* 15.2.19.7.26 */ mrb_define_method(mrb, tc, "utc" , mrb_time_utc, MRB_ARGS_NONE()); /* 15.2.19.7.27 */ mrb_define_method(mrb, tc, "utc?", mrb_time_utc_p,MRB_ARGS_NONE()); /* 15.2.19.7.28 */ diff --git a/src/numeric.c b/src/numeric.c index 4288df44a..a1299a74f 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -702,6 +702,7 @@ flo_round(mrb_state *mrb, mrb_value num) f = 1.0; i = ndigits >= 0 ? ndigits : -ndigits; + if (ndigits > DBL_DIG+2) return num; while (--i >= 0) f = f*10.0; diff --git a/src/string.c b/src/string.c index de8a15ba9..ecbe21a22 100644 --- a/src/string.c +++ b/src/string.c @@ -2789,6 +2789,9 @@ mrb_str_inspect(mrb_state *mrb, mrb_value str) const char *p, *pend; char buf[CHAR_ESC_LEN + 1]; mrb_value result = mrb_str_new_lit(mrb, "\""); +#ifdef MRB_UTF8_STRING + uint32_t ascii_flag = MRB_STR_ASCII; +#endif p = RSTRING_PTR(str); pend = RSTRING_END(str); for (;p < pend; p++) { @@ -2805,6 +2808,7 @@ mrb_str_inspect(mrb_state *mrb, mrb_value str) } mrb_str_cat(mrb, result, buf, clen); p += clen-1; + ascii_flag = 0; continue; } #endif @@ -2846,7 +2850,10 @@ mrb_str_inspect(mrb_state *mrb, mrb_value str) } } mrb_str_cat_lit(mrb, result, "\""); - RSTR_COPY_ASCII_FLAG(mrb_str_ptr(result), mrb_str_ptr(str)); +#ifdef MRB_UTF8_STRING + mrb_str_ptr(str)->flags |= ascii_flag; + mrb_str_ptr(result)->flags |= ascii_flag; +#endif return result; } |
