diff options
-rw-r--r-- | complex.c | 58 | ||||
-rw-r--r-- | internal.h | 3 | ||||
-rw-r--r-- | numeric.c | 12 | ||||
-rw-r--r-- | rational.c | 8 | ||||
-rw-r--r-- | test/ruby/test_complex.rb | 102 | ||||
-rw-r--r-- | version.h | 2 |
6 files changed, 163 insertions, 22 deletions
@@ -71,10 +71,27 @@ 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) && + LIKELY(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) && + LIKELY(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) && + LIKELY(rb_method_basic_definition_p(rb_cRational, idPLUS))) { + if (FIXNUM_ZERO_P(y)) + return x; + return rb_rational_plus(x, y); + } + return rb_funcall(x, '+', 1, y); } @@ -106,20 +123,39 @@ 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) && + LIKELY(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; + return rb_int_mul(x, y); + } + else if (RB_FLOAT_TYPE_P(x) && + LIKELY(rb_method_basic_definition_p(rb_cFloat, idMULT))) { + if (y == ONE) return x; + return rb_float_mul(x, y); + } + else if (RB_TYPE_P(x, T_RATIONAL) && + LIKELY(rb_method_basic_definition_p(rb_cRational, idMULT))) { + if (y == ONE) return x; + return rb_rational_mul(x, y); + } + else if (LIKELY(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) && + LIKELY(rb_method_basic_definition_p(CLASS_OF(x), idMINUS))) { return x; + } return rb_funcall(x, '-', 1, y); } diff --git a/internal.h b/internal.h index 433ab6635d..d107fbe7c7 100644 --- a/internal.h +++ b/internal.h @@ -1677,8 +1677,10 @@ VALUE rb_int_pred(VALUE num); VALUE rb_int_uminus(VALUE num); VALUE rb_float_uminus(VALUE num); VALUE rb_int_plus(VALUE x, VALUE y); +VALUE rb_float_plus(VALUE x, VALUE y); VALUE rb_int_minus(VALUE x, VALUE y); VALUE rb_int_mul(VALUE x, VALUE y); +VALUE rb_float_mul(VALUE x, VALUE y); VALUE rb_int_idiv(VALUE x, VALUE y); VALUE rb_int_modulo(VALUE x, VALUE y); VALUE rb_int_round(VALUE num, int ndigits, enum ruby_num_rounding_mode mode); @@ -1970,6 +1972,7 @@ void rb_last_status_clear(void); VALUE rb_rational_canonicalize(VALUE x); VALUE rb_rational_uminus(VALUE self); VALUE rb_rational_plus(VALUE self, VALUE other); +VALUE rb_rational_mul(VALUE self, VALUE other); VALUE rb_lcm(VALUE x, VALUE y); VALUE rb_rational_reciprocal(VALUE x); VALUE rb_cstr_to_rat(const char *, int); @@ -1018,8 +1018,8 @@ rb_float_uminus(VALUE flt) * Returns a new Float which is the sum of +float+ and +other+. */ -static VALUE -flo_plus(VALUE x, VALUE y) +VALUE +rb_float_plus(VALUE x, VALUE y) { if (RB_TYPE_P(y, T_FIXNUM)) { return DBL2NUM(RFLOAT_VALUE(x) + (double)FIX2LONG(y)); @@ -1066,8 +1066,8 @@ flo_minus(VALUE x, VALUE y) * Returns a new Float which is the product of +float+ and +other+. */ -static VALUE -flo_mul(VALUE x, VALUE y) +VALUE +rb_float_mul(VALUE x, VALUE y) { if (RB_TYPE_P(y, T_FIXNUM)) { return DBL2NUM(RFLOAT_VALUE(x) * (double)FIX2LONG(y)); @@ -5674,9 +5674,9 @@ Init_Numeric(void) rb_define_alias(rb_cFloat, "inspect", "to_s"); rb_define_method(rb_cFloat, "coerce", flo_coerce, 1); rb_define_method(rb_cFloat, "-@", rb_float_uminus, 0); - rb_define_method(rb_cFloat, "+", flo_plus, 1); + rb_define_method(rb_cFloat, "+", rb_float_plus, 1); rb_define_method(rb_cFloat, "-", flo_minus, 1); - rb_define_method(rb_cFloat, "*", flo_mul, 1); + rb_define_method(rb_cFloat, "*", rb_float_mul, 1); rb_define_method(rb_cFloat, "/", flo_div, 1); rb_define_method(rb_cFloat, "quo", flo_quo, 1); rb_define_method(rb_cFloat, "fdiv", flo_quo, 1); diff --git a/rational.c b/rational.c index f668cc4691..236bc08e39 100644 --- a/rational.c +++ b/rational.c @@ -877,8 +877,8 @@ f_muldiv(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k) * Rational(9, 8) * 4 #=> (9/2) * Rational(20, 9) * 9.8 #=> 21.77777777777778 */ -static VALUE -nurat_mul(VALUE self, VALUE other) +VALUE +rb_rational_mul(VALUE self, VALUE other) { if (RB_INTEGER_TYPE_P(other)) { { @@ -1396,7 +1396,7 @@ f_round_common(int argc, VALUE *argv, VALUE self, VALUE (*func)(VALUE)) rb_raise(rb_eTypeError, "not an integer"); b = f_expt10(n); - s = nurat_mul(self, b); + s = rb_rational_mul(self, b); if (k_float_p(s)) { if (INT_NEGATIVE_P(n)) @@ -2734,7 +2734,7 @@ Init_Rational(void) rb_define_method(rb_cRational, "-@", rb_rational_uminus, 0); rb_define_method(rb_cRational, "+", rb_rational_plus, 1); rb_define_method(rb_cRational, "-", nurat_sub, 1); - rb_define_method(rb_cRational, "*", nurat_mul, 1); + rb_define_method(rb_cRational, "*", rb_rational_mul, 1); rb_define_method(rb_cRational, "/", nurat_div, 1); rb_define_method(rb_cRational, "quo", nurat_div, 1); rb_define_method(rb_cRational, "fdiv", nurat_fdiv, 1); diff --git a/test/ruby/test_complex.rb b/test/ruby/test_complex.rb index 1180e9acb0..4aa3eda1d4 100644 --- a/test/ruby/test_complex.rb +++ b/test/ruby/test_complex.rb @@ -269,6 +269,39 @@ class Complex_Test < Test::Unit::TestCase assert_equal(Complex(Rational(5,3),Rational(2)), c + Rational(2,3)) end + def test_add_with_redefining_int_plus + assert_in_out_err([], <<-'end;', ['true'], []) + class Integer + remove_method :+ + def +(other); 42; end + end + a = Complex(1, 2) + Complex(0, 1) + puts a == Complex(42, 42) + end; + end + + def test_add_with_redefining_float_plus + assert_in_out_err([], <<-'end;', ['true'], []) + class Float + remove_method :+ + 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_add_with_redefining_rational_plus + assert_in_out_err([], <<-'end;', ['true'], []) + class Rational + remove_method :+ + def +(other); 355/113r; end + end + a = Complex(1r, 2r) + Complex(0, 1) + puts a == Complex(355/113r, 355/113r) + end; + end + def test_sub c = Complex(1,2) c2 = Complex(2,3) @@ -282,6 +315,39 @@ 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 + remove_method :- + 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 + remove_method :- + 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 + remove_method :- + 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) @@ -300,6 +366,42 @@ 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 + remove_method :* + 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 + remove_method :* + 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 + remove_method :* + 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 @@ -1,6 +1,6 @@ #define RUBY_VERSION "2.6.0" #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 22 +#define RUBY_PATCHLEVEL 23 #define RUBY_RELEASE_YEAR 2019 #define RUBY_RELEASE_MONTH 1 |