From 06d701a1f0c5981a386458c55cccef9486819cb5 Mon Sep 17 00:00:00 2001 From: mrkn Date: Fri, 11 Nov 2016 15:55:30 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56719 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- bignum.c | 28 +++++++++++++++++----------- internal.h | 4 ++-- numeric.c | 53 +++++++++++++++++++++++++++++++---------------------- rational.c | 18 ++++++++++++------ 4 files changed, 62 insertions(+), 41 deletions(-) diff --git a/bignum.c b/bignum.c index 18919d09c3..c0847e620d 100644 --- a/bignum.c +++ b/bignum.c @@ -6090,7 +6090,7 @@ big_shift(VALUE x, long n) 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) #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) 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) 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) 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 diff --git a/internal.h b/internal.h index fec2dbeedf..be3694ecc6 100644 --- a/internal.h +++ b/internal.h @@ -891,7 +891,7 @@ size_t rb_ary_memsize(VALUE); /* 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); 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))) diff --git a/numeric.c b/numeric.c index e2c26f54c2..8df969eb49 100644 --- a/numeric.c +++ b/numeric.c @@ -3549,6 +3549,35 @@ rb_int_mul(VALUE x, VALUE y) 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) * */ -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; } diff --git a/rational.c b/rational.c index 2ba501b4a2..44a720aebe 100644 --- a/rational.c +++ b/rational.c @@ -721,7 +721,7 @@ f_addsub(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k) 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) } } 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) } } 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) } } 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, VALUE self) 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, VALUE self) static VALUE nurat_to_f(VALUE self) { - get_dat1(self); - return rb_int_fdiv(dat->num, dat->den); + return DBL2NUM(nurat_to_double(self)); } /*