diff --git a/base/gmp.jl b/base/gmp.jl index 1d45bb99b789f..e32f0275654f4 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -525,7 +525,7 @@ function base(b::Integer, n::BigInt) unsafe_wrap(String, p, true) end -function ndigits0zpb(x::BigInt, b::Integer=10) +function ndigits0zpb(x::BigInt, b::Integer) b < 2 && throw(DomainError()) x.size == 0 && return 0 # for consistency with other ndigits0z methods if ispow2(b) && 2 <= b <= 62 # GMP assumes b is in this range diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 350dda898f32c..9c7e99487b906 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -202,7 +202,7 @@ const powers_of_ten = [ 0x000000e8d4a51000, 0x000009184e72a000, 0x00005af3107a4000, 0x00038d7ea4c68000, 0x002386f26fc10000, 0x016345785d8a0000, 0x0de0b6b3a7640000, 0x8ac7230489e80000, ] -function ndigits0z(x::Union{UInt8,UInt16,UInt32,UInt64}) +function ndigits0z(x::Base.BitUnsigned64) lz = (sizeof(x)<<3)-leading_zeros(x) nd = (1233*lz)>>12+1 nd -= x < powers_of_ten[nd] @@ -215,10 +215,11 @@ function ndigits0z(x::UInt128) end return n + ndigits0z(UInt64(x)) end -ndigits0z(x::Integer) = ndigits0z(unsigned(abs(x))) -ndigits(x::Integer) = x==0 ? 1 : ndigits0z(x) -const ndigits_max_mul = Core.sizeof(Int) == 4 ? 69000000 : 290000000000000000 +ndigits0z(x::Base.BitSigned) = ndigits0z(unsigned(abs(x))) + +ndigits0z(x::Integer) = ndigits(x, false) +ndigits(x::Integer, min1::Bool=true) = x==0 ? min1%Int : ndigits0zpb(x, 10) # The suffix "nb" stands for "negative base" function ndigits0znb(n::Integer, b::Integer) @@ -233,6 +234,8 @@ end ndigits0znb(n::Unsigned, b::Integer) = ndigits0znb(signed(n), b) +const ndigits_max_mul = Core.sizeof(Int) == 4 ? 69000000 : 290000000000000000 + # The suffix "pb" stands for "positive base" function ndigits0zpb(n::Unsigned, b::Int) # precondition: b > 1 @@ -253,17 +256,20 @@ function ndigits0zpb(n::Unsigned, b::Int) return d end -ndigits0zpb(x::Integer, b::Integer) = ndigits0zpb(unsigned(abs(x)), Int(b)) +ndigits0zpb(x::Signed, b::Integer) = ndigits0zpb(unsigned(abs(x)), Int(b)) +ndigits0zpb(x::Unsigned, b::Integer) = ndigits0zpb(x, Int(b)) # TODO: test this path (from ndigits below) # The suffix "0z" means that the ouput is 0 on input zero (cf. #16841) """ ndigits0z(n::Integer, b::Integer=10) Return 0 if `n == 0`, otherwise compute the number of digits in number -`n` written in base `b`. +`n` written in base `b`. The base `b` must not be in `[-1, 0, 1]`. """ ndigits0z(x::Integer, b::Integer) = ndigits(x, b, false) +# min1: whether the minimum value of this function should be 1 +# (for the special input value 0), or not (then ndigits(0, b) == 0) function ndigits(x::Integer, b::Integer, min1::Bool=true) if b < -1 x == 0 ? min1%Int : ndigits0znb(x, b) diff --git a/test/bigint.jl b/test/bigint.jl index 4f29b748ac048..086487222ad69 100644 --- a/test/bigint.jl +++ b/test/bigint.jl @@ -278,9 +278,9 @@ ndigits_mismatch(n) = ndigits(n) != ndigits(BigInt(n)) ndigits(big(rand(Int)), rand(63:typemax(Int))) ndigits(big(rand(Int)), big(2)^rand(2:999)) -for i in big([-20:-1;1:20; rand(Int)]) - for b in -10:1 - @test_throws DomainError ndigits(i, b) +for x in big([-20:20; rand(Int)]) + for b in -1:1 + @test_throws DomainError ndigits(x, b) end end diff --git a/test/intfuncs.jl b/test/intfuncs.jl index 9db92315f3d82..106de94e5636b 100644 --- a/test/intfuncs.jl +++ b/test/intfuncs.jl @@ -92,6 +92,11 @@ for b in -1:1 @test_throws DomainError ndigits(rand(Int), b) end +# test unsigned bases work +@test ndigits(9, 0x2) = 4 +@test ndigits(0x9, 0x2) = 4 + + @test bin(3) == "11" @test bin(3, 2) == "11" @test bin(3, 3) == "011"