diff options
author | naruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-02-02 15:54:51 +0000 |
---|---|---|
committer | naruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-02-02 15:54:51 +0000 |
commit | 038ccbd112d26d15b7433b86bf48b1be0fea6e2f (patch) | |
tree | 1a1526b8206577a2b172836d875fc904d3b33f7f /numeric.c | |
parent | b36f5ba197ebf5b871044c037bebfffc2675780c (diff) |
Use carry flag to reduce instructions
NOTE:
(1) Fixnum's LSB is always 1.
It means you can always run `x - 1` without overflow.
(2) Of course `z = x + (y-1)` may overflow.
Now z's LSB is always 1, and the MSB of true result is also 1.
You can get true result in long as `(1<<63)|(z>>1)`,
and it equals to `(z<<63)|(z>>1)` == `ror(z)`.
GCC and Clang have __builtin_add_ovewflow:
* https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html
* https://clang.llvm.org/docs/LanguageExtensions.html#checked-arithmetic-builtins
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57506 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'numeric.c')
-rw-r--r-- | numeric.c | 20 |
1 files changed, 2 insertions, 18 deletions
@@ -3458,15 +3458,7 @@ static VALUE fix_plus(VALUE x, VALUE y) { if (FIXNUM_P(y)) { - long a, b, c; - VALUE r; - - a = FIX2LONG(x); - b = FIX2LONG(y); - c = a + b; - r = LONG2NUM(c); - - return r; + return rb_fix_plus_fix(x, y); } else if (RB_TYPE_P(y, T_BIGNUM)) { return rb_big_plus(y, x); @@ -3513,15 +3505,7 @@ static VALUE fix_minus(VALUE x, VALUE y) { if (FIXNUM_P(y)) { - long a, b, c; - VALUE r; - - a = FIX2LONG(x); - b = FIX2LONG(y); - c = a - b; - r = LONG2NUM(c); - - return r; + return rb_fix_minus_fix(x, y); } else if (RB_TYPE_P(y, T_BIGNUM)) { x = rb_int2big(FIX2LONG(x)); |