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

ruby-changes:54473

From: mrkn <ko1@a...>
Date: Wed, 2 Jan 2019 13:25:16 +0900 (JST)
Subject: [ruby-changes:54473] mrkn:r66688 (trunk): complex.c: fix against redefining component methods

mrkn	2019-01-02 13:25:11 +0900 (Wed, 02 Jan 2019)

  New Revision: 66688

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=66688

  Log:
    complex.c: fix against redefining component methods
    
    This fixes the incompatibility (maybe unintentionally) introduced by
    removal of `#ifndef PRESERVE_SIGNEDZERO` guards in f_add, f_mul, and
    f_sub functions in r62701.  [Bug #15491] [ruby-core:90843]

  Modified files:
    trunk/complex.c
    trunk/test/ruby/test_complex.rb
Index: test/ruby/test_complex.rb
===================================================================
--- test/ruby/test_complex.rb	(revision 66687)
+++ test/ruby/test_complex.rb	(revision 66688)
@@ -276,7 +276,7 @@ class Complex_Test < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/ruby/test_complex.rb#L276
         def +(other); 42; end
       end
       a = Complex(1, 2) + Complex(0, 1)
-      puts a == Complex(1, 42)
+      puts a == Complex(42, 42)
     end;
   end
 
@@ -286,8 +286,8 @@ class Complex_Test < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/ruby/test_complex.rb#L286
         remove_method :+
         def +(other); 42.0; end
       end
-      a = Complex(1, 2.0) + Complex(0, 1)
-      puts a == Complex(1, 42.0)
+      a = Complex(1.0, 2.0) + Complex(0, 1)
+      puts a == Complex(42.0, 42.0)
     end;
   end
 
@@ -297,8 +297,8 @@ class Complex_Test < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/ruby/test_complex.rb#L297
         remove_method :+
         def +(other); 355/113r; end
       end
-      a = Complex(1, 2r) + Complex(0, 1)
-      puts a == Complex(1, 355/113r)
+      a = Complex(1r, 2r) + Complex(0, 1)
+      puts a == Complex(355/113r, 355/113r)
     end;
   end
 
@@ -315,6 +315,36 @@ class Complex_Test < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/ruby/test_complex.rb#L315
     assert_equal(Complex(Rational(1,3),Rational(2)), c - Rational(2,3))
   end
 
+  def test_sub_with_redefining_int_minus
+    assert_in_out_err([], <<-'end;', ['true'], [])
+      class Integer
+        def -(other); 42; end
+      end
+      a = Complex(1, 2) - Complex(0, 1)
+      puts a == Complex(42, 42)
+    end;
+  end
+
+  def test_sub_with_redefining_float_minus
+    assert_in_out_err([], <<-'end;', ['true'], [])
+      class Float
+        def -(other); 42.0; end
+      end
+      a = Complex(1.0, 2.0) - Complex(0, 1)
+      puts a == Complex(42.0, 42.0)
+    end;
+  end
+
+  def test_sub_with_redefining_rational_minus
+    assert_in_out_err([], <<-'end;', ['true'], [])
+      class Rational
+        def -(other); 355/113r; end
+      end
+      a = Complex(1r, 2r) - Complex(0, 1)
+      puts a == Complex(355/113r, 355/113r)
+    end;
+  end
+
   def test_mul
     c = Complex(1,2)
     c2 = Complex(2,3)
@@ -333,6 +363,39 @@ class Complex_Test < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/ruby/test_complex.rb#L363
     c = Complex(0, Float::INFINITY)
     assert_equal(Complex(0, Float::INFINITY), c * Complex(1, 0))
     assert_equal(Complex(-Float::INFINITY, 0), c * Complex(0, 1))
+
+    assert_equal(Complex(-0.0, -0.0), Complex(-0.0, 0) * Complex(0, 0))
+  end
+
+  def test_mul_with_redefining_int_mult
+    assert_in_out_err([], <<-'end;', ['true'], [])
+      class Integer
+        def *(other); 42; end
+      end
+      a = Complex(2, 0) * Complex(1, 2)
+      puts a == Complex(0, 84)
+    end;
+  end
+
+  def test_mul_with_redefining_float_mult
+    assert_in_out_err([], <<-'end;', ['true'], [])
+      class Float
+        def *(other); 42.0; end
+      end
+      a = Complex(2.0, 0.0) * Complex(1, 2)
+      puts a == Complex(0.0, 84.0)
+    end;
+  end
+
+
+  def test_mul_with_redefining_rational_mult
+    assert_in_out_err([], <<-'end;', ['true'], [])
+      class Rational
+        def *(other); 355/113r; end
+      end
+      a = Complex(2r, 0r) * Complex(1, 2)
+      puts a == Complex(0r, 2*355/113r)
+    end;
   end
 
   def test_div
Index: complex.c
===================================================================
--- complex.c	(revision 66687)
+++ complex.c	(revision 66688)
@@ -71,21 +71,24 @@ f_##n(VALUE x, VALUE y)\ https://github.com/ruby/ruby/blob/trunk/complex.c#L71
 inline static VALUE
 f_add(VALUE x, VALUE y)
 {
-    if (FIXNUM_ZERO_P(y))
-        return x;
-    if (FIXNUM_ZERO_P(x))
-        return y;
-
     if (RB_INTEGER_TYPE_P(x) &&
         UNLIKELY(rb_method_basic_definition_p(rb_cInteger, idPLUS))) {
+        if (FIXNUM_ZERO_P(x))
+            return y;
+        if (FIXNUM_ZERO_P(y))
+            return x;
         return rb_int_plus(x, y);
     }
     else if (RB_FLOAT_TYPE_P(x) &&
              UNLIKELY(rb_method_basic_definition_p(rb_cFloat, idPLUS))) {
+        if (FIXNUM_ZERO_P(y))
+            return x;
         return rb_float_plus(x, y);
     }
     else if (RB_TYPE_P(x, T_RATIONAL) &&
              UNLIKELY(rb_method_basic_definition_p(rb_cRational, idPLUS))) {
+        if (FIXNUM_ZERO_P(y))
+            return x;
         return rb_rational_plus(x, y);
     }
 
@@ -120,20 +123,28 @@ f_gt_p(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/complex.c#L123
 inline static VALUE
 f_mul(VALUE x, VALUE y)
 {
-    if (FIXNUM_ZERO_P(y) && RB_INTEGER_TYPE_P(x))
-	return ZERO;
-    if (FIXNUM_ZERO_P(x) && RB_INTEGER_TYPE_P(y))
-	return ZERO;
-    if (y == ONE) return x;
-    if (x == ONE) return y;
+    if (RB_INTEGER_TYPE_P(x) &&
+        UNLIKELY(rb_method_basic_definition_p(rb_cInteger, idMULT))) {
+        if (FIXNUM_ZERO_P(y))
+            return ZERO;
+        if (FIXNUM_ZERO_P(x) && RB_INTEGER_TYPE_P(y))
+            return ZERO;
+        if (x == ONE) return y;
+        if (y == ONE) return x;
+    }
+    else if (UNLIKELY(rb_method_basic_definition_p(CLASS_OF(x), idMULT))) {
+        if (y == ONE) return x;
+    }
     return rb_funcall(x, '*', 1, y);
 }
 
 inline static VALUE
 f_sub(VALUE x, VALUE y)
 {
-    if (FIXNUM_ZERO_P(y))
+    if (FIXNUM_ZERO_P(y) &&
+        UNLIKELY(rb_method_basic_definition_p(CLASS_OF(x), idMINUS))) {
 	return x;
+    }
     return rb_funcall(x, '-', 1, y);
 }
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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