From 84549e3f209fb9c153e0c559611bfb801b1e5b09 Mon Sep 17 00:00:00 2001 From: gogotanaka Date: Thu, 29 Jan 2015 14:06:00 -0800 Subject: [PATCH 1/1] Make math.c twice as faster when Bignum passed To: https://bugs.ruby-lang.org/ --- math.c | 88 ++++++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 54 insertions(+), 34 deletions(-) diff --git a/math.c b/math.c index dfbd476..44ec735 100644 --- a/math.c +++ b/math.c @@ -26,13 +26,33 @@ static ID id_to_f; VALUE rb_mMath; VALUE rb_eMathDomainError; -#define fix_to_f_optimizable() rb_method_basic_definition_p(rb_cFixnum, id_to_f) -#define Get_Float(x) \ - ((RB_TYPE_P((x), T_FLOAT) ? (void)0 : ((x) = rb_to_float(x))), RFLOAT_VALUE(x)) -#define Get_Double(x) \ - (FIXNUM_P(x) && fix_to_f_optimizable() ? \ - (double)FIX2LONG(x) : \ - Get_Float(x)) +static inline double +num2dbl_with_to_f(VALUE num) +{ + switch (TYPE(num)) { + case T_FLOAT: + return RFLOAT_VALUE(num); + + case T_FIXNUM: + if (rb_method_basic_definition_p(rb_cFixnum, id_to_f)) { + return (double)FIX2LONG(num); + } + else { + return RFLOAT_VALUE(rb_to_float(num)); + } + + case T_BIGNUM: + if (rb_method_basic_definition_p(rb_cBignum, id_to_f)) { + return rb_big2dbl(num); + } + else { + return RFLOAT_VALUE(rb_to_float(num)); + } + + default: + return RFLOAT_VALUE(rb_to_float(num)); + } +} #define domain_error(msg) \ rb_raise(rb_eMathDomainError, "Numerical argument is out of domain - " #msg) @@ -74,8 +94,8 @@ math_atan2(VALUE obj, VALUE y, VALUE x) # define M_PI 3.14159265358979323846 #endif double dx, dy; - dx = Get_Double(x); - dy = Get_Double(y); + dx = num2dbl_with_to_f(x); + dy = num2dbl_with_to_f(y); if (dx == 0.0 && dy == 0.0) { if (!signbit(dx)) return DBL2NUM(dy); @@ -118,7 +138,7 @@ math_atan2(VALUE obj, VALUE y, VALUE x) static VALUE math_cos(VALUE obj, VALUE x) { - return DBL2NUM(cos(Get_Double(x))); + return DBL2NUM(cos(num2dbl_with_to_f(x))); } /* @@ -139,7 +159,7 @@ math_cos(VALUE obj, VALUE x) static VALUE math_sin(VALUE obj, VALUE x) { - return DBL2NUM(sin(Get_Double(x))); + return DBL2NUM(sin(num2dbl_with_to_f(x))); } @@ -160,7 +180,7 @@ math_sin(VALUE obj, VALUE x) static VALUE math_tan(VALUE obj, VALUE x) { - return DBL2NUM(tan(Get_Double(x))); + return DBL2NUM(tan(num2dbl_with_to_f(x))); } /* @@ -182,7 +202,7 @@ math_acos(VALUE obj, VALUE x) { double d0, d; - d0 = Get_Double(x); + d0 = num2dbl_with_to_f(x); /* check for domain error */ if (d0 < -1.0 || 1.0 < d0) domain_error("acos"); d = acos(d0); @@ -207,7 +227,7 @@ math_asin(VALUE obj, VALUE x) { double d0, d; - d0 = Get_Double(x); + d0 = num2dbl_with_to_f(x); /* check for domain error */ if (d0 < -1.0 || 1.0 < d0) domain_error("asin"); d = asin(d0); @@ -230,7 +250,7 @@ math_asin(VALUE obj, VALUE x) static VALUE math_atan(VALUE obj, VALUE x) { - return DBL2NUM(atan(Get_Double(x))); + return DBL2NUM(atan(num2dbl_with_to_f(x))); } #ifndef HAVE_COSH @@ -258,7 +278,7 @@ cosh(double x) static VALUE math_cosh(VALUE obj, VALUE x) { - return DBL2NUM(cosh(Get_Double(x))); + return DBL2NUM(cosh(num2dbl_with_to_f(x))); } #ifndef HAVE_SINH @@ -286,7 +306,7 @@ sinh(double x) static VALUE math_sinh(VALUE obj, VALUE x) { - return DBL2NUM(sinh(Get_Double(x))); + return DBL2NUM(sinh(num2dbl_with_to_f(x))); } #ifndef HAVE_TANH @@ -314,7 +334,7 @@ tanh(double x) static VALUE math_tanh(VALUE obj, VALUE x) { - return DBL2NUM(tanh(Get_Double(x))); + return DBL2NUM(tanh(num2dbl_with_to_f(x))); } /* @@ -336,7 +356,7 @@ math_acosh(VALUE obj, VALUE x) { double d0, d; - d0 = Get_Double(x); + d0 = num2dbl_with_to_f(x); /* check for domain error */ if (d0 < 1.0) domain_error("acosh"); d = acosh(d0); @@ -360,7 +380,7 @@ math_acosh(VALUE obj, VALUE x) static VALUE math_asinh(VALUE obj, VALUE x) { - return DBL2NUM(asinh(Get_Double(x))); + return DBL2NUM(asinh(num2dbl_with_to_f(x))); } /* @@ -382,7 +402,7 @@ math_atanh(VALUE obj, VALUE x) { double d0, d; - d0 = Get_Double(x); + d0 = num2dbl_with_to_f(x); /* check for domain error */ if (d0 < -1.0 || +1.0 < d0) domain_error("atanh"); /* check for pole error */ @@ -411,7 +431,7 @@ math_atanh(VALUE obj, VALUE x) static VALUE math_exp(VALUE obj, VALUE x) { - return DBL2NUM(exp(Get_Double(x))); + return DBL2NUM(exp(num2dbl_with_to_f(x))); } #if defined __CYGWIN__ @@ -475,7 +495,7 @@ math_log1(VALUE x) numbits = 0; } - d0 = Get_Double(x); + d0 = num2dbl_with_to_f(x); /* check for domain error */ if (d0 < 0.0) domain_error("log"); /* check for pole error */ @@ -530,7 +550,7 @@ math_log2(VALUE obj, VALUE x) numbits = 0; } - d0 = Get_Double(x); + d0 = num2dbl_with_to_f(x); /* check for domain error */ if (d0 < 0.0) domain_error("log2"); /* check for pole error */ @@ -571,7 +591,7 @@ math_log10(VALUE obj, VALUE x) numbits = 0; } - d0 = Get_Double(x); + d0 = num2dbl_with_to_f(x); /* check for domain error */ if (d0 < 0.0) domain_error("log10"); /* check for pole error */ @@ -613,7 +633,7 @@ math_sqrt(VALUE obj, VALUE x) { double d0, d; - d0 = Get_Double(x); + d0 = num2dbl_with_to_f(x); /* check for domain error */ if (d0 < 0.0) domain_error("sqrt"); if (d0 == 0.0) return DBL2NUM(0.0); @@ -659,7 +679,7 @@ math_sqrt(VALUE obj, VALUE x) static VALUE math_cbrt(VALUE obj, VALUE x) { - return DBL2NUM(cbrt(Get_Double(x))); + return DBL2NUM(cbrt(num2dbl_with_to_f(x))); } /* @@ -679,7 +699,7 @@ math_frexp(VALUE obj, VALUE x) double d; int exp; - d = frexp(Get_Double(x), &exp); + d = frexp(num2dbl_with_to_f(x), &exp); return rb_assoc_new(DBL2NUM(d), INT2NUM(exp)); } @@ -696,7 +716,7 @@ math_frexp(VALUE obj, VALUE x) static VALUE math_ldexp(VALUE obj, VALUE x, VALUE n) { - return DBL2NUM(ldexp(Get_Double(x), NUM2INT(n))); + return DBL2NUM(ldexp(num2dbl_with_to_f(x), NUM2INT(n))); } /* @@ -712,7 +732,7 @@ math_ldexp(VALUE obj, VALUE x, VALUE n) static VALUE math_hypot(VALUE obj, VALUE x, VALUE y) { - return DBL2NUM(hypot(Get_Double(x), Get_Double(y))); + return DBL2NUM(hypot(num2dbl_with_to_f(x), num2dbl_with_to_f(y))); } /* @@ -732,7 +752,7 @@ math_hypot(VALUE obj, VALUE x, VALUE y) static VALUE math_erf(VALUE obj, VALUE x) { - return DBL2NUM(erf(Get_Double(x))); + return DBL2NUM(erf(num2dbl_with_to_f(x))); } /* @@ -752,7 +772,7 @@ math_erf(VALUE obj, VALUE x) static VALUE math_erfc(VALUE obj, VALUE x) { - return DBL2NUM(erfc(Get_Double(x))); + return DBL2NUM(erfc(num2dbl_with_to_f(x))); } /* @@ -828,7 +848,7 @@ math_gamma(VALUE obj, VALUE x) }; double d0, d; double intpart, fracpart; - d0 = Get_Double(x); + d0 = num2dbl_with_to_f(x); /* check for domain error */ if (isinf(d0) && signbit(d0)) domain_error("gamma"); fracpart = modf(d0, &intpart); @@ -863,7 +883,7 @@ math_lgamma(VALUE obj, VALUE x) double d0, d; int sign=1; VALUE v; - d0 = Get_Double(x); + d0 = num2dbl_with_to_f(x); /* check for domain error */ if (isinf(d0)) { if (signbit(d0)) domain_error("lgamma"); -- gogotanaka