From bdc00ba604b74646fbf551a544d973466ce39558 Mon Sep 17 00:00:00 2001 From: matz Date: Sun, 6 Apr 2008 17:11:50 +0000 Subject: * bignum.c (rb_cmpint): moved from compar.c, to check bignum zero. * range.c (range_step): add step for each iteration if begin and end are numeric. [ruby-core:15990] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@15911 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- range.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'range.c') diff --git a/range.c b/range.c index be6b3e52bb..078219e184 100644 --- a/range.c +++ b/range.c @@ -223,10 +223,12 @@ range_hash(VALUE range) } static void -range_each_func(VALUE range, VALUE (*func) (VALUE, void *), VALUE v, VALUE e, - void *arg) +range_each_func(VALUE range, VALUE (*func) (VALUE, void *), void *arg) { int c; + VALUE b = RANGE_BEG(range); + VALUE e = RANGE_END(range); + VALUE v; if (EXCL(range)) { while (r_lt(v, e)) { @@ -267,7 +269,7 @@ step_i(VALUE i, void *arg) * rng.step(n=1) {| obj | block } => rng * * Iterates over rng, passing each nth element to the block. If - * the range contains numbers or strings, natural ordering is used. Otherwise + * the range contains numbers, n is added for each iteration. Otherwise * step invokes succ to iterate through range * elements. The following code uses class Xs, which is defined * in the class-level documentation. @@ -293,8 +295,9 @@ step_i(VALUE i, void *arg) static VALUE range_step(int argc, VALUE *argv, VALUE range) { - VALUE b, e, step; + VALUE b, e, step, tmp, c; long unit; + int nv; RETURN_ENUMERATOR(range, argc, argv); @@ -312,14 +315,15 @@ range_step(int argc, VALUE *argv, VALUE range) else { VALUE tmp = rb_to_int(step); unit = rb_cmpint(tmp, step, INT2FIX(0)); - step = tmp; } } if (unit < 0) { rb_raise(rb_eArgError, "step can't be negative"); } - if (unit == 0) + if (unit == 0) { rb_raise(rb_eArgError, "step can't be 0"); + } + if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */ long end = FIX2LONG(e); long i; @@ -332,9 +336,20 @@ range_step(int argc, VALUE *argv, VALUE range) if (i + unit < i) break; i += unit; } + + } + else if (rb_obj_is_kind_of(b, rb_cNumeric) || + !NIL_P(rb_check_to_integer(b, "to_int")) || + !NIL_P(rb_check_to_integer(e, "to_int"))) { + ID op = EXCL(range) ? '<' : rb_intern("<="); + + while (RTEST(rb_funcall(b, op, 1, e))) { + rb_yield(b); + b = rb_funcall(b, '+', 1, step); + } } else { - VALUE tmp = rb_check_string_type(b); + tmp = rb_check_string_type(b); if (!NIL_P(tmp)) { VALUE args[2], iter[2]; @@ -365,7 +380,7 @@ range_step(int argc, VALUE *argv, VALUE range) } args[0] = INT2FIX(1); args[1] = step; - range_each_func(range, step_i, b, e, args); + range_each_func(range, step_i, args); } } return range; @@ -428,7 +443,7 @@ range_each(VALUE range) rb_block_call(beg, rb_intern("upto"), 2, args, rb_yield, 0); } else { - range_each_func(range, each_i, beg, end, NULL); + range_each_func(range, each_i, NULL); } return range; } -- cgit v1.2.3