aboutsummaryrefslogtreecommitdiffstats
path: root/bignum.c
diff options
context:
space:
mode:
authornaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-02-05 04:31:27 +0000
committernaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-02-05 04:31:27 +0000
commit1f57a334daa4cd27decdc756cd709163e00e6a0c (patch)
tree9bdb85c498731821aa32bddb893bf0e93c30548a /bignum.c
parentb658249cef3c0032be91e499dfc04cd00642d354 (diff)
downloadruby-1f57a334daa4cd27decdc756cd709163e00e6a0c.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.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/bignum.c b/bignum.c
index afd264adec..bc24764b88 100644
--- a/bignum.c
+++ b/bignum.c
@@ -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)
{