diff options
author | naruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-02-05 04:31:27 +0000 |
---|---|---|
committer | naruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-02-05 04:31:27 +0000 |
commit | 1db619a8e1b8a5d3b52871993f6d6b608e79058e (patch) | |
tree | 9bdb85c498731821aa32bddb893bf0e93c30548a /bignum.c | |
parent | d3642de04134abab0131548c03a878a486416c7d (diff) | |
download | ruby-1db619a8e1b8a5d3b52871993f6d6b608e79058e.tar.gz |
* 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.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53741 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'bignum.c')
-rw-r--r-- | bignum.c | 40 |
1 files changed, 40 insertions, 0 deletions
@@ -4367,6 +4367,46 @@ rb_ll2inum(LONG_LONG n) #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) { |