[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]