From 4273a983123f90efc8b8bbf0e5f66418df704e8d Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Fri, 14 Sep 2018 19:04:48 +0200 Subject: [PATCH 1/3] =?UTF-8?q?fix=20digits(n::Unsigned)=20with=20neg=20ba?= =?UTF-8?q?se=20for=20`n=20>=20typemax(n)=C3=B72`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #29183. The same idea as in #29148 is used. --- base/intfuncs.jl | 17 +++++++++++++++-- test/intfuncs.jl | 9 ++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index a6f6ea05efe41..343bd6045a929 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -743,12 +743,25 @@ julia> digits!([2,2,2,2,2,2], 10, base = 2) 0 ``` """ -function digits!(a::AbstractVector{T}, n::Integer; base::Integer = 10) where T<:Integer - base < 0 && isa(n, Unsigned) && return digits!(a, convert(Signed, n), base = base) +function digits!(a::AbstractVector{T}, n::Integer; base::Integer = 10, skipfirst=false) where T<:Integer 2 <= abs(base) || throw(ArgumentError("base must be ≥ 2 or ≤ -2, got $base")) hastypemax(T) && abs(base) - 1 > typemax(T) && throw(ArgumentError("type $T too small for base $base")) + isempty(a) && return a + + if base < 0 && n isa Unsigned + d = mod(n, -base) + ns = -signed(fld(n, -base)) + digits!(a, ns, base = base, skipfirst=true) + a[firstindex(a)] = d + return a + end + for i in eachindex(a) + if skipfirst + skipfirst = false + continue + end if base > 0 a[i] = rem(n, base) n = div(n, base) diff --git a/test/intfuncs.jl b/test/intfuncs.jl index b060bc69686b2..37033bde31fa4 100644 --- a/test/intfuncs.jl +++ b/test/intfuncs.jl @@ -179,11 +179,18 @@ end @test digits(5, base = 3) == [2, 1] @testset "digits/base with negative bases" begin - @testset "digits(n::$T, base = b)" for T in (Int, UInt, BigInt, Int32) + @testset "digits(n::$T, base = b)" for T in (Int, UInt, BigInt, Int32, UInt32) @test digits(T(8163), base = -10) == [3, 4, 2, 2, 1] if !(T<:Unsigned) @test digits(T(-8163), base = -10) == [7, 7, 9, 9] end + if T !== BigInt + b = rand(-32:-2) + for n = T[rand(T), typemax(T), typemin(T)] + # issue #29183 + @test digits(n, base=b) == digits(signed(widen(n)), base=b) + end + end end @test [string(n, base = b) for n = [-10^9, -10^5, -2^20, -2^10, -100, -83, -50, -34, -27, -16, -7, -3, -2, -1, From ac7d8925820e39807b00189f5e08c52e3973a9a0 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Sun, 16 Sep 2018 16:00:22 +0200 Subject: [PATCH 2/3] rename skipfirst -> _skipfirst --- base/intfuncs.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 343bd6045a929..c69ea8ce44bd4 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -743,7 +743,7 @@ julia> digits!([2,2,2,2,2,2], 10, base = 2) 0 ``` """ -function digits!(a::AbstractVector{T}, n::Integer; base::Integer = 10, skipfirst=false) where T<:Integer +function digits!(a::AbstractVector{T}, n::Integer; base::Integer = 10, _skipfirst=false) where T<:Integer 2 <= abs(base) || throw(ArgumentError("base must be ≥ 2 or ≤ -2, got $base")) hastypemax(T) && abs(base) - 1 > typemax(T) && throw(ArgumentError("type $T too small for base $base")) @@ -752,14 +752,14 @@ function digits!(a::AbstractVector{T}, n::Integer; base::Integer = 10, skipfirst if base < 0 && n isa Unsigned d = mod(n, -base) ns = -signed(fld(n, -base)) - digits!(a, ns, base = base, skipfirst=true) + digits!(a, ns, base = base, _skipfirst=true) a[firstindex(a)] = d return a end for i in eachindex(a) - if skipfirst - skipfirst = false + if _skipfirst + _skipfirst = false continue end if base > 0 From 501d0a53190833c4a2c4b75c15aff08c847f67fa Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Sun, 16 Sep 2018 16:07:24 +0200 Subject: [PATCH 3/3] remove keyword --- base/intfuncs.jl | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index c69ea8ce44bd4..5079989881aa9 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -743,26 +743,23 @@ julia> digits!([2,2,2,2,2,2], 10, base = 2) 0 ``` """ -function digits!(a::AbstractVector{T}, n::Integer; base::Integer = 10, _skipfirst=false) where T<:Integer +function digits!(a::AbstractVector{T}, n::Integer; base::Integer = 10) where T<:Integer 2 <= abs(base) || throw(ArgumentError("base must be ≥ 2 or ≤ -2, got $base")) hastypemax(T) && abs(base) - 1 > typemax(T) && throw(ArgumentError("type $T too small for base $base")) isempty(a) && return a - + skipfirst = false if base < 0 && n isa Unsigned d = mod(n, -base) - ns = -signed(fld(n, -base)) - digits!(a, ns, base = base, _skipfirst=true) - a[firstindex(a)] = d - return a + n = -signed(fld(n, -base)) + skipfirst = true end for i in eachindex(a) - if _skipfirst - _skipfirst = false - continue - end - if base > 0 + if skipfirst + skipfirst = false + a[i] = d + elseif base > 0 a[i] = rem(n, base) n = div(n, base) else