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:
parent
b22352af91
commit
67cacdb836
4 changed files with 55 additions and 0 deletions
14
array.c
14
array.c
|
@ -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
19
enum.c
|
@ -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);
|
||||
|
|
|
@ -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([]))
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue