From caa54131a83b0febc7288625c9b3a5911885774d Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Thu, 13 Sep 2018 21:31:58 +0200 Subject: [PATCH] =?UTF-8?q?fix=20unsigned=20ndigits=20with=20neg=20base=20?= =?UTF-8?q?for=20`n=20>=20typemax(n)=C3=B72`=20(#29148)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 77ec1ec7003dd1ba86770a6be89333259c0e69da) --- base/intfuncs.jl | 3 ++- test/intfuncs.jl | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 2b75f09ac62e71..a6f6ea05efe41d 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -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" diff --git a/test/intfuncs.jl b/test/intfuncs.jl index 4ead5b224fad0c..b060bc69686b2d 100644 --- a/test/intfuncs.jl +++ b/test/intfuncs.jl @@ -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"