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

ruby-changes:54639

From: naruse <ko1@a...>
Date: Fri, 18 Jan 2019 08:08:16 +0900 (JST)
Subject: [ruby-changes:54639] naruse:r66854 (ruby_2_6): merge revision(s) 66681, 66682, 66684, 66688, 66697, 66751, 66693, 66694: [Backport #15491]

naruse	2019-01-18 08:08:10 +0900 (Fri, 18 Jan 2019)

  New Revision: 66854

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

  Log:
    merge revision(s) 66681,66682,66684,66688,66697,66751,66693,66694: [Backport #15491]
    
    complex.c: Optimize Complex#+ for some conditions
    
    Optimize f_add defined in complex.c for some specific conditions.
    It makes Complex#+ about 1.4x faster than r66678.
    
    Compared to r66678:
    
    ```
    mrkn-mbp15-late2016:complex-optim-o3 mrkn$ make benchmark ITEM=complex_float_ COMPARE_RUBY=/Users/mrkn/.rbenv/versions/trunk-o3/bin/ruby
    /Users/mrkn/src/github.com/ruby/ruby/revision.h unchanged
    /Users/mrkn/.rbenv/shims/ruby --disable=gems -rrubygems -I/Users/mrkn/src/github.com/ruby/ruby/benchmark/lib /Users/mrkn/src/github.com/ruby/ruby/benchmark/benchmark-driver/exe/benchmark-driver \
                        --executables="compare-ruby::/Users/mrkn/.rbenv/versions/trunk-o3/bin/ruby -I.ext/common --disable-gem" \
                        --executables="built-ruby::./miniruby -I/Users/mrkn/src/github.com/ruby/ruby/lib -I. -I.ext/common  -r/Users/mrkn/src/github.com/ruby/ruby/prelude --disable-gem" \
                        $(find /Users/mrkn/src/github.com/ruby/ruby/benchmark -maxdepth 1 -name '*complex_float_*.yml' -o -name '*complex_float_*.rb' | sort)
    Calculating -------------------------------------
                         compare-ruby  built-ruby
       complex_float_add       9.132M     12.864M i/s -      1.000M times in 0.109511s 0.077734s
       complex_float_div     600.723k    627.878k i/s -      1.000M times in 1.664662s 1.592666s
       complex_float_mul       2.320M      2.347M i/s -      1.000M times in 0.431039s 0.426113s
       complex_float_new       1.473M      1.489M i/s -      1.000M times in 0.678791s 0.671750s
     complex_float_power       1.690M      1.722M i/s -      1.000M times in 0.591863s 0.580775s
       complex_float_sub       8.870M      9.516M i/s -      1.000M times in 0.112740s 0.105091s
    
    Comparison:
                    complex_float_add
              built-ruby:  12864383.7 i/s
            compare-ruby:   9131502.8 i/s - 1.41x  slower
    
                    complex_float_div
              built-ruby:    627878.0 i/s
            compare-ruby:    600722.5 i/s - 1.05x  slower
    
                    complex_float_mul
              built-ruby:   2346795.3 i/s
            compare-ruby:   2319975.7 i/s - 1.01x  slower
    
                    complex_float_new
              built-ruby:   1488649.1 i/s
            compare-ruby:   1473207.5 i/s - 1.01x  slower
    
                  complex_float_power
              built-ruby:   1721837.2 i/s
            compare-ruby:   1689580.2 i/s - 1.02x  slower
    
                    complex_float_sub
              built-ruby:   9515562.7 i/s
            compare-ruby:   8869966.3 i/s - 1.07x  slower
    ```
    
    suppress warning: method redefined; discarding old + introduced at r66681
    
    complex.c: fix indentation
    
    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]
    
    complex.c: Optimize Complex#* and Complex#**
    
    Optimize f_mul for the core numeric class components.
    This change improves the computation time of Complex#* and Complex#**.
    
    ```
    $ make benchmark ITEM=complex_float_ COMPARE_RUBY=/Users/mrkn/.rbenv/versions/2.6.0/bin/ruby
    generating known_errors.inc
    known_errors.inc unchanged
    /Users/mrkn/src/github.com/ruby/ruby/revision.h unchanged
    /Users/mrkn/.rbenv/shims/ruby --disable=gems -rrubygems -I/Users/mrkn/src/github.com/ruby/ruby/benchmark/lib /Users/mrkn/src/github.com/ruby/ruby/benchmark/benchmark-driver/exe/benchmark-driver \
                        --executables="compare-ruby::/Users/mrkn/.rbenv/versions/2.6.0/bin/ruby -I.ext/common --disable-gem" \
                        --executables="built-ruby::./miniruby -I/Users/mrkn/src/github.com/ruby/ruby/lib -I. -I.ext/common  -r/Users/mrkn/src/github.com/ruby/ruby/prelude --disable-gem" \
                        $(find /Users/mrkn/src/github.com/ruby/ruby/benchmark -maxdepth 1 -name '*complex_float_*.yml' -o -name '*complex_float_*.rb' | sort)
    Calculating -------------------------------------
                         compare-ruby  built-ruby
       complex_float_add       6.558M     13.012M i/s -      1.000M times in 0.152480s 0.076850s
       complex_float_div     576.821k    567.969k i/s -      1.000M times in 1.733640s 1.760660s
       complex_float_mul       1.690M      2.628M i/s -      1.000M times in 0.591786s 0.380579s
       complex_float_new       1.350M      1.268M i/s -      1.000M times in 0.740669s 0.788762s
     complex_float_power       1.571M      1.835M i/s -      1.000M times in 0.636507s 0.544909s
       complex_float_sub       8.635M      8.779M i/s -      1.000M times in 0.115814s 0.113906s
    
    Comparison:
                    complex_float_add
              built-ruby:  13012361.7 i/s
            compare-ruby:   6558237.1 i/s - 1.98x  slower
    
                    complex_float_div
            compare-ruby:    576821.0 i/s
              built-ruby:    567968.8 i/s - 1.02x  slower
    
                    complex_float_mul
              built-ruby:   2627575.4 i/s
            compare-ruby:   1689800.0 i/s - 1.55x  slower
    
                    complex_float_new
            compare-ruby:   1350130.8 i/s
              built-ruby:   1267809.6 i/s - 1.06x  slower
    
                  complex_float_power
              built-ruby:   1835168.8 i/s
            compare-ruby:   1571074.6 i/s - 1.17x  slower
    
                    complex_float_sub
              built-ruby:   8779168.8 i/s
            compare-ruby:   8634534.7 i/s - 1.02x  slower
    ```
    
    complex.c: replace misused UNLIKELY with LIKELY
    
    test_complex.rb: fix tests for RUBYOPT="-w"
    
    test_complex.rb: use the same approach to fix failures
    
    as r66682.

  Modified directories:
    branches/ruby_2_6/
  Modified files:
    branches/ruby_2_6/complex.c
    branches/ruby_2_6/internal.h
    branches/ruby_2_6/numeric.c
    branches/ruby_2_6/rational.c
    branches/ruby_2_6/test/ruby/test_complex.rb
    branches/ruby_2_6/version.h
Index: ruby_2_6/complex.c
===================================================================
--- ruby_2_6/complex.c	(revision 66853)
+++ ruby_2_6/complex.c	(revision 66854)
@@ -71,10 +71,27 @@ f_##n(VALUE x, VALUE y)\ https://github.com/ruby/ruby/blob/trunk/ruby_2_6/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) &&
+        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) https://github.com/ruby/ruby/blob/trunk/ruby_2_6/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) &&
+        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);
 }
 
Index: ruby_2_6/test/ruby/test_complex.rb
===================================================================
--- ruby_2_6/test/ruby/test_complex.rb	(revision 66853)
+++ ruby_2_6/test/ruby/test_complex.rb	(revision 66854)
@@ -269,6 +269,39 @@ class Complex_Test < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/ruby_2_6/test/ruby/test_complex.rb#L269
     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::TestCas https://github.com/ruby/ruby/blob/trunk/ruby_2_6/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
+        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::TestCas https://github.com/ruby/ruby/blob/trunk/ruby_2_6/test/ruby/test_complex.rb#L366
     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
Index: ruby_2_6/internal.h
===================================================================
--- ruby_2_6/internal.h	(revision 66853)
+++ ruby_2_6/internal.h	(revision 66854)
@@ -1677,8 +1677,10 @@ VALUE rb_int_pred(VALUE num); https://github.com/ruby/ruby/blob/trunk/ruby_2_6/internal.h#L1677
 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); https://github.com/ruby/ruby/blob/trunk/ruby_2_6/internal.h#L1972
 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);
Index: ruby_2_6/numeric.c
===================================================================
--- ruby_2_6/numeric.c	(revision 66853)
+++ ruby_2_6/numeric.c	(revision 66854)
@@ -1018,8 +1018,8 @@ rb_float_uminus(VALUE flt) https://github.com/ruby/ruby/blob/trunk/ruby_2_6/numeric.c#L1018
  * 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) https://github.com/ruby/ruby/blob/trunk/ruby_2_6/numeric.c#L1066
  * 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) https://github.com/ruby/ruby/blob/trunk/ruby_2_6/numeric.c#L5674
     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);
Index: ruby_2_6/rational.c
===================================================================
--- ruby_2_6/rational.c	(revision 66853)
+++ ruby_2_6/rational.c	(revision 66854)
@@ -877,8 +877,8 @@ f_muldiv(VALUE self, VALUE anum, VALUE a https://github.com/ruby/ruby/blob/trunk/ruby_2_6/rational.c#L877
  *    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, VA https://github.com/ruby/ruby/blob/trunk/ruby_2_6/rational.c#L1396
 	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) https://github.com/ruby/ruby/blob/trunk/ruby_2_6/rational.c#L2734
     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);
Index: ruby_2_6/version.h
===================================================================
--- ruby_2_6/version.h	(revision 66853)
+++ ruby_2_6/version.h	(revision 66854)
@@ -1,6 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_6/version.h#L1
 #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
Index: ruby_2_6
===================================================================
--- ruby_2_6	(revision 66853)
+++ ruby_2_6	(revision 66854)

Property changes on: ruby_2_6
___________________________________________________________________
Modified: svn:mergeinfo
## -0,0 +0,1 ##
   Merged /trunk:r66681-66682,66684,66688,66693-66694,66697,66751

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

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