-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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 hang/incorrect result for ndigits(n,b) when b < 0 #8266
Conversation
@danluu you are the master at breaking stuff 👍 |
Maybe a negative base should just be an error? |
It's used occasionally, and handling the negative case correctly should have the same performance impact on the common case as checking for an error, so why not just return the right answer? |
Fair enough. I notice this is also broken for I think it would be more robust to (1) use integer ceiling division instead of |
After changing this, I remembered why I didn't do this inside ndigits0z, which is that |
Personally I kind of dislike the use of |
I'm just going to throw an error in the bigint case when |
This change would definitely be cleaner if the signed version didn't call the unsigned version. Separating those two seems like an ok thing to do, but what if someone really wants ndigits(::Unsigned, ::Integer)? That can't just call ndigits(signed(n), b) without the possibility of overflowing the conversion. |
I think ideally most functions would use just |
I think some of optimized code will break if things are just changed to It should be possible to write something a clean/fast version that doesn't have separate |
Yes a larger refactoring can certainly come later. |
Also, I just merged the |
I don't think this issue is exposed in public APIs, but could cause a problem potentially:
|
Is that on a previous version? here's what I get on my latest version:
Manually tracing through the code, we have:
We should have m = 1, n = 0, which will cause us to skip the loop and just return 0. |
Oh, nevermind, I need to change that. I got a stale version when I switched machines. |
function ndigits0z(n::Unsigned, b::Int) | ||
d = 0 | ||
if b < 0 | ||
d = ndigitsnb(signed(n), b) |
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.
Should this call ndigits0znb
?
Is this a bugfix we should @JuliaBackports? |
Answering my own question. No, this is not a minimal bugfix, but depends on other new functionality. |
Looks like this new test was never added to the list in |
(cherry picked from commit ff0470c) ref PR #9620 Conflicts: test/combinatorics.jl TST intfuncs more coverage (cherry picked from commit 3d376d1) (leave out ndigits tests that rely on #8266 which was not backported) Conflicts: test/intfuncs.jl TST fix 32bit bits test, add comment to interesting binomial result (cherry picked from commit 93f6ccb)
This presently hangs for n large enough to trigger the slow division code path in
ndigits0z
, since we have n::unsigned and we try to put a negative number in there, which turns into a huge unsigned number.For smaller n, the result is wrong in most cases when b < 0.
This PR doesn't optimize the negative base version the same way the positive base version is optimized, but it at least doesn't hang and works for the cases I've tried.