diff --git a/ChangeLog b/ChangeLog index 85e45b6843..cd6fdcd76e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Sat Apr 16 01:03:32 2016 Tanaka Akira + + * array.c (rb_ary_sum): Fix SEGV by [1/2r, 1].sum. + Fri Apr 15 23:52:00 2016 Kenta Murata * rational.c (rb_rational_plus): rename from rb_rational_add diff --git a/array.c b/array.c index 8e50449efa..5fe5800954 100644 --- a/array.c +++ b/array.c @@ -5682,7 +5682,7 @@ rb_ary_dig(int argc, VALUE *argv, VALUE self) static VALUE rb_ary_sum(int argc, VALUE *argv, VALUE ary) { - VALUE e, v; + VALUE e, v, r; long i, n; int block_given; @@ -5695,6 +5695,7 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary) return v; n = 0; + r = Qundef; for (i = 0; i < RARRAY_LEN(ary); i++) { e = RARRAY_AREF(ary, i); if (block_given) @@ -5708,22 +5709,31 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary) } else if (RB_TYPE_P(e, T_BIGNUM)) v = rb_big_plus(e, v); + else if (RB_TYPE_P(e, T_RATIONAL)) { + if (r == Qundef) + r = e; + else + r = rb_rational_plus(r, e); + } else - goto not_integer; + goto not_exact; } if (n != 0) v = rb_fix_plus(LONG2FIX(n), v); + if (r != Qundef) + v = rb_rational_plus(r, v); return v; - not_integer: + not_exact: if (n != 0) v = rb_fix_plus(LONG2FIX(n), v); + if (r != Qundef) + v = rb_rational_plus(r, v); if (RB_FLOAT_TYPE_P(e)) { /* Kahan's compensated summation algorithm */ double f, c; - float_value: f = NUM2DBL(v); c = 0.0; for (; i < RARRAY_LEN(ary); i++) { @@ -5753,20 +5763,6 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary) v = DBL2NUM(f); } - if (RB_TYPE_P(e, T_RATIONAL)) { - for (; i < RARRAY_LEN(ary); i++) { - e = RARRAY_AREF(ary, i); - if (block_given) - e = rb_yield(e); - if (RB_FLOAT_TYPE_P(e)) { - v = rb_to_float(v); - goto float_value; - } - v = rb_rational_plus(e, v); - } - return v; - } - for (; i < RARRAY_LEN(ary); i++) { e = RARRAY_AREF(ary, i); if (block_given) diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb index 8293a784da..fb6b2a42ad 100644 --- a/test/ruby/test_array.rb +++ b/test/ruby/test_array.rb @@ -2761,6 +2761,7 @@ class TestArray < Test::Unit::TestCase assert_float_equal((FIXNUM_MAX+1).to_f, [FIXNUM_MAX, 1, 0.0].sum) assert_float_equal((FIXNUM_MAX+1).to_f, [0.0, FIXNUM_MAX+1].sum) + assert_rational_equal(3/2r, [1/2r, 1].sum) assert_rational_equal(5/6r, [1/2r, 1/3r].sum) assert_equal(2.0+3.0i, [2.0, 3.0i].sum)