ruby-changes:44646
From: mrkn <ko1@a...>
Date: Sat, 12 Nov 2016 00:55:36 +0900 (JST)
Subject: [ruby-changes:44646] mrkn:r56719 (trunk): rational.c: avoid needless object allocation with nurat_to_double
mrkn 2016-11-12 00:55:30 +0900 (Sat, 12 Nov 2016) New Revision: 56719 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=56719 Log: rational.c: avoid needless object allocation with nurat_to_double * rational.c (nurat_to_double): introduce to convert rational to double without object allocation. * rational.c (rb_rational_plus, nurat_{sub,mul,to_f}): rewrite by using nurat_to_double. * bignum.c (rb_big_fdiv_double): introduce to calculate fdiv and return the result as a double value. * bignum.c (big_fdiv{,_int,_float}): change the return types for implementing rb_big_fdiv_double. * bignum.c (rb_big_fdiv): rewrite by using rb_big_fdiv_double. * numeric.c (rb_int_fdiv_double): introduce to calculate fdiv and return the result as a double value. * numeric.c (fix_fdiv_double): rewrite from fix_fdiv to return the result as a double value. * numeric.c (rb_int_fdiv): rewrite by using rb_int_fdiv_double. * internal.h (rb_{big,int}_fdiv_double): exported. Modified files: trunk/bignum.c trunk/internal.h trunk/numeric.c trunk/rational.c Index: internal.h =================================================================== --- internal.h (revision 56718) +++ internal.h (revision 56719) @@ -891,7 +891,7 @@ size_t rb_ary_memsize(VALUE); https://github.com/ruby/ruby/blob/trunk/internal.h#L891 /* bignum.c */ extern const char ruby_digitmap[]; -VALUE rb_big_fdiv(VALUE x, VALUE y); +double rb_big_fdiv_double(VALUE x, VALUE y); VALUE rb_big_uminus(VALUE x); VALUE rb_big_hash(VALUE); VALUE rb_big_odd_p(VALUE); @@ -1170,7 +1170,7 @@ VALUE rb_dbl_hash(double d); https://github.com/ruby/ruby/blob/trunk/internal.h#L1170 VALUE rb_fix_plus(VALUE x, VALUE y); VALUE rb_int_ge(VALUE x, VALUE y); enum ruby_num_rounding_mode rb_num_get_rounding_option(VALUE opts); -VALUE rb_int_fdiv(VALUE x, VALUE y); +double rb_int_fdiv_double(VALUE x, VALUE y); #if USE_FLONUM #define RUBY_BIT_ROTL(v, n) (((v) << (n)) | ((v) >> ((sizeof(v) * 8) - n))) Index: numeric.c =================================================================== --- numeric.c (revision 56718) +++ numeric.c (revision 56719) @@ -3549,6 +3549,35 @@ rb_int_mul(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/numeric.c#L3549 return rb_num_coerce_bin(x, y, '*'); } +static double +fix_fdiv_double(VALUE x, VALUE y) +{ + if (FIXNUM_P(y)) { + return (double)FIX2LONG(x) / (double)FIX2LONG(y); + } + else if (RB_TYPE_P(y, T_BIGNUM)) { + return rb_big_fdiv_double(rb_int2big(FIX2LONG(x)), y); + } + else if (RB_TYPE_P(y, T_FLOAT)) { + return (double)FIX2LONG(x) / RFLOAT_VALUE(y); + } + else { + return RFLOAT_VALUE(rb_num_coerce_bin(x, y, rb_intern("fdiv"))); + } +} + +double +rb_int_fdiv_double(VALUE x, VALUE y) +{ + if (FIXNUM_P(x)) { + return fix_fdiv_double(x, y); + } + else if (RB_TYPE_P(x, T_BIGNUM)) { + return rb_big_fdiv_double(x, y); + } + return NAN; +} + /* * Document-method: Integer#fdiv * call-seq: @@ -3564,31 +3593,11 @@ rb_int_mul(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/numeric.c#L3593 * */ -static VALUE -fix_fdiv(VALUE x, VALUE y) -{ - if (FIXNUM_P(y)) { - return DBL2NUM((double)FIX2LONG(x) / (double)FIX2LONG(y)); - } - else if (RB_TYPE_P(y, T_BIGNUM)) { - return rb_big_fdiv(rb_int2big(FIX2LONG(x)), y); - } - else if (RB_TYPE_P(y, T_FLOAT)) { - return DBL2NUM((double)FIX2LONG(x) / RFLOAT_VALUE(y)); - } - else { - return rb_num_coerce_bin(x, y, rb_intern("fdiv")); - } -} - VALUE rb_int_fdiv(VALUE x, VALUE y) { - if (FIXNUM_P(x)) { - return fix_fdiv(x, y); - } - else if (RB_TYPE_P(x, T_BIGNUM)) { - return rb_big_fdiv(x, y); + if (RB_INTEGER_TYPE_P(x)) { + return DBL2NUM(rb_int_fdiv_double(x, y)); } return Qnil; } Index: rational.c =================================================================== --- rational.c (revision 56718) +++ rational.c (revision 56719) @@ -721,7 +721,7 @@ f_addsub(VALUE self, VALUE anum, VALUE a https://github.com/ruby/ruby/blob/trunk/rational.c#L721 return f_rational_new_no_reduce2(CLASS_OF(self), num, den); } -static VALUE nurat_to_f(VALUE self); +static double nurat_to_double(VALUE self); /* * call-seq: * rat + numeric -> numeric @@ -747,7 +747,7 @@ rb_rational_plus(VALUE self, VALUE other https://github.com/ruby/ruby/blob/trunk/rational.c#L747 } } else if (RB_TYPE_P(other, T_FLOAT)) { - return DBL2NUM(RFLOAT_VALUE(nurat_to_f(self)) + RFLOAT_VALUE(other)); + return DBL2NUM(nurat_to_double(self) + RFLOAT_VALUE(other)); } else if (RB_TYPE_P(other, T_RATIONAL)) { { @@ -788,7 +788,7 @@ nurat_sub(VALUE self, VALUE other) https://github.com/ruby/ruby/blob/trunk/rational.c#L788 } } else if (RB_FLOAT_TYPE_P(other)) { - return DBL2NUM(RFLOAT_VALUE(nurat_to_f(self)) - RFLOAT_VALUE(other)); + return DBL2NUM(nurat_to_double(self) - RFLOAT_VALUE(other)); } else if (RB_TYPE_P(other, T_RATIONAL)) { { @@ -868,7 +868,7 @@ nurat_mul(VALUE self, VALUE other) https://github.com/ruby/ruby/blob/trunk/rational.c#L868 } } else if (RB_FLOAT_TYPE_P(other)) { - return DBL2NUM(RFLOAT_VALUE(nurat_to_f(self)) * RFLOAT_VALUE(other)); + return DBL2NUM(nurat_to_double(self) * RFLOAT_VALUE(other)); } else if (RB_TYPE_P(other, T_RATIONAL)) { { @@ -1433,6 +1433,13 @@ nurat_round_n(int argc, VALUE *argv, VAL https://github.com/ruby/ruby/blob/trunk/rational.c#L1433 return f_round_common(argc, argv, self, round_func); } +static double +nurat_to_double(VALUE self) +{ + get_dat1(self); + return rb_int_fdiv_double(dat->num, dat->den); +} + /* * call-seq: * rat.to_f -> float @@ -1447,8 +1454,7 @@ nurat_round_n(int argc, VALUE *argv, VAL https://github.com/ruby/ruby/blob/trunk/rational.c#L1454 static VALUE nurat_to_f(VALUE self) { - get_dat1(self); - return rb_int_fdiv(dat->num, dat->den); + return DBL2NUM(nurat_to_double(self)); } /* Index: bignum.c =================================================================== --- bignum.c (revision 56718) +++ bignum.c (revision 56719) @@ -6090,7 +6090,7 @@ big_shift(VALUE x, long n) https://github.com/ruby/ruby/blob/trunk/bignum.c#L6090 return x; } -static VALUE +static double big_fdiv(VALUE x, VALUE y, long ey) { #define DBL_BIGDIG ((DBL_MANT_DIG + BITSPERDIG) / BITSPERDIG) @@ -6108,14 +6108,14 @@ big_fdiv(VALUE x, VALUE y, long ey) https://github.com/ruby/ruby/blob/trunk/bignum.c#L6108 #if SIZEOF_LONG > SIZEOF_INT { /* Visual C++ can't be here */ - if (l > INT_MAX) return DBL2NUM(INFINITY); - if (l < INT_MIN) return DBL2NUM(0.0); + if (l > INT_MAX) return INFINITY; + if (l < INT_MIN) return 0.0; } #endif - return DBL2NUM(ldexp(big2dbl(z), (int)l)); + return ldexp(big2dbl(z), (int)l); } -static VALUE +static double big_fdiv_int(VALUE x, VALUE y) { long l, ey; @@ -6127,7 +6127,7 @@ big_fdiv_int(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/bignum.c#L6127 return big_fdiv(x, y, ey); } -static VALUE +static double big_fdiv_float(VALUE x, VALUE y) { int i; @@ -6135,8 +6135,8 @@ big_fdiv_float(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/bignum.c#L6135 return big_fdiv(x, y, i - DBL_MANT_DIG); } -VALUE -rb_big_fdiv(VALUE x, VALUE y) +double +rb_big_fdiv_double(VALUE x, VALUE y) { double dx, dy; @@ -6154,14 +6154,20 @@ rb_big_fdiv(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/bignum.c#L6154 else if (RB_FLOAT_TYPE_P(y)) { dy = RFLOAT_VALUE(y); if (isnan(dy)) - return y; + return dy; if (isinf(dx)) return big_fdiv_float(x, y); } else { - return rb_num_coerce_bin(x, y, rb_intern("fdiv")); + return RFLOAT_VALUE(rb_num_coerce_bin(x, y, rb_intern("fdiv"))); } - return DBL2NUM(dx / dy); + return dx / dy; +} + +VALUE +rb_big_fdiv(VALUE x, VALUE y) +{ + return DBL2NUM(rb_big_fdiv_double(x, y)); } VALUE -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/