Bug #17731
closedInteger downflow with inject/reduce
Description
Test case:
[-2305843009213693953,-2305843009213693953,-2305843009213693953].inject(:+)
or
([-2**61-1] * 3).inject(:+)
Expected Result:
-6917529027641081859
Actual Result:
11529215046068469757
Some clues:
- Downflow seems not happen if there are only two elements in Array
- The sample above works fine in https://try.ruby-lang.org/
- [-2305843009213693953,-2305843009213693953,-2305843009213693953].sum can get the correct result
- ([-2**61] * 3).inject(:+) can get the correct result
Affected Versions:
- ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-linux]
- ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-linux]
- ruby 2.6.6p146 (2020-03-31 revision 67876) [x86_64-linux]
Updated by gaojun (Jun Gao) over 3 years ago
Some more interesting samples:
3.0.0 :001 > [0,-2305843009213693953,-2305843009213693953].inject(:+)
=> 13835058055282163710
3.0.0 :002 > [-2305843009213693953,-2305843009213693953].inject(:+)
=> -4611686018427387906
3.0.0 :003 > [-2305843009213693953,-2305843009213693953,0].inject(:+)
=> -4611686018427387906
Updated by Hanmac (Hans Mackowiak) over 3 years ago
more interesting samples:
[-2305843009213693953,-2305843009213693953,-2305843009213693953].inject(:+)
#=> 11529215046068469757
[-2305843009213693953,-2305843009213693953,-2305843009213693953].inject(&:+)
#=> -6917529027641081859
Updated by marcandre (Marc-Andre Lafortune) over 3 years ago
- Assignee set to marcandre (Marc-Andre Lafortune)
Right, there's a ULONG2NUM
that seem to assume the subtotal is always positive...
I'll make a PR for this
Updated by marcandre (Marc-Andre Lafortune) over 3 years ago
- Backport changed from 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN to 2.5: REQUIRED, 2.6: REQUIRED, 2.7: REQUIRED, 3.0: REQUIRED
Removing the letter 'U' fixes it...
Updated by akr (Akira Tanaka) over 3 years ago
marcandre (Marc-Andre Lafortune) wrote in #note-3:
Right, there's a
ULONG2NUM
that seem to assume the subtotal is always positive...
I'll make a PR for this
nobu changed it from LONG2NUM to ULONG2NUM at
https://github.com/ruby/ruby/commit/6bb70c11b344dee0739c6fb7bbf0ea124b5225b6
Updated by Anonymous over 3 years ago
- Status changed from Open to Closed
Applied in changeset git|a85ed626f18d1014d09fb37eb0a703976c3d2b53.
Fix Enumerable#inject with high negative fixnums [Bug #17731]
Updated by marcandre (Marc-Andre Lafortune) over 3 years ago
akr (Akira Tanaka) wrote in #note-5:
nobu changed it from LONG2NUM to ULONG2NUM at
https://github.com/ruby/ruby/commit/6bb70c11b344dee0739c6fb7bbf0ea124b5225b6
Thanks.
The other changes were for counts (always positive) and most were considered as integers. In the inject
case, the values can be any fixnum, including negative ones, so that change was a bug. Now fixed.
Updated by nagachika (Tomoyuki Chikanaga) over 3 years ago
- Backport changed from 2.5: REQUIRED, 2.6: REQUIRED, 2.7: REQUIRED, 3.0: REQUIRED to 2.5: REQUIRED, 2.6: REQUIRED, 2.7: DONE, 3.0: REQUIRED
ruby_2_7 364c8595884808315aaec9605bf2423963ed81c0 merged revision(s) a85ed626f18d1014d09fb37eb0a703976c3d2b53.
Updated by naruse (Yui NARUSE) over 3 years ago
- Backport changed from 2.5: REQUIRED, 2.6: REQUIRED, 2.7: DONE, 3.0: REQUIRED to 2.5: REQUIRED, 2.6: REQUIRED, 2.7: DONE, 3.0: DONE
ruby_3_0 855401da495117fcf5d258fe43b71010abc43d9a merged revision(s) a85ed626f18d1014d09fb37eb0a703976c3d2b53.