* internal.h (DLONG): defined if long is 32bit (and LONG_LONG is 64bit;

but LONG_LONG is always defined as 64bit), or there's int128_t.

* internal.h (DL2NUM): defined if DLONG is defined.

* internal.h (rb_fix_mul_fix): defined for `Fixnum * Fixnum`.

* insns.def (opt_mul): use rb_fix_mul_fix().

* numeric.c (fix_mul): ditto.

* time.c (mul): ditto.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54203 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
naruse 2016-03-20 11:10:43 +00:00
parent 57638377cc
commit 148f1b9d57
5 changed files with 46 additions and 96 deletions

52
time.c
View file

@ -91,61 +91,11 @@ sub(VALUE x, VALUE y)
return rb_funcall(x, '-', 1, y);
}
#if !(HAVE_LONG_LONG && SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG)
static int
long_mul(long x, long y, long *z)
{
unsigned long a, b, c;
int s;
if (x == 0 || y == 0) {
*z = 0;
return 1;
}
if (x < 0) {
s = -1;
a = (unsigned long)-x;
}
else {
s = 1;
a = (unsigned long)x;
}
if (y < 0) {
s = -s;
b = (unsigned long)-y;
}
else {
b = (unsigned long)y;
}
if (a <= ULONG_MAX / b) {
c = a * b;
if (s < 0) {
if (c <= (unsigned long)LONG_MAX + 1) {
*z = -(long)c;
return 1;
}
}
else {
if (c <= (unsigned long)LONG_MAX) {
*z = (long)c;
return 1;
}
}
}
return 0;
}
#endif
static VALUE
mul(VALUE x, VALUE y)
{
if (FIXNUM_P(x) && FIXNUM_P(y)) {
#if HAVE_LONG_LONG && SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
return LL2NUM((LONG_LONG)FIX2LONG(x) * FIX2LONG(y));
#else
long z;
if (long_mul(FIX2LONG(x), FIX2LONG(y), &z))
return LONG2NUM(z);
#endif
rb_fix_mul_fix(x, y);
}
if (RB_TYPE_P(x, T_BIGNUM))
return rb_big_mul(x, y);