summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--array.c4
-rw-r--r--random.c30
-rw-r--r--test/ruby/test_array.rb13
-rw-r--r--version.h4
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 <nobu@ruby-lang.org>
+
+ * 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 <akr@fsij.org>
* 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"