ruby-changes:51801
From: nobu <ko1@a...>
Date: Sun, 22 Jul 2018 19:47:38 +0900 (JST)
Subject: [ruby-changes:51801] nobu:r64014 (trunk): fix sum on infinity
nobu 2018-07-22 19:47:33 +0900 (Sun, 22 Jul 2018) New Revision: 64014 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=64014 Log: fix sum on infinity * array.c (rb_ary_sum): consider non-finite floats. [ruby-core:88024] [Bug #14926] * enum.c (sum_iter): ditto. Modified files: trunk/array.c trunk/enum.c trunk/test/ruby/test_array.rb trunk/test/ruby/test_enum.rb Index: array.c =================================================================== --- array.c (revision 64013) +++ array.c (revision 64014) @@ -5973,6 +5973,20 @@ rb_ary_sum(int argc, VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/array.c#L5973 else goto not_float; + if (isnan(f)) continue; + if (isnan(x)) { + f = x; + continue; + } + if (isinf(x)) { + if (isinf(f) && signbit(x) != signbit(f)) + f = NAN; + else + f = x; + continue; + } + if (isinf(f)) continue; + t = f + x; if (fabs(f) >= fabs(x)) c += ((f - t) + x); Index: enum.c =================================================================== --- enum.c (revision 64013) +++ enum.c (revision 64014) @@ -3809,6 +3809,25 @@ sum_iter(VALUE i, struct enum_sum_memo * https://github.com/ruby/ruby/blob/trunk/enum.c#L3809 goto some_value; } + if (isnan(f)) return; + if (isnan(x)) { + memo->v = i; + memo->f = x; + return; + } + if (isinf(x)) { + if (isinf(f) && signbit(x) != signbit(f)) { + memo->f = NAN; + memo->v = DBL2NUM(f); + } + else { + memo->f = x; + memo->v = i; + } + return; + } + if (isinf(f)) return; + t = f + x; if (fabs(f) >= fabs(x)) c += ((f - t) + x); Index: test/ruby/test_enum.rb =================================================================== --- test/ruby/test_enum.rb (revision 64013) +++ test/ruby/test_enum.rb (revision 64014) @@ -966,6 +966,21 @@ class TestEnumerable < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/ruby/test_enum.rb#L966 assert_float_equal(large_number+(small_number*11), [small_number, large_number/1r, *[small_number]*10].each.sum) assert_float_equal(small_number, [large_number, small_number, -large_number].each.sum) + k = Class.new do + include Enumerable + def initialize(*values) + @values = values + end + def each(&block) + @values.each(&block) + end + end + assert_equal(+Float::INFINITY, k.new(0.0, +Float::INFINITY).sum) + assert_equal(+Float::INFINITY, k.new(+Float::INFINITY, 0.0).sum) + assert_equal(-Float::INFINITY, k.new(0.0, -Float::INFINITY).sum) + assert_equal(-Float::INFINITY, k.new(-Float::INFINITY, 0.0).sum) + assert_predicate(k.new(-Float::INFINITY, Float::INFINITY).sum, :nan?) + assert_equal("abc", ["a", "b", "c"].each.sum("")) assert_equal([1, [2], 3], [[1], [[2]], [3]].each.sum([])) end Index: test/ruby/test_array.rb =================================================================== --- test/ruby/test_array.rb (revision 64013) +++ test/ruby/test_array.rb (revision 64014) @@ -2967,6 +2967,13 @@ class TestArray < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_array.rb#L2967 assert_float_equal(large_number+(small_number*10), [large_number/1r, *[small_number]*10].sum) assert_float_equal(large_number+(small_number*11), [small_number, large_number/1r, *[small_number]*10].sum) assert_float_equal(small_number, [large_number, small_number, -large_number].sum) + assert_equal(+Float::INFINITY, [+Float::INFINITY].sum) + assert_equal(+Float::INFINITY, [0.0, +Float::INFINITY].sum) + assert_equal(+Float::INFINITY, [+Float::INFINITY, 0.0].sum) + assert_equal(-Float::INFINITY, [-Float::INFINITY].sum) + assert_equal(-Float::INFINITY, [0.0, -Float::INFINITY].sum) + assert_equal(-Float::INFINITY, [-Float::INFINITY, 0.0].sum) + assert_predicate([-Float::INFINITY, Float::INFINITY].sum, :nan?) assert_equal("abc", ["a", "b", "c"].sum("")) assert_equal([1, [2], 3], [[1], [[2]], [3]].sum([])) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/