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

ruby-changes:19301

From: mrkn <ko1@a...>
Date: Mon, 25 Apr 2011 07:27:53 +0900 (JST)
Subject: [ruby-changes:19301] Ruby:r31340 (trunk): * random.c (random_s_rand, Init_Random): Random.rand should behave as

mrkn	2011-04-25 07:27:39 +0900 (Mon, 25 Apr 2011)

  New Revision: 31340

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=31340

  Log:
    * random.c (random_s_rand, Init_Random): Random.rand should behave as
      Random::DEFAULT.rand rather than Kernel#rand.
    * random.c (rand_range, random_rand): rand_range function extracted
      from random_rand function.
    * random.c (rb_f_rand): accept a Range argument as Random#rand
      [ruby-dev:43427] #4605

  Modified files:
    trunk/ChangeLog
    trunk/random.c
    trunk/test/ruby/test_rand.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 31339)
+++ ChangeLog	(revision 31340)
@@ -1,3 +1,14 @@
+Mon Apr 25 07:18:00 2011  Kenta Murata  <mrkn@m...>
+
+	* random.c (random_s_rand, Init_Random): Random.rand should behave as
+	  Random::DEFAULT.rand rather than Kernel#rand.
+
+	* random.c (rand_range, random_rand): rand_range function extracted
+	  from random_rand function.
+
+	* random.c (rb_f_rand): accept a Range argument as Random#rand
+	  [ruby-dev:43427] #4605
+
 Mon Apr 25 03:31:06 2011  Tadayoshi Funaba  <tadf@d...>
 
 	* lib/time.rb: require 'date'.
Index: test/ruby/test_rand.rb
===================================================================
--- test/ruby/test_rand.rb	(revision 31339)
+++ test/ruby/test_rand.rb	(revision 31340)
@@ -347,19 +347,33 @@
   end
 
   def test_random_range
+    srand(0)
     r = Random.new(0)
-    %w(9 5 8).each {|w| assert_equal(w.to_i, r.rand(5..9)) }
-    %w(-237 731 383).each {|w| assert_equal(w.to_i, r.rand(-1000..1000)) }
+    %w(9 5 8).each {|w|
+      assert_equal(w.to_i, rand(5..9))
+      assert_equal(w.to_i, r.rand(5..9))
+    }
+    %w(-237 731 383).each {|w|
+      assert_equal(w.to_i, rand(-1000..1000))
+      assert_equal(w.to_i, r.rand(-1000..1000))
+    }
     %w(1267650600228229401496703205382
        1267650600228229401496703205384
        1267650600228229401496703205383).each do |w|
+      assert_equal(w.to_i, rand(2**100+5..2**100+9))
       assert_equal(w.to_i, r.rand(2**100+5..2**100+9))
     end
+
+    v = rand(3.1..4)
+    assert_instance_of(Float, v, '[ruby-core:24679]')
+    assert_include(3.1..4, v)
+
     v = r.rand(3.1..4)
     assert_instance_of(Float, v, '[ruby-core:24679]')
     assert_include(3.1..4, v)
 
     now = Time.now
+    assert_equal(now, rand(now..now))
     assert_equal(now, r.rand(now..now))
   end
 
Index: random.c
===================================================================
--- random.c	(revision 31339)
+++ random.c	(revision 31340)
@@ -324,6 +324,7 @@
 }
 
 VALUE rb_cRandom;
+static VALUE rb_Random_DEFAULT;
 #define id_minus '-'
 #define id_plus  '+'
 static ID id_rand, id_bytes;
@@ -1025,6 +1026,88 @@
     return x;
 }
 
+static inline VALUE
+rand_range(struct MT* mt, VALUE range)
+{
+    VALUE beg = Qundef, end = Qundef, vmax, v;
+    int excl = 0;
+
+    if ((v = vmax = range_values(range, &beg, &end, &excl)) == Qfalse)
+	return Qfalse;
+    if (TYPE(vmax) != T_FLOAT && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) {
+	long max;
+	vmax = v;
+	v = Qnil;
+	if (FIXNUM_P(vmax)) {
+	  fixnum:
+	    if ((max = FIX2LONG(vmax) - excl) >= 0) {
+		unsigned long r = limited_rand(mt, (unsigned long)max);
+		v = ULONG2NUM(r);
+	    }
+	}
+	else if (BUILTIN_TYPE(vmax) == T_BIGNUM && RBIGNUM_SIGN(vmax) && !rb_bigzero_p(vmax)) {
+	    vmax = excl ? rb_big_minus(vmax, INT2FIX(1)) : rb_big_norm(vmax);
+	    if (FIXNUM_P(vmax)) {
+		excl = 0;
+		goto fixnum;
+	    }
+	    v = limited_big_rand(mt, RBIGNUM(vmax));
+	}
+    }
+    else if (v = rb_check_to_float(vmax), !NIL_P(v)) {
+	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) {
+		r = genrand_real(mt);
+	    }
+	    else {
+		r = genrand_real2(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) {
+	    v = rb_float_new(0.0);
+	}
+    }
+
+    if (FIXNUM_P(beg) && FIXNUM_P(v)) {
+	long x = FIX2LONG(beg) + FIX2LONG(v);
+	return LONG2NUM(x);
+    }
+    switch (TYPE(v)) {
+      case T_NIL:
+	break;
+      case T_BIGNUM:
+	return rb_big_plus(v, beg);
+      case T_FLOAT: {
+	VALUE f = rb_check_to_float(beg);
+	if (!NIL_P(f)) {
+	    RFLOAT_VALUE(v) += RFLOAT_VALUE(f);
+	    return v;
+	}
+      }
+      default:
+	return rb_funcall2(beg, id_plus, 1, &v);
+    }
+
+    return v;
+}
+
 /*
  * call-seq:
  *     prng.rand -> float
@@ -1076,58 +1159,8 @@
 	else
 	    v = Qnil;
     }
-    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;
-	    vmax = v;
-	    v = Qnil;
-	    if (FIXNUM_P(vmax)) {
-	      fixnum:
-		if ((max = FIX2LONG(vmax) - excl) >= 0) {
-		    unsigned long r = limited_rand(&rnd->mt, (unsigned long)max);
-		    v = ULONG2NUM(r);
-		}
-	    }
-	    else if (BUILTIN_TYPE(vmax) == T_BIGNUM && RBIGNUM_SIGN(vmax) && !rb_bigzero_p(vmax)) {
-		vmax = excl ? rb_big_minus(vmax, INT2FIX(1)) : rb_big_norm(vmax);
-		if (FIXNUM_P(vmax)) {
-		    excl = 0;
-		    goto fixnum;
-		}
-		v = limited_big_rand(&rnd->mt, RBIGNUM(vmax));
-	    }
-	}
-	else if (v = rb_check_to_float(vmax), !NIL_P(v)) {
-	    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) {
-		    r = genrand_real(&rnd->mt);
-		}
-		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) {
-		v = rb_float_new(0.0);
-	    }
-	}
+    else if ((v = rand_range(&rnd->mt, vmax)) != Qfalse) {
+	/* nothing to do */
     }
     else {
 	v = Qnil;
@@ -1138,24 +1171,8 @@
 	rb_str_append(mesg, rb_obj_as_string(argv[0]));
 	rb_exc_raise(rb_exc_new3(rb_eArgError, mesg));
     }
-    if (beg == Qundef) return v;
-    if (FIXNUM_P(beg) && FIXNUM_P(v)) {
-	long x = FIX2LONG(beg) + FIX2LONG(v);
-	return LONG2NUM(x);
-    }
-    switch (TYPE(v)) {
-      case T_BIGNUM:
-	return rb_big_plus(v, beg);
-      case T_FLOAT: {
-	VALUE f = rb_check_to_float(beg);
-	if (!NIL_P(f)) {
-	    RFLOAT_VALUE(v) += RFLOAT_VALUE(f);
-	    return v;
-	}
-      }
-      default:
-	return rb_funcall2(beg, id_plus, 1, &v);
-    }
+
+    return v;
 }
 
 /*
@@ -1201,12 +1218,15 @@
 static VALUE
 rb_f_rand(int argc, VALUE *argv, VALUE obj)
 {
-    VALUE vmax, r;
+    VALUE v, vmax, r;
     struct MT *mt = default_mt();
 
     if (argc == 0) goto zero_arg;
     rb_scan_args(argc, argv, "01", &vmax);
     if (NIL_P(vmax)) goto zero_arg;
+    if ((v = rand_range(mt, vmax)) != Qfalse) {
+	return v;
+    }
     vmax = rb_to_int(vmax);
     if (vmax == INT2FIX(0) || NIL_P(r = rand_int(mt, vmax, 0))) {
       zero_arg:
@@ -1215,6 +1235,12 @@
     return r;
 }
 
+static VALUE
+random_s_rand(int argc, VALUE *argv, VALUE obj)
+{
+    return random_rand(argc, argv, rb_Random_DEFAULT);
+}
+
 static st_index_t hashseed;
 
 static VALUE
@@ -1297,11 +1323,13 @@
     rb_define_private_method(rb_cRandom, "state", random_state, 0);
     rb_define_private_method(rb_cRandom, "left", random_left, 0);
     rb_define_method(rb_cRandom, "==", random_equal, 1);
-    rb_define_const(rb_cRandom, "DEFAULT",
-		    TypedData_Wrap_Struct(rb_cRandom, &random_data_type, &default_rand));
 
+    rb_Random_DEFAULT = TypedData_Wrap_Struct(rb_cRandom, &random_data_type, &default_rand);
+    rb_global_variable(&rb_Random_DEFAULT);
+    rb_define_const(rb_cRandom, "DEFAULT", rb_Random_DEFAULT);
+
     rb_define_singleton_method(rb_cRandom, "srand", rb_f_srand, -1);
-    rb_define_singleton_method(rb_cRandom, "rand", rb_f_rand, -1);
+    rb_define_singleton_method(rb_cRandom, "rand", random_s_rand, -1);
     rb_define_singleton_method(rb_cRandom, "new_seed", random_seed, 0);
     rb_define_private_method(CLASS_OF(rb_cRandom), "state", random_s_state, 0);
     rb_define_private_method(CLASS_OF(rb_cRandom), "left", random_s_left, 0);

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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