-
Notifications
You must be signed in to change notification settings - Fork 160
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix bug in BlistList
for two ranges that could lead to wrong results
#3689
Conversation
Several results were wrong, and had been wrong since at least GAP 4.4. E.g. before this commit: gap> BlistList([0..3], [-3..-1]); [ true, true, true, false ] Now we get the correct result gap> BlistList([0,1,2,3], [-3..-1]); [ false, false, false, false ] One major issue was the use of unsigned variables to store signed data. Two variables were only of type `long` instead of `Int`, but on 64bit, this could lead to further issues. The logic handling the intersection was broken and overly complicated. The rewritten logic should be simpler. Finally, there is a tiny optimization enabled by switching from 1-based indexing to 0-based.
// compute bounds | ||
i = t - s; | ||
j = lenSub + i; | ||
if (i < 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that it is crucial to compute i and j before capping the bounds; clearly the previous two lines do not commute; yet in the old code, they were in the wrong order.
long s, t; /* elements of a range */ | ||
Int lenSub; /* logical length of sublist */ | ||
Int i, j, k, l; /* loop variables */ | ||
Int s, t; /* elements of a range */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s, t were just of type long
, so in 64 bit mode, with compilers where long is only 32 bit (basically anywhere except some Microsoft / Windows compilers), there could be overflow here. I didn't add tests for that, though.
for ( ; k+BIPEB < j; k += BIPEB ) | ||
ptrBlist[k/BIPEB] = ~(UInt)0; | ||
for ( ; k < j; k++ ) | ||
ptrBlist[k/BIPEB] |= (1UL << k%BIPEB); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that k-1
changed to k
by adjusting the bounds. I hope the optimizer would have produced identical results in both cases; but the result is certainly slightly easier to read.
Backported to stable-4.11 in 8761c8f |
BlistList
for two ranges that could lead to wrong results
BlistList
for two ranges that could lead to wrong resultsBlistList
for two ranges that could lead to wrong results
Several results were wrong, and had been wrong since at least GAP 4.4.
E.g. before this commit:
Now we get the correct result
One major issue was the use of unsigned variables to store signed data. Two
variables were only of type
long
instead ofInt
, but on 64bit, this couldlead to further issues.
The logic handling the intersection was broken and overly complicated. The
rewritten logic should be simpler.
Finally, there is a tiny optimization enabled by switching from 1-based
indexing to 0-based.