mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66688 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
888ddda157
commit
ee2ddf5411
2 changed files with 91 additions and 17 deletions
35
complex.c
35
complex.c
|
@ -71,21 +71,24 @@ f_##n(VALUE x, VALUE y)\
|
|||
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)
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -276,7 +276,7 @@ class Complex_Test < Test::Unit::TestCase
|
|||
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::TestCase
|
|||
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::TestCase
|
|||
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::TestCase
|
|||
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::TestCase
|
|||
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
|
||||
|
|
Loading…
Add table
Reference in a new issue