* 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

View file

@ -266,6 +266,34 @@ nlz_int128(uint128_t x)
}
#endif
#if HAVE_LONG_LONG && SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
# define DLONG LONG_LONG
# define DL2NUM(x) LL2NUM(x)
#elif defined(HAVE_INT128_T)
# define DLONG int128_t
# define DL2NUM(x) (RB_FIXABLE(x) ? LONG2FIX(x) : rb_int128t2big(x))
#endif
VALUE rb_int128t2big(int128_t n);
/* arguments must be Fixnum */
static inline VALUE
rb_fix_mul_fix(VALUE x, VALUE y)
{
long lx = FIX2LONG(x);
long ly = FIX2LONG(y);
#ifdef DLONG
return DL2NUM((DLONG)lx * (DLONG)ly);
#else
if (MUL_OVERFLOW_FIXNUM_P(a, b)) {
return rb_big_mul(rb_int2big(a), rb_int2big(b));
}
else {
return LONG2FIX(a * b);
}
#endif
}
/*
* This behaves different from C99 for negative arguments.
* Note that div may overflow fixnum.