diff options
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | bignum.c | 17 | ||||
-rw-r--r-- | compar.c | 16 | ||||
-rw-r--r-- | range.c | 33 | ||||
-rw-r--r-- | test/ruby/test_range.rb | 6 | ||||
-rw-r--r-- | version.h | 6 |
6 files changed, 54 insertions, 34 deletions
@@ -22,6 +22,11 @@ Sat Apr 5 05:50:57 2008 Eric Hodel <drbrain@segment7.net> * lib/webrick/httprequest.rb: Fix redefined method warning. +Sat Apr 5 02:13:52 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * bignum.c (rb_cmpint): moved from compar.c, to check bignum + zero. + Fri Apr 4 23:24:06 2008 NARUSE, Yui <naruse@ruby-lang.org> * re.c (rb_memsearch_qs): wrong boundary condition. @@ -38,6 +43,11 @@ Fri Apr 4 05:57:11 2008 Yukihiro Matsumoto <matz@ruby-lang.org> * lib/net/pop.rb (Net::POP3::do_finish): clear @n_mails and @n_bytes as well. [ruby-core:16144] +Fri Apr 4 01:59:30 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * range.c (range_step): add step for each iteration if begin and + end are numeric. [ruby-core:15990] + Fri Apr 4 00:42:26 2008 Yukihiro Matsumoto <matz@ruby-lang.org> * bignum.c (Init_Bignum): rdiv method removed. [ruby-dev:34242] @@ -50,6 +50,23 @@ bigzero_p(VALUE x) return 1; } +int +rb_cmpint(VALUE val, VALUE a, VALUE b) +{ + if (NIL_P(val)) { + rb_cmperr(a, b); + } + if (FIXNUM_P(val)) return FIX2INT(val); + if (TYPE(val) == T_BIGNUM) { + if (BIGZEROP(val)) return 0; + if (RBIGNUM_SIGN(val)) return 1; + return -1; + } + if (RTEST(rb_funcall(val, '>', 1, INT2FIX(0)))) return 1; + if (RTEST(rb_funcall(val, '<', 1, INT2FIX(0)))) return -1; + return 0; +} + #define RBIGNUM_SET_LEN(b,l) \ ((RBASIC(b)->flags & RBIGNUM_EMBED_FLAG) ? \ (RBASIC(b)->flags = (RBASIC(b)->flags & ~RBIGNUM_EMBED_LEN_MASK) | \ @@ -15,22 +15,6 @@ VALUE rb_mComparable; static ID cmp; -int -rb_cmpint(VALUE val, VALUE a, VALUE b) -{ - if (NIL_P(val)) { - rb_cmperr(a, b); - } - if (FIXNUM_P(val)) return FIX2INT(val); - if (TYPE(val) == T_BIGNUM) { - if (RBIGNUM_SIGN(val)) return 1; - return -1; - } - if (RTEST(rb_funcall(val, '>', 1, INT2FIX(0)))) return 1; - if (RTEST(rb_funcall(val, '<', 1, INT2FIX(0)))) return -1; - return 0; -} - void rb_cmperr(VALUE x, VALUE y) { @@ -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 <i>rng</i>, passing each <i>n</i>th element to the block. If - * the range contains numbers or strings, natural ordering is used. Otherwise + * the range contains numbers, <i>n</i> is added for each iteration. Otherwise * <code>step</code> invokes <code>succ</code> to iterate through range * elements. The following code uses class <code>Xs</code>, 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; } diff --git a/test/ruby/test_range.rb b/test/ruby/test_range.rb index b8cd5a7416..09781dd407 100644 --- a/test/ruby/test_range.rb +++ b/test/ruby/test_range.rb @@ -114,12 +114,6 @@ class TestRange < Test::Unit::TestCase (0..10).step(2) {|x| a << x } assert_equal([0, 2, 4, 6, 8, 10], a) - o = Object.new - def o.to_int; 2; end - a = [] - (0..10).step(o) {|x| a << x } - assert_equal([0, 2, 4, 6, 8, 10], a) - assert_raise(ArgumentError) { (0..10).step(-1) { } } assert_raise(ArgumentError) { (0..10).step(0) { } } @@ -1,7 +1,7 @@ #define RUBY_VERSION "1.9.0" -#define RUBY_RELEASE_DATE "2008-04-06" +#define RUBY_RELEASE_DATE "2008-04-07" #define RUBY_VERSION_CODE 190 -#define RUBY_RELEASE_CODE 20080406 +#define RUBY_RELEASE_CODE 20080407 #define RUBY_PATCHLEVEL 0 #define RUBY_VERSION_MAJOR 1 @@ -9,7 +9,7 @@ #define RUBY_VERSION_TEENY 0 #define RUBY_RELEASE_YEAR 2008 #define RUBY_RELEASE_MONTH 4 -#define RUBY_RELEASE_DAY 6 +#define RUBY_RELEASE_DAY 7 #ifdef RUBY_EXTERN RUBY_EXTERN const char ruby_version[]; |