Skip to content

Commit

Permalink
fix unsigned ndigits with neg base for n > typemax(n)÷2 (#29148)
Browse files Browse the repository at this point in the history
It relies on the fact that `cld(x, b) == -fld(x, -b)` but does the conversion from unsigned to signed before negating the unsigned quotient; since `-b ≥ 2` the quotient always fits in the signed type.

(cherry picked from commit 77ec1ec)
  • Loading branch information
rfourquet authored and KristofferC committed Sep 17, 2018
1 parent 5ac0cdc commit a031553
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 1 deletion.
3 changes: 2 additions & 1 deletion base/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,8 @@ function ndigits0znb(x::Integer, b::Integer)
return d
end

ndigits0znb(x::Unsigned, b::Integer) = ndigits0znb(signed(x), b)
# do first division before conversion with signed here, which can otherwise overflow
ndigits0znb(x::Unsigned, b::Integer) = ndigits0znb(-signed(fld(x, -b)), b) + (x != 0)
ndigits0znb(x::Bool, b::Integer) = x % Int

# The suffix "pb" stands for "positive base"
Expand Down
9 changes: 9 additions & 0 deletions test/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,15 @@ end
@test iszero([Base.ndigits0z(false, b) for b in [-20:-2;2:20]])
@test all(n -> n == 1, Base.ndigits0z(true, b) for b in [-20:-2;2:20])
@test all(n -> n == 1, ndigits(x, base=b) for b in [-20:-2;2:20] for x in [true, false])

# issue #29148
@test ndigits(typemax(UInt64), base=-2) == ndigits(big(typemax(UInt64)), base=-2)
for T in Base.BitInteger_types
n = rand(T)
b = -rand(2:100)
@test ndigits(n, base=b) == ndigits(big(n), base=b)
end

end
@testset "bin/oct/dec/hex/bits" begin
@test string(UInt32('3'), base = 2) == "110011"
Expand Down

0 comments on commit a031553

Please sign in to comment.