зеркало из https://github.com/github/ruby.git
fix description for current implementation
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57534 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
b163b3ff64
Коммит
68e10755d4
22
internal.h
22
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));
|
||||
|
|
Загрузка…
Ссылка в новой задаче