From 16516b5fbf8edd00ce848daf6b4c0d811a4828f5 Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Mon, 17 Sep 2018 08:51:29 -0400 Subject: [PATCH] =?UTF-8?q?fix=20digits(n::Unsigned)=20with=20neg=20base?= =?UTF-8?q?=20for=20`n=20>=20typemax(n)=C3=B72`=20(#29205)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Alternative based on https://github.com/JuliaLang/julia/pull/29187 Tests from rforquet's PR linked above. --- base/intfuncs.jl | 24 ++++++++++++++++-------- test/intfuncs.jl | 9 ++++++++- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index a6f6ea05efe41..8b9f3d441ec01 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -744,17 +744,25 @@ julia> digits!([2,2,2,2,2,2], 10, base = 2) ``` """ 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) 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")) - for i in eachindex(a) - if base > 0 - a[i] = rem(n, base) - n = div(n, base) - else - a[i] = mod(n, -base) - n = cld(n, base) + isempty(a) && return a + + if base > 0 + for i in eachindex(a) + n, d = divrem(n, base) + a[i] = d + end + else + # manually peel one loop iteration for type stability + n, d = fldmod(n, -base) + a[firstindex(a)] = d + n = -signed(n) + for i in firstindex(a)+1:lastindex(a) + n, d = fldmod(n, -base) + a[i] = d + n = -n end end return a 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,