ruby-changes:17832
From: nobu <ko1@a...>
Date: Sat, 20 Nov 2010 12:05:05 +0900 (JST)
Subject: [ruby-changes:17832] Ruby:r29843 (trunk): * random.c (random_rand): get rid of overflow.
nobu 2010-11-20 12:04:59 +0900 (Sat, 20 Nov 2010) New Revision: 29843 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=29843 Log: * random.c (random_rand): get rid of overflow. Modified files: trunk/random.c trunk/test/ruby/test_rand.rb Index: test/ruby/test_rand.rb =================================================================== --- test/ruby/test_rand.rb (revision 29842) +++ test/ruby/test_rand.rb (revision 29843) @@ -379,6 +379,8 @@ 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 Index: random.c =================================================================== --- random.c (revision 29842) +++ random.c (revision 29843) @@ -964,11 +964,12 @@ } 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 @@ 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 @@ 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 @@ } } 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 @@ 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) { -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/