summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/mruby/numeric.h4
-rw-r--r--mrbgems/mruby-complex/src/complex.c8
-rw-r--r--mrbgems/mruby-math/src/math.c2
-rw-r--r--mrbgems/mruby-random/src/mt19937ar.c224
-rw-r--r--mrbgems/mruby-random/src/mt19937ar.h80
-rw-r--r--mrbgems/mruby-random/src/random.c226
-rw-r--r--mrbgems/mruby-time/include/mruby/time.h2
-rw-r--r--mrbgems/mruby-time/src/time.c91
-rw-r--r--src/numeric.c1
-rw-r--r--src/string.c9
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;
}