diff --git a/numeric.c b/numeric.c index 58dad48fe2..3200a341b4 100644 --- a/numeric.c +++ b/numeric.c @@ -1760,6 +1760,9 @@ ruby_float_step_size(double beg, double end, double unit, int excl) 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, VALUE step, int excl) /* 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', 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 from) 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); } diff --git a/test/ruby/test_numeric.rb b/test/ruby/test_numeric.rb index 223bf92138..90d4d9ffea 100644 --- a/test/ruby/test_numeric.rb +++ b/test/ruby/test_numeric.rb @@ -283,6 +283,7 @@ class TestNumeric < Test::Unit::TestCase 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 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