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/