diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-04-15 16:04:18 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-04-15 16:04:18 +0000 |
commit | 72305d2531437e5303ac4d1c8756e81d35869149 (patch) | |
tree | 3145ab4b9318f6dec882816e229fb4c900519182 | |
parent | 7111e7c6f87dbe1e21252f38b09a8796138a992e (diff) |
* array.c (rb_ary_sum): Fix SEGV by [1/2r, 1].sum.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54606 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | array.c | 32 | ||||
-rw-r--r-- | test/ruby/test_array.rb | 1 |
3 files changed, 19 insertions, 18 deletions
@@ -1,3 +1,7 @@ +Sat Apr 16 01:03:32 2016 Tanaka Akira <[email protected]> + + * array.c (rb_ary_sum): Fix SEGV by [1/2r, 1].sum. + Fri Apr 15 23:52:00 2016 Kenta Murata <[email protected]> * rational.c (rb_rational_plus): rename from rb_rational_add @@ -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) |