From 99aaee351e42ca0d823ca959241668dc2eb77df2 Mon Sep 17 00:00:00 2001 From: nobu Date: Sat, 20 Nov 2010 03:04:59 +0000 Subject: [PATCH] * random.c (random_rand): get rid of overflow. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@29843 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- random.c | 23 +++++++++++++++++++---- test/ruby/test_rand.rb | 2 ++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/random.c b/random.c index dbc77d0532..5701ba7f8d 100644 --- a/random.c +++ b/random.c @@ -964,11 +964,12 @@ rb_random_bytes(VALUE obj, long n) } static VALUE -range_values(VALUE vmax, VALUE *begp, int *exclp) +range_values(VALUE vmax, VALUE *begp, VALUE *endp, int *exclp) { VALUE end, r; if (!rb_range_values(vmax, begp, &end, exclp)) return Qfalse; + if (endp) *endp = end; if (!rb_respond_to(end, id_minus)) return Qfalse; r = rb_funcall2(end, id_minus, 1, begp); if (NIL_P(r)) return Qfalse; @@ -1052,7 +1053,7 @@ static VALUE random_rand(int argc, VALUE *argv, VALUE obj) { rb_random_t *rnd = get_rnd(obj); - VALUE vmax, beg = Qundef, v; + VALUE vmax, beg = Qundef, end, v; int excl = 0; if (argc == 0) { @@ -1075,7 +1076,7 @@ random_rand(int argc, VALUE *argv, VALUE obj) else v = Qnil; } - else if ((v = range_values(vmax, &beg, &excl)) != Qfalse) { + else if ((v = range_values(vmax, &beg, &end, &excl)) != Qfalse) { vmax = v; if (TYPE(vmax) != T_FLOAT && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) { long max; @@ -1098,7 +1099,18 @@ random_rand(int argc, VALUE *argv, VALUE obj) } } else if (v = rb_check_to_float(vmax), !NIL_P(v)) { - double max = float_value(v), r; + int scale = 1; + double max = RFLOAT_VALUE(v), mid = 0.5, r; + if (isinf(max)) { + double min = float_value(rb_to_float(beg)) / 2.0; + max = float_value(rb_to_float(end)) / 2.0; + scale = 2; + mid = max + min; + max -= min; + } + else { + float_value(v); + } v = Qnil; if (max > 0.0) { if (excl) { @@ -1107,6 +1119,9 @@ random_rand(int argc, VALUE *argv, VALUE obj) else { r = genrand_real2(&rnd->mt); } + if (scale > 1) { + return rb_float_new(+(+(+(r - 0.5) * max) * scale) + mid); + } v = rb_float_new(r * max); } else if (max == 0.0 && !excl) { diff --git a/test/ruby/test_rand.rb b/test/ruby/test_rand.rb index c3282cf804..5ff2fe5e68 100644 --- a/test/ruby/test_rand.rb +++ b/test/ruby/test_rand.rb @@ -379,6 +379,8 @@ END assert_in_delta(1.7151893663724195, r.rand(1.0...2.0), 0.0001, '[ruby-core:24655]') assert_in_delta(7.027633760716439, r.rand(1.0...11.0), 0.0001, '[ruby-core:24655]') assert_in_delta(3.0897663659937937, r.rand(2.0...4.0), 0.0001, '[ruby-core:24655]') + + assert_nothing_raised {r.rand(-Float::MAX..Float::MAX)} end def test_random_equal