1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

fix sum on infinity

* array.c (rb_ary_sum): consider non-finite floats.
  [ruby-core:88024] [Bug #14926]

* enum.c (sum_iter): ditto.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64014 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2018-07-22 10:47:33 +00:00
parent b22352af91
commit 67cacdb836
4 changed files with 55 additions and 0 deletions

14
array.c
View file

@ -5973,6 +5973,20 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary)
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);

19
enum.c
View file

@ -3809,6 +3809,25 @@ sum_iter(VALUE i, struct enum_sum_memo *memo)
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);

View file

@ -2967,6 +2967,13 @@ class TestArray < Test::Unit::TestCase
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([]))

View file

@ -966,6 +966,21 @@ class TestEnumerable < Test::Unit::TestCase
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