From 8554e163557a4f32f6e9427146d594df31ac024a Mon Sep 17 00:00:00 2001 From: nobu Date: Wed, 25 Aug 2010 22:30:03 +0000 Subject: [PATCH] * array.c (rb_ary_{shuffle_bang,sample}): use Random class object. * random.c (try_get_rnd): use default_rand for Random as same as singleton methods. * random.c (rb_random_real): check the range of result. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@29098 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 9 +++++++++ array.c | 4 ++-- random.c | 30 ++++++++++++++++++++++++------ test/ruby/test_array.rb | 13 +++++++++++++ version.h | 4 ++-- 5 files changed, 50 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 198b4462f6..dc596b2159 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Thu Aug 26 07:29:54 2010 Nobuyoshi Nakada + + * array.c (rb_ary_{shuffle_bang,sample}): use Random class object. + + * random.c (try_get_rnd): use default_rand for Random as same as + singleton methods. + + * random.c (rb_random_real): check the range of result. + Wed Aug 25 22:11:11 2010 Tanaka Akira * ext/pathname/pathname.c (path_binread): Pathname#binread translated diff --git a/array.c b/array.c index 172a653aa2..a21f9ef51e 100644 --- a/array.c +++ b/array.c @@ -3748,7 +3748,7 @@ static VALUE sym_random; static VALUE rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary) { - VALUE *ptr, opts, randgen = Qnil; + VALUE *ptr, opts, randgen = rb_cRandom; long i = RARRAY_LEN(ary); if (OPTHASH_GIVEN_P(opts)) { @@ -3811,7 +3811,7 @@ static VALUE rb_ary_sample(int argc, VALUE *argv, VALUE ary) { VALUE nv, result, *ptr; - VALUE opts, randgen = Qnil; + VALUE opts, randgen = rb_cRandom; long n, len, i, j, k, idx[10]; len = RARRAY_LEN(ary); diff --git a/random.c b/random.c index a89fcb8ee9..25c9dea1ff 100644 --- a/random.c +++ b/random.c @@ -229,15 +229,20 @@ static rb_random_t default_rand; static VALUE rand_init(struct MT *mt, VALUE vseed); static VALUE random_seed(void); -static struct MT * -default_mt(void) +static rb_random_t * +rand_start(rb_random_t *r) { - rb_random_t *r = &default_rand; struct MT *mt = &r->mt; if (!genrand_initialized(mt)) { r->seed = rand_init(mt, random_seed()); } - return mt; + return r; +} + +static struct MT * +default_mt(void) +{ + return &rand_start(&default_rand)->mt; } unsigned int @@ -363,6 +368,9 @@ get_rnd(VALUE obj) static rb_random_t * try_get_rnd(VALUE obj) { + if (obj == rb_cRandom) { + return rand_start(&default_rand); + } if (!rb_typeddata_is_kind_of(obj, &random_data_type)) return NULL; return DATA_PTR(obj); } @@ -879,7 +887,13 @@ rb_random_int32(VALUE obj) { rb_random_t *rnd = try_get_rnd(obj); if (!rnd) { - VALUE lim = ULONG2NUM(0xffffffff); +#if SIZEOF_LONG * CHAR_BIT > 32 + VALUE lim = ULONG2NUM(0x100000000); +#elif defined HAVE_LONG_LONG + VALUE lim = ULL2NUM((LONG_LONG)0xffffffff+1); +#else + VALUE lim = rb_big_plus(ULONG2NUM(0xffffffff), INT2FIX(1)); +#endif return NUM2ULONG(rb_funcall2(obj, id_rand, 1, &lim)); } return genrand_int32(&rnd->mt); @@ -891,7 +905,11 @@ rb_random_real(VALUE obj) rb_random_t *rnd = try_get_rnd(obj); if (!rnd) { VALUE v = rb_funcall2(obj, id_rand, 0, 0); - return NUM2DBL(v); + double d = NUM2DBL(v); + if (d < 0.0 || d >= 1.0) { + rb_raise(rb_eRangeError, "random number too big %g", d); + } + return d; } return genrand_real(&rnd->mt); } diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb index f95d8870a1..4a8b700c77 100644 --- a/test/ruby/test_array.rb +++ b/test/ruby/test_array.rb @@ -1899,6 +1899,19 @@ class TestArray < Test::Unit::TestCase end end + def test_shuffle_random + cc = nil + gen = proc do + 10000000 + end + class << gen + alias rand call + end + assert_raise(RangeError) { + [*0..2].shuffle(random: gen) + } + end + def test_sample 100.times do assert([0, 1, 2].include?([2, 1, 0].sample)) diff --git a/version.h b/version.h index 8b0f309ec5..22dd27a585 100644 --- a/version.h +++ b/version.h @@ -1,11 +1,11 @@ #define RUBY_VERSION "1.9.3" -#define RUBY_RELEASE_DATE "2010-08-25" +#define RUBY_RELEASE_DATE "2010-08-26" #define RUBY_PATCHLEVEL -1 #define RUBY_BRANCH_NAME "trunk" #define RUBY_RELEASE_YEAR 2010 #define RUBY_RELEASE_MONTH 8 -#define RUBY_RELEASE_DAY 25 +#define RUBY_RELEASE_DAY 26 #include "ruby/version.h"