diff options
-rw-r--r-- | bignum.c | 16 | ||||
-rw-r--r-- | compile.c | 2 | ||||
-rw-r--r-- | include/ruby/ruby.h | 37 | ||||
-rw-r--r-- | insns.def | 2 | ||||
-rw-r--r-- | internal.h | 12 | ||||
-rw-r--r-- | numeric.c | 33 | ||||
-rw-r--r-- | object.c | 5 | ||||
-rw-r--r-- | sprintf.c | 6 |
8 files changed, 71 insertions, 42 deletions
@@ -3184,15 +3184,13 @@ rb_int2big(SIGNED_VALUE n) VALUE rb_uint2inum(VALUE n) { - if (POSFIXABLE(n)) return LONG2FIX(n); - return rb_uint2big(n); + return ULONG2NUM(n); } VALUE rb_int2inum(SIGNED_VALUE n) { - if (FIXABLE(n)) return LONG2FIX(n); - return rb_int2big(n); + return LONG2NUM(n); } void @@ -4438,8 +4436,18 @@ rb_ull2inum(unsigned LONG_LONG n) VALUE rb_ll2inum(LONG_LONG n) { +#ifdef HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW + SIGNED_VALUE v; + if (__builtin_mul_overflow(n, 2, &v)) { + return rb_ll2big(n); + } + else { + return ((VALUE)v) | RUBY_FIXNUM_FLAG; + } +#else if (FIXABLE(n)) return LONG2FIX(n); return rb_ll2big(n); +#endif } #endif /* HAVE_LONG_LONG */ @@ -3190,7 +3190,7 @@ case_when_optimizable_literal(NODE *node) double ival; if (RB_TYPE_P(v, T_FLOAT) && modf(RFLOAT_VALUE(v), &ival) == 0.0) { - return FIXABLE(ival) ? LONG2FIX((long)ival) : rb_dbl2big(ival); + return rb_dbl2ival(ival); } if (SYMBOL_P(v) || rb_obj_is_kind_of(v, rb_cNumeric)) { return v; diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h index d770c30735..0cd88fb002 100644 --- a/include/ruby/ruby.h +++ b/include/ruby/ruby.h @@ -1504,6 +1504,29 @@ rb_integer_type_p(VALUE obj) } #endif +static inline int +rb_long2fix_overflow(long l, VALUE *ptr) +{ +#ifdef HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW + SIGNED_VALUE v; + if (__builtin_mul_overflow(l, 2, &v)) { + return 1; + } + else { + *ptr = ((VALUE)v) | RUBY_FIXNUM_FLAG; + return 0; + } +#else + if (RB_FIXABLE(l)) { + *ptr = RB_LONG2FIX(l); + return 0; + } + else { + return 1; + } +#endif +} + #if SIZEOF_INT < SIZEOF_LONG # define RB_INT2NUM(v) RB_INT2FIX((int)(v)) # define RB_UINT2NUM(v) RB_LONG2FIX((unsigned int)(v)) @@ -1511,10 +1534,11 @@ rb_integer_type_p(VALUE obj) static inline VALUE rb_int2num_inline(int v) { - if (RB_FIXABLE(v)) - return RB_INT2FIX(v); - else + VALUE ret; + if (rb_long2fix_overflow(v, &ret)) return rb_int2big(v); + else + return ret; } #define RB_INT2NUM(x) rb_int2num_inline(x) @@ -1534,10 +1558,11 @@ rb_uint2num_inline(unsigned int v) static inline VALUE rb_long2num_inline(long v) { - if (RB_FIXABLE(v)) - return RB_LONG2FIX(v); - else + VALUE ret; + if (rb_long2fix_overflow(v, &ret)) return rb_int2big(v); + else + return ret; } #define RB_LONG2NUM(x) rb_long2num_inline(x) @@ -1345,7 +1345,7 @@ opt_case_dispatch if (RB_FLOAT_TYPE_P(key)) { double kval = RFLOAT_VALUE(key); if (!isinf(kval) && modf(kval, &kval) == 0.0) { - key = FIXABLE(kval) ? LONG2FIX((long)kval) : rb_dbl2big(kval); + key = rb_dbl2ival(kval); } } if (st_lookup(RHASH_TBL_RAW(hash), key, &val)) { diff --git a/internal.h b/internal.h index 06455f9409..bf54c64be7 100644 --- a/internal.h +++ b/internal.h @@ -1383,6 +1383,18 @@ rb_float_new_inline(double d) #define rb_float_value(v) rb_float_value_inline(v) #define rb_float_new(d) rb_float_new_inline(d) +static inline VALUE +rb_dbl2ival(double d) +{ + VALUE val; + if (rb_long2fix_overflow(d, &val)) { + return rb_dbl2big(d); + } + else { + return val; + } +} + /* object.c */ void rb_obj_copy_ivar(VALUE dest, VALUE obj); CONSTFUNC(VALUE rb_obj_equal(VALUE obj1, VALUE obj2)); @@ -1279,10 +1279,7 @@ flo_mod(VALUE x, VALUE y) static VALUE dbl2ival(double d) { - if (FIXABLE(d)) { - return LONG2FIX((long)d); - } - return rb_dbl2big(d); + return rb_dbl2ival(d); } /* @@ -1967,7 +1964,6 @@ static VALUE flo_floor(int argc, VALUE *argv, VALUE num) { double number, f; - long val; int ndigits = 0; if (rb_check_arity(argc, 0, 1)) { @@ -1984,11 +1980,7 @@ flo_floor(int argc, VALUE *argv, VALUE num) return DBL2NUM(f); } f = floor(number); - if (!FIXABLE(f)) { - return rb_dbl2big(f); - } - val = (long)f; - return LONG2FIX(val); + return dbl2ival(f); } /* @@ -2327,16 +2319,11 @@ static VALUE flo_to_i(VALUE num) { double f = RFLOAT_VALUE(num); - long val; if (f > 0.0) f = floor(f); if (f < 0.0) f = ceil(f); - if (!FIXABLE(f)) { - return rb_dbl2big(f); - } - val = (long)f; - return LONG2FIX(val); + return dbl2ival(f); } /* @@ -3020,13 +3007,17 @@ VALUE rb_num2fix(VALUE val) { long v; + VALUE w; - if (FIXNUM_P(val)) return val; - - v = rb_num2long(val); - if (!FIXABLE(v)) + if (FIXNUM_P(val)) { + return val; + } + else if (rb_long2fix_overflow((v = rb_num2long(val)), &w)) { rb_raise(rb_eRangeError, "integer %ld out of range of fixnum", v); - return LONG2FIX(v); + } + else { + return w; + } } #if HAVE_LONG_LONG @@ -2747,11 +2747,8 @@ rb_convert_to_integer(VALUE val, int base) VALUE tmp; if (RB_FLOAT_TYPE_P(val)) { - double f; if (base != 0) goto arg_error; - f = RFLOAT_VALUE(val); - if (FIXABLE(f)) return LONG2FIX((long)f); - return rb_dbl2big(f); + return rb_dbl2ival(RFLOAT_VALUE(val)); } else if (RB_INTEGER_TYPE_P(val)) { if (base != 0) goto arg_error; @@ -832,11 +832,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt) bin_retry: switch (TYPE(val)) { case T_FLOAT: - if (FIXABLE(RFLOAT_VALUE(val))) { - val = LONG2FIX((long)RFLOAT_VALUE(val)); - goto bin_retry; - } - val = rb_dbl2big(RFLOAT_VALUE(val)); + val = rb_dbl2ival(RFLOAT_VALUE(val)); if (FIXNUM_P(val)) goto bin_retry; bignum = 1; break; |