[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]