From 68e10755d469dfe26e3cf34439bae046dff06c1c Mon Sep 17 00:00:00 2001 From: naruse Date: Sat, 4 Feb 2017 18:14:42 +0000 Subject: fix description for current implementation git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57534 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- internal.h | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/internal.h b/internal.h index 7d9250c886..5baac16957 100644 --- a/internal.h +++ b/internal.h @@ -360,12 +360,24 @@ rb_fix_plus_fix(VALUE x, VALUE y) #ifdef HAVE_BUILTIN___BUILTIN_ADD_OVERFLOW long lz; /* NOTE - * (1) Fixnum's LSB is always 1. + * (1) `LONG2FIX(FIX2LONG(x)+FIX2LONG(y))` + + = `((lx*2+1)/2 + (ly*2+1)/2)*2+1` + + = `lx*2 + ly*2 + 1` + + = `(lx*2+1) + (ly*2+1) - 1` + + = `x + y - 1` + * (2) 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)`. + * (3) Of course `z = x + (y-1)` may overflow. + * At that time true value is + * * positive: 0b0 1xxx...1, and z = 0b1xxx...1 + * * nevative: 0b1 0xxx...1, and z = 0b0xxx...1 + * To convert this true value to long, + * (a) Use arithmetic shift + * * positive: 0b11xxx... + * * negative: 0b00xxx... + * (b) invert MSB + * * positive: 0b01xxx... + * * negative: 0b10xxx... */ if (__builtin_add_overflow((long)x, (long)y-1, &lz)) { return rb_int2big(rb_overflowed_fix_to_int(lz)); -- cgit v1.2.3