aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--bignum.c4
-rw-r--r--intern.h2
-rw-r--r--numeric.c90
4 files changed, 91 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index 4f9c495aa0..4df14f3164 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Wed Aug 3 12:40:28 2005 Tadashi Saito <shiba@mail2.accsnet.ne.jp>
+
+ * numeric.c (fix_minus, fix_mul, fix_quo, fix_div, fix_mod,
+ fix_divmod, fix_pow): ditto.
+
+ * numeric.c (fix_plus): reduce coercing when a method knows about
+ a operand type. [ruby-dev:26723]
+
+ * bignum.c (rb_big_div, rb_big_modulo): export to reduce
+ coercing.
+
Wed Aug 3 10:13:52 2005 NAKAMURA Usaku <usa@ruby-lang.org>
* configure.in, {bcc32,win32,wince}/Makefile.sub (HAVE_SNPRINTF,
diff --git a/bignum.c b/bignum.c
index 3d11efa8c4..402de8a992 100644
--- a/bignum.c
+++ b/bignum.c
@@ -1424,7 +1424,7 @@ bigdivmod(x, y, divp, modp)
* Divides big by other, returning the result.
*/
-static VALUE
+VALUE
rb_big_div(x, y)
VALUE x, y;
{
@@ -1458,7 +1458,7 @@ rb_big_div(x, y)
* information.
*/
-static VALUE
+VALUE
rb_big_modulo(x, y)
VALUE x, y;
{
diff --git a/intern.h b/intern.h
index d99a7c0163..cb16a81eb1 100644
--- a/intern.h
+++ b/intern.h
@@ -98,6 +98,8 @@ double rb_big2dbl _((VALUE));
VALUE rb_big_plus _((VALUE, VALUE));
VALUE rb_big_minus _((VALUE, VALUE));
VALUE rb_big_mul _((VALUE, VALUE));
+VALUE rb_big_div _((VALUE, VALUE));
+VALUE rb_big_modulo _((VALUE, VALUE));
VALUE rb_big_divmod _((VALUE, VALUE));
VALUE rb_big_pow _((VALUE, VALUE));
VALUE rb_big_and _((VALUE, VALUE));
diff --git a/numeric.c b/numeric.c
index f602679d1e..ec01d69260 100644
--- a/numeric.c
+++ b/numeric.c
@@ -1985,10 +1985,14 @@ fix_plus(x, y)
}
return r;
}
- if (TYPE(y) == T_FLOAT) {
+ switch (TYPE(y)) {
+ case T_BIGNUM:
+ return rb_big_plus(y, x);
+ case T_FLOAT:
return rb_float_new((double)FIX2LONG(x) + RFLOAT(y)->value);
+ default:
+ return rb_num_coerce_bin(x, y);
}
- return rb_num_coerce_bin(x, y);
}
/*
@@ -2018,10 +2022,15 @@ fix_minus(x, y)
}
return r;
}
- if (TYPE(y) == T_FLOAT) {
+ switch (TYPE(y)) {
+ case T_BIGNUM:
+ x = rb_int2big(FIX2LONG(x));
+ return rb_big_minus(x, y);
+ case T_FLOAT:
return rb_float_new((double)FIX2LONG(x) - RFLOAT(y)->value);
+ default:
+ return rb_num_coerce_bin(x, y);
}
- return rb_num_coerce_bin(x, y);
}
/*
@@ -2053,10 +2062,14 @@ fix_mul(x, y)
}
return r;
}
- if (TYPE(y) == T_FLOAT) {
+ switch (TYPE(y)) {
+ case T_BIGNUM:
+ return rb_big_mul(y, x);
+ case T_FLOAT:
return rb_float_new((double)FIX2LONG(x) * RFLOAT(y)->value);
+ default:
+ return rb_num_coerce_bin(x, y);
}
- return rb_num_coerce_bin(x, y);
}
static void
@@ -2107,7 +2120,14 @@ fix_quo(x, y)
if (FIXNUM_P(y)) {
return rb_float_new((double)FIX2LONG(x) / (double)FIX2LONG(y));
}
- return rb_num_coerce_bin(x, y);
+ switch (TYPE(y)) {
+ case T_BIGNUM:
+ return rb_float_new((double)FIX2LONG(y) / rb_big2dbl(y));
+ case T_FLOAT:
+ return rb_float_new((double)FIX2LONG(x) / RFLOAT(y)->value);
+ default:
+ return rb_num_coerce_bin(x, y);
+ }
}
/*
@@ -2130,7 +2150,15 @@ fix_div(x, y)
fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, 0);
return LONG2NUM(div);
}
- return rb_num_coerce_bin(x, y);
+ switch (TYPE(y)) {
+ case T_BIGNUM:
+ x = rb_int2big(FIX2LONG(x));
+ return rb_big_div(x, y);
+ case T_FLOAT:
+ return rb_Integer(rb_float_new((double)FIX2LONG(x) / RFLOAT(y)->value));
+ default:
+ return rb_num_coerce_bin(x, y);
+ }
}
/*
@@ -2152,7 +2180,20 @@ fix_mod(x, y)
fixdivmod(FIX2LONG(x), FIX2LONG(y), 0, &mod);
return LONG2NUM(mod);
}
- return rb_num_coerce_bin(x, y);
+ switch (TYPE(y)) {
+ case T_BIGNUM:
+ x = rb_int2big(FIX2LONG(x));
+ return rb_big_modulo(x, y);
+ case T_FLOAT:
+ {
+ double mod;
+
+ flodivmod((double)FIX2LONG(x), RFLOAT(y)->value, 0, &mod);
+ return rb_float_new(mod);
+ }
+ default:
+ return rb_num_coerce_bin(x, y);
+ }
}
/*
@@ -2172,7 +2213,23 @@ fix_divmod(x, y)
return rb_assoc_new(LONG2NUM(div), LONG2NUM(mod));
}
- return rb_num_coerce_bin(x, y);
+ switch (TYPE(y)) {
+ case T_BIGNUM:
+ x = rb_int2big(FIX2LONG(x));
+ return rb_big_divmod(x, y);
+ case T_FLOAT:
+ {
+ double div, mod;
+ volatile VALUE a, b;
+
+ flodivmod((double)FIX2LONG(x), RFLOAT(y)->value, &div, &mod);
+ a = rb_float_new(div);
+ b = rb_float_new(mod);
+ return rb_assoc_new(a, b);
+ }
+ default:
+ return rb_num_coerce_bin(x, y);
+ }
}
/*
@@ -2202,11 +2259,16 @@ fix_pow(x, y)
return rb_big_pow(rb_int2big(a), y);
}
return rb_float_new(pow((double)a, (double)b));
- } else if (TYPE(y) == T_FLOAT) {
- long a = FIX2LONG(x);
- return rb_float_new(pow((double)a, RFLOAT(y)->value));
}
- return rb_num_coerce_bin(x, y);
+ switch (TYPE(y)) {
+ case T_BIGNUM:
+ x = rb_int2big(FIX2LONG(x));
+ return rb_big_pow(x, y);
+ case T_FLOAT:
+ return rb_float_new(pow((double)FIX2LONG(x), RFLOAT(y)->value));
+ default:
+ return rb_num_coerce_bin(x, y);
+ }
}
/*