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

ruby-changes:33130

From: marcandre <ko1@a...>
Date: Fri, 28 Feb 2014 11:05:03 +0900 (JST)
Subject: [ruby-changes:33130] marcandRe: r45209 (trunk): * numeric.c: Fix Numeric#step with 0 unit [#9575]

marcandre	2014-02-28 11:04:59 +0900 (Fri, 28 Feb 2014)

  New Revision: 45209

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

  Log:
    * numeric.c: Fix Numeric#step with 0 unit [#9575]

  Modified files:
    trunk/numeric.c
    trunk/test/ruby/test_numeric.rb
Index: numeric.c
===================================================================
--- numeric.c	(revision 45208)
+++ numeric.c	(revision 45209)
@@ -1760,6 +1760,9 @@ ruby_float_step_size(double beg, double https://github.com/ruby/ruby/blob/trunk/numeric.c#L1760
     if (isinf(unit)) {
 	return unit > 0 ? beg <= end : beg >= end;
     }
+    if (unit == 0) {
+	return INFINITY;
+    }
     if (err>0.5) err=0.5;
     if (excl) {
 	if (n<=0) return 0;
@@ -1789,6 +1792,11 @@ ruby_float_step(VALUE from, VALUE to, VA https://github.com/ruby/ruby/blob/trunk/numeric.c#L1792
 	    /* if unit is infinity, i*unit+beg is NaN */
 	    if (n) rb_yield(DBL2NUM(beg));
 	}
+	else if (unit == 0) {
+	    VALUE val = DBL2NUM(beg);
+	    for (;;)
+		rb_yield(val);
+	}
 	else {
 	    for (i=0; i<n; i++) {
 		double d = i*unit+beg;
@@ -1808,7 +1816,9 @@ ruby_num_interval_step_size(VALUE from, https://github.com/ruby/ruby/blob/trunk/numeric.c#L1816
 	long delta, diff;
 
 	diff = FIX2LONG(step);
-	if (!diff) rb_num_zerodiv();
+	if (diff == 0) {
+	    return DBL2NUM(INFINITY);
+	}
 	delta = FIX2LONG(to) - FIX2LONG(from);
 	if (diff < 0) {
 	    diff = -diff;
@@ -1830,7 +1840,11 @@ ruby_num_interval_step_size(VALUE from, https://github.com/ruby/ruby/blob/trunk/numeric.c#L1840
     }
     else {
 	VALUE result;
-	ID cmp = RTEST(rb_funcall(step, '>', 1, INT2FIX(0))) ? '>' : '<';
+	ID cmp = '>';
+	switch (rb_cmpint(rb_num_coerce_cmp(step, INT2FIX(0), id_cmp), step, INT2FIX(0))) {
+	    case 0: return DBL2NUM(INFINITY);
+	    case -1: cmp = '<'; break;
+	}
 	if (RTEST(rb_funcall(from, cmp, 1, to))) return INT2FIX(0);
 	result = rb_funcall(rb_funcall(to, '-', 1, from), id_div, 1, step);
 	if (!excl || RTEST(rb_funcall(rb_funcall(from, '+', 1, rb_funcall(result, '*', 1, step)), cmp, 1, to))) {
@@ -1939,7 +1953,10 @@ num_step(int argc, VALUE *argv, VALUE fr https://github.com/ruby/ruby/blob/trunk/numeric.c#L1953
     RETURN_SIZED_ENUMERATOR(from, argc, argv, num_step_size);
 
     NUM_STEP_SCAN_ARGS(argc, argv, to, step, hash, desc);
-    if (RB_TYPE_P(to, T_FLOAT)) {
+    if (RTEST(rb_num_coerce_cmp(step, INT2FIX(0), id_eq))) {
+	inf = 1;
+    }
+    else if (RB_TYPE_P(to, T_FLOAT)) {
 	double f = RFLOAT_VALUE(to);
 	inf = isinf(f) && (signbit(f) ? desc : !desc);
     }
Index: test/ruby/test_numeric.rb
===================================================================
--- test/ruby/test_numeric.rb	(revision 45208)
+++ test/ruby/test_numeric.rb	(revision 45209)
@@ -283,6 +283,7 @@ class TestNumeric < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_numeric.rb#L283
     assert_step [], [2, 1, 3]
     assert_step [], [-2, -1, -3]
     assert_step [3, 3, 3, 3], [3, by: 0], inf: true
+    assert_step [3, 3, 3, 3], [3, by: 0, to: 42], inf: true
     assert_step [10], [10, 1, -bignum]
 
     assert_step [], [1, 0, Float::INFINITY]
@@ -292,6 +293,19 @@ class TestNumeric < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_numeric.rb#L293
     assert_step [10, 11, 12, 13], [10], inf: true
     assert_step [10, 9, 8, 7], [10, by: -1], inf: true
     assert_step [10, 9, 8, 7], [10, by: -1, to: nil], inf: true
+
+    assert_step [42, 42, 42, 42], [42, by: 0, to: -Float::INFINITY], inf: true
+    assert_step [42, 42, 42, 42], [42, by: 0, to: 42.5], inf: true
+    assert_step [4.2, 4.2, 4.2, 4.2], [4.2, by: 0.0], inf: true
+    assert_step [4.2, 4.2, 4.2, 4.2], [4.2, by: -0.0], inf: true
+    assert_step [42.0, 42.0, 42.0, 42.0], [42, by: 0.0, to: 44], inf: true
+    assert_step [42.0, 42.0, 42.0, 42.0], [42, by: 0.0, to: 0], inf: true
+    assert_step [42.0, 42.0, 42.0, 42.0], [42, by: -0.0, to: 44], inf: true
+
+    assert_step [bignum]*4, [bignum, by: 0], inf: true
+    assert_step [bignum]*4, [bignum, by: 0.0], inf: true
+    assert_step [bignum]*4, [bignum, by: 0, to: bignum+1], inf: true
+    assert_step [bignum]*4, [bignum, by: 0, to: 0], inf: true
   end
 
   def test_num2long

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

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