aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bignum.c28
-rw-r--r--internal.h4
-rw-r--r--numeric.c53
-rw-r--r--rational.c18
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));
}
/*