ruby-changes:41667
From: naruse <ko1@a...>
Date: Fri, 5 Feb 2016 13:31:27 +0900 (JST)
Subject: [ruby-changes:41667] naruse:r53741 (trunk): * insns.def (opt_mult): Use int128_t for overflow detection.
naruse 2016-02-05 13:31:27 +0900 (Fri, 05 Feb 2016) New Revision: 53741 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=53741 Log: * insns.def (opt_mult): Use int128_t for overflow detection. * bignum.c (rb_uint128t2big): added for opt_mult. * bignum.c (rb_uint128t2big): added for rb_uint128t2big.. * configure.in: define int128_t, uint128_t and related MACROs. Initially introduced by r41379 but reverted by r50749. Modified files: trunk/ChangeLog trunk/bignum.c trunk/configure.in trunk/insns.def Index: bignum.c =================================================================== --- bignum.c (revision 53740) +++ bignum.c (revision 53741) @@ -4367,6 +4367,46 @@ rb_ll2inum(LONG_LONG n) https://github.com/ruby/ruby/blob/trunk/bignum.c#L4367 #endif /* HAVE_LONG_LONG */ +#ifdef HAVE_INT128_T +static VALUE +rb_uint128t2big(uint128_t n) +{ + long i; + VALUE big = bignew(bdigit_roomof(SIZEOF_INT128_T), 1); + BDIGIT *digits = BDIGITS(big); + + for (i = 0; i < bdigit_roomof(SIZEOF_INT128_T); i++) { + digits[i] = BIGLO(RSHIFT(n ,BITSPERDIG*i)); + } + + i = bdigit_roomof(SIZEOF_INT128_T); + while (i-- && !digits[i]) ; + BIGNUM_SET_LEN(big, i+1); + return big; +} + +VALUE +rb_int128t2big(int128_t n) +{ + int neg = 0; + uint128_t u; + VALUE big; + + if (n < 0) { + u = 1 + (uint128_t)(-(n + 1)); /* u = -n avoiding overflow */ + neg = 1; + } + else { + u = n; + } + big = rb_uint128t2big(u); + if (neg) { + BIGNUM_SET_SIGN(big, 0); + } + return big; +} +#endif + VALUE rb_cstr2inum(const char *str, int base) { Index: configure.in =================================================================== --- configure.in (revision 53740) +++ configure.in (revision 53741) @@ -1472,6 +1472,7 @@ RUBY_CHECK_SIZEOF(short) https://github.com/ruby/ruby/blob/trunk/configure.in#L1472 RUBY_CHECK_SIZEOF(long, [int], [ILP LP]) RUBY_CHECK_SIZEOF(long long) RUBY_CHECK_SIZEOF(__int64) +RUBY_CHECK_SIZEOF(__int128) RUBY_CHECK_SIZEOF(off_t) RUBY_CHECK_SIZEOF(void*, [int long "long long"], [ILP LP LLP]) RUBY_CHECK_SIZEOF(float) @@ -2007,6 +2008,7 @@ typedef $1 t; int s = sizeof(t) == 42;]) https://github.com/ruby/ruby/blob/trunk/configure.in#L2008 ["$ac_cv_sizeof_long"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])long"], ["$ac_cv_sizeof_long_long"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])long long"], ["$ac_cv_sizeof___int64"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])__int64"], + ["$ac_cv_sizeof___int128"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])__int128"], [ rb_cv_type_$1=no])])]) if test "${rb_cv_type_$1}" != no; then AC_DEFINE([HAVE_]AS_TR_CPP($1), 1) @@ -2028,6 +2030,8 @@ RUBY_DEFINT(int32_t, 4) https://github.com/ruby/ruby/blob/trunk/configure.in#L2030 RUBY_DEFINT(uint32_t, 4, unsigned) RUBY_DEFINT(int64_t, 8) RUBY_DEFINT(uint64_t, 8, unsigned) +RUBY_DEFINT(int128_t, 16) +RUBY_DEFINT(uint128_t, 16, unsigned) RUBY_DEFINT(intptr_t, void*) RUBY_DEFINT(uintptr_t, void*, unsigned) RUBY_DEFINT(ssize_t, size_t, [], [@%:@include <sys/types.h>]) dnl may differ from int, so not use AC_TYPE_SSIZE_T. Index: insns.def =================================================================== --- insns.def (revision 53740) +++ insns.def (revision 53741) @@ -1430,20 +1430,29 @@ opt_mult https://github.com/ruby/ruby/blob/trunk/insns.def#L1430 { if (FIXNUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED_P(BOP_MULT, FIXNUM_REDEFINED_OP_FLAG)) { - long a, b; - - a = FIX2LONG(recv); + long a = FIX2LONG(recv); if (a == 0) { val = recv; } else { - b = FIX2LONG(obj); - if (MUL_OVERFLOW_FIXNUM_P(a, b)) { +#ifdef HAVE_INT128_T + VALUE rb_int128t2big(int128_t n); + int128_t r = (int128_t)a * FIX2LONG(obj); + if (RB_FIXABLE(r)) { + val = LONG2FIX((long)r); + } + else { + val = rb_int128t2big(r); + } +#else + long b = FIX2LONG(obj); + if (MUL_OVERFLOW_FIXNUM_P(a, b)) { val = rb_big_mul(rb_int2big(a), rb_int2big(b)); - } - else { + } + else { val = LONG2FIX(a * b); - } + } +#endif } } else if (FLONUM_2_P(recv, obj) && Index: ChangeLog =================================================================== --- ChangeLog (revision 53740) +++ ChangeLog (revision 53741) @@ -1,3 +1,14 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Fri Feb 5 12:22:20 2016 NARUSE, Yui <naruse@r...> + + * insns.def (opt_mult): Use int128_t for overflow detection. + + * bignum.c (rb_uint128t2big): added for opt_mult. + + * bignum.c (rb_uint128t2big): added for rb_uint128t2big.. + + * configure.in: define int128_t, uint128_t and related MACROs. + Initially introduced by r41379 but reverted by r50749. + Thu Feb 4 21:05:17 2016 Martin Duerst <duerst@i...> * enc/unicode.c: Activated :ascii flag for ASCII-only case conversion -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/