From 9f770e48e25e317fdcba078b437d2e084e2dff67 Mon Sep 17 00:00:00 2001 From: Petr Vana Date: Wed, 22 Sep 2021 09:19:23 +0200 Subject: [PATCH 1/7] Fix Printf for typemin(<:Signed) --- stdlib/Printf/src/Printf.jl | 8 +++++++- stdlib/Printf/test/runtests.jl | 11 +++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/stdlib/Printf/src/Printf.jl b/stdlib/Printf/src/Printf.jl index 8dacee5a1dc1b..15946fddc4eb3 100644 --- a/stdlib/Printf/src/Printf.jl +++ b/stdlib/Printf/src/Printf.jl @@ -292,7 +292,13 @@ fmt(buf, pos, arg::AbstractFloat, spec::Spec{T}) where {T <: Ints} = bs = base(T) arg2 = toint(arg) n = i = ndigits(arg2, base=bs, pad=1) - x, neg = arg2 < 0 ? (-arg2, true) : (arg2, false) + one = oneunit(arg2) + neg = arg2 < 0 + if typeof(arg2) <: Signed && !(typeof(arg2) <: BigInt) + x = neg ? unsigned(-(arg2+one))+one : unsigned(arg2) + else + x = neg ? -arg2 : arg2 + end arglen = n + (neg || (plus | space)) + (T == Val{'o'} && hash ? 1 : 0) + (T == Val{'x'} && hash ? 2 : 0) + (T == Val{'X'} && hash ? 2 : 0) diff --git a/stdlib/Printf/test/runtests.jl b/stdlib/Printf/test/runtests.jl index 3d7929c42e9e0..e80cbe9626823 100644 --- a/stdlib/Printf/test/runtests.jl +++ b/stdlib/Printf/test/runtests.jl @@ -762,6 +762,17 @@ end @test Printf.@sprintf("%20.0X", UInt(3989525555)) == " EDCB5433" @test Printf.@sprintf("%20.X", UInt(0)) == " 0" + # issue #41971 + @test Printf.@sprintf("%4d", typemin(Int8)) == "-128" + @test Printf.@sprintf("%4d", typemax(Int8)) == " 127" + @test Printf.@sprintf("%6d", typemin(Int16)) == "-32768" + @test Printf.@sprintf("%6d", typemax(Int16)) == " 32767" + @test Printf.@sprintf("%11d", typemin(Int32)) == "-2147483648" + @test Printf.@sprintf("%11d", typemax(Int32)) == " 2147483647" + @test Printf.@sprintf("%20d", typemin(Int64)) == "-9223372036854775808" + @test Printf.@sprintf("%20d", typemax(Int64)) == " 9223372036854775807" + @test Printf.@sprintf("%40d", typemin(Int128)) == "-170141183460469231731687303715884105728" + @test Printf.@sprintf("%40d", typemax(Int128)) == " 170141183460469231731687303715884105727" end @testset "%n" begin From 871dd875187cfc50ee707e0a8872c7b869e8f942 Mon Sep 17 00:00:00 2001 From: Petr Vana Date: Wed, 22 Sep 2021 09:46:49 +0200 Subject: [PATCH 2/7] Enforce the unsigned type --- stdlib/Printf/src/Printf.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Printf/src/Printf.jl b/stdlib/Printf/src/Printf.jl index 15946fddc4eb3..9a13dcd289215 100644 --- a/stdlib/Printf/src/Printf.jl +++ b/stdlib/Printf/src/Printf.jl @@ -295,7 +295,7 @@ fmt(buf, pos, arg::AbstractFloat, spec::Spec{T}) where {T <: Ints} = one = oneunit(arg2) neg = arg2 < 0 if typeof(arg2) <: Signed && !(typeof(arg2) <: BigInt) - x = neg ? unsigned(-(arg2+one))+one : unsigned(arg2) + x = neg ? unsigned(-(arg2+one))+unsigned(one) : unsigned(arg2) else x = neg ? -arg2 : arg2 end From d104f5e7c899a2ae3479cbb1d196669150591613 Mon Sep 17 00:00:00 2001 From: Petr Vana Date: Wed, 22 Sep 2021 11:08:01 +0200 Subject: [PATCH 3/7] Simplify the code thanks to defined overflow behavior in Julia --- stdlib/Printf/src/Printf.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stdlib/Printf/src/Printf.jl b/stdlib/Printf/src/Printf.jl index 9a13dcd289215..6cadb4876e23d 100644 --- a/stdlib/Printf/src/Printf.jl +++ b/stdlib/Printf/src/Printf.jl @@ -292,10 +292,9 @@ fmt(buf, pos, arg::AbstractFloat, spec::Spec{T}) where {T <: Ints} = bs = base(T) arg2 = toint(arg) n = i = ndigits(arg2, base=bs, pad=1) - one = oneunit(arg2) neg = arg2 < 0 if typeof(arg2) <: Signed && !(typeof(arg2) <: BigInt) - x = neg ? unsigned(-(arg2+one))+unsigned(one) : unsigned(arg2) + x = unsigned(neg ? -arg2 : arg2) else x = neg ? -arg2 : arg2 end From 0262f4cf567d6922f3288597dfd0e45f267a50fa Mon Sep 17 00:00:00 2001 From: Petr Vana Date: Wed, 22 Sep 2021 12:20:33 +0200 Subject: [PATCH 4/7] Update type check because BigInt (and maybe other user-defined types) are <: Signed --- stdlib/Printf/src/Printf.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Printf/src/Printf.jl b/stdlib/Printf/src/Printf.jl index 6cadb4876e23d..6c2b704b8dfaa 100644 --- a/stdlib/Printf/src/Printf.jl +++ b/stdlib/Printf/src/Printf.jl @@ -293,7 +293,7 @@ fmt(buf, pos, arg::AbstractFloat, spec::Spec{T}) where {T <: Ints} = arg2 = toint(arg) n = i = ndigits(arg2, base=bs, pad=1) neg = arg2 < 0 - if typeof(arg2) <: Signed && !(typeof(arg2) <: BigInt) + if typeof(arg2) <: Union{Int8, Int16, Int32, Int64, Int128} x = unsigned(neg ? -arg2 : arg2) else x = neg ? -arg2 : arg2 From a8798a7cf60a4aa4cf27b13e6ff08d0509ba84a2 Mon Sep 17 00:00:00 2001 From: Petr Vana Date: Wed, 22 Sep 2021 12:41:47 +0200 Subject: [PATCH 5/7] Use Base.BitSigned --- stdlib/Printf/src/Printf.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Printf/src/Printf.jl b/stdlib/Printf/src/Printf.jl index 6c2b704b8dfaa..ebc77c2172d48 100644 --- a/stdlib/Printf/src/Printf.jl +++ b/stdlib/Printf/src/Printf.jl @@ -293,7 +293,7 @@ fmt(buf, pos, arg::AbstractFloat, spec::Spec{T}) where {T <: Ints} = arg2 = toint(arg) n = i = ndigits(arg2, base=bs, pad=1) neg = arg2 < 0 - if typeof(arg2) <: Union{Int8, Int16, Int32, Int64, Int128} + if typeof(arg2) <: Base.BitSigned x = unsigned(neg ? -arg2 : arg2) else x = neg ? -arg2 : arg2 From 0b6b06c58e6c36d744d34844e6cf194d6a63cff6 Mon Sep 17 00:00:00 2001 From: Petr Vana Date: Thu, 23 Sep 2021 20:50:23 +0200 Subject: [PATCH 6/7] Replace typeof(x) <: T by x isa T Co-authored-by: Jeff Bezanson --- stdlib/Printf/src/Printf.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Printf/src/Printf.jl b/stdlib/Printf/src/Printf.jl index ebc77c2172d48..7e47f46be8e56 100644 --- a/stdlib/Printf/src/Printf.jl +++ b/stdlib/Printf/src/Printf.jl @@ -293,7 +293,7 @@ fmt(buf, pos, arg::AbstractFloat, spec::Spec{T}) where {T <: Ints} = arg2 = toint(arg) n = i = ndigits(arg2, base=bs, pad=1) neg = arg2 < 0 - if typeof(arg2) <: Base.BitSigned + if arg2 isa Base.BitSigned x = unsigned(neg ? -arg2 : arg2) else x = neg ? -arg2 : arg2 From c128d04cb36759ffb596bf029f9c9450629db049 Mon Sep 17 00:00:00 2001 From: Petr Vana Date: Thu, 23 Sep 2021 22:17:35 +0200 Subject: [PATCH 7/7] Simplify to one-liner code using abs() --- stdlib/Printf/src/Printf.jl | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/stdlib/Printf/src/Printf.jl b/stdlib/Printf/src/Printf.jl index 7e47f46be8e56..b7487db017d45 100644 --- a/stdlib/Printf/src/Printf.jl +++ b/stdlib/Printf/src/Printf.jl @@ -293,11 +293,7 @@ fmt(buf, pos, arg::AbstractFloat, spec::Spec{T}) where {T <: Ints} = arg2 = toint(arg) n = i = ndigits(arg2, base=bs, pad=1) neg = arg2 < 0 - if arg2 isa Base.BitSigned - x = unsigned(neg ? -arg2 : arg2) - else - x = neg ? -arg2 : arg2 - end + x = arg2 isa Base.BitSigned ? unsigned(abs(arg2)) : abs(arg2) arglen = n + (neg || (plus | space)) + (T == Val{'o'} && hash ? 1 : 0) + (T == Val{'x'} && hash ? 2 : 0) + (T == Val{'X'} && hash ? 2 : 0)