From 1a5a012854fcaa436fb86f01010ccb8179f98cec Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Tue, 18 Dec 2018 19:04:31 -0500 Subject: [PATCH 01/11] Add `signed(T)`, `unsigned(T)`. Converts Types into their corresponding signed/unsigned equivalents, maintaining storage size, but changing signed-ness. --- base/int.jl | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/base/int.jl b/base/int.jl index 8de57b0f18cac..8885bb6dc5bec 100644 --- a/base/int.jl +++ b/base/int.jl @@ -137,7 +137,19 @@ abs(x::Signed) = flipsign(x,x) ~(n::Integer) = -n-1 -unsigned(x::BitSigned) = reinterpret(typeof(convert(Unsigned, zero(x))), x) +""" + unsigned(T) -> Unsigned equivalent to T + +Get the corresponding unsigned type for T. + +# Examples +```jldoctest +julia> unsigned(Int8) +UInt8 +``` +""" +unsigned(::Type{T}) where {T<:BitSigned} = typeof(convert(Unsigned, zero(T))) +unsigned(x::BitSigned) = reinterpret(unsigned(typeof(x)), x) unsigned(x::Bool) = convert(Unsigned, x) """ @@ -159,7 +171,14 @@ julia> signed(unsigned(-2)) ``` """ unsigned(x) = convert(Unsigned, x) -signed(x::Unsigned) = reinterpret(typeof(convert(Signed, zero(x))), x) + +""" + signed(T) -> Signed equivalent to T + +Get the corresponding signed type for T. +""" +signed(::Type{T}) where {T<:Unsigned} = typeof(convert(Signed, zero(T))) +signed(x::Unsigned) = reinterpret(signed(typeof(x)), x) """ signed(x) From 64e0bdeead6a343c2433bef34dea37b736627535 Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Tue, 18 Dec 2018 19:08:10 -0500 Subject: [PATCH 02/11] Switch order of `unsigned(x)` and `unsigned(T)` for docstring --- base/int.jl | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/base/int.jl b/base/int.jl index 8885bb6dc5bec..254653c757081 100644 --- a/base/int.jl +++ b/base/int.jl @@ -137,21 +137,6 @@ abs(x::Signed) = flipsign(x,x) ~(n::Integer) = -n-1 -""" - unsigned(T) -> Unsigned equivalent to T - -Get the corresponding unsigned type for T. - -# Examples -```jldoctest -julia> unsigned(Int8) -UInt8 -``` -""" -unsigned(::Type{T}) where {T<:BitSigned} = typeof(convert(Unsigned, zero(T))) -unsigned(x::BitSigned) = reinterpret(unsigned(typeof(x)), x) -unsigned(x::Bool) = convert(Unsigned, x) - """ unsigned(x) -> Unsigned @@ -173,12 +158,19 @@ julia> signed(unsigned(-2)) unsigned(x) = convert(Unsigned, x) """ - signed(T) -> Signed equivalent to T + unsigned(T) -> Unsigned equivalent to T -Get the corresponding signed type for T. +Get the corresponding unsigned type for T. + +# Examples +```jldoctest +julia> unsigned(Int8) +UInt8 +``` """ -signed(::Type{T}) where {T<:Unsigned} = typeof(convert(Signed, zero(T))) -signed(x::Unsigned) = reinterpret(signed(typeof(x)), x) +unsigned(::Type{T}) where {T<:BitSigned} = typeof(convert(Unsigned, zero(T))) +unsigned(x::BitSigned) = reinterpret(unsigned(typeof(x)), x) +unsigned(x::Bool) = convert(Unsigned, x) """ signed(x) @@ -188,6 +180,15 @@ signed without checking for overflow. """ signed(x) = convert(Signed, x) +""" + signed(T) -> Signed equivalent to T + +Get the corresponding signed type for T. +""" +signed(::Type{T}) where {T<:Unsigned} = typeof(convert(Signed, zero(T))) +signed(x::Unsigned) = reinterpret(signed(typeof(x)), x) + + div(x::BitSigned, y::Unsigned) = flipsign(signed(div(unsigned(abs(x)), y)), x) div(x::Unsigned, y::BitSigned) = unsigned(flipsign(signed(div(x, unsigned(abs(y)))), y)) From eab2d5415307526ec32e378252ade200cdfd3b34 Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Wed, 19 Dec 2018 12:31:45 -0500 Subject: [PATCH 03/11] Restore `[un]signed(x)` impls; use for `signed(T)` Also, since I restored the original definitions, I also reordered the methods back to their original places. --- base/int.jl | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/base/int.jl b/base/int.jl index 254653c757081..427474487a4b3 100644 --- a/base/int.jl +++ b/base/int.jl @@ -137,6 +137,9 @@ abs(x::Signed) = flipsign(x,x) ~(n::Integer) = -n-1 +unsigned(x::BitSigned) = reinterpret(typeof(convert(Unsigned, zero(x))), x) +unsigned(x::Bool) = convert(Unsigned, x) + """ unsigned(x) -> Unsigned @@ -157,6 +160,17 @@ julia> signed(unsigned(-2)) """ unsigned(x) = convert(Unsigned, x) +signed(x::Unsigned) = reinterpret(typeof(convert(Signed, zero(x))), x) + +""" + signed(x) + +Convert a number to a signed integer. If the argument is unsigned, it is reinterpreted as +signed without checking for overflow. +""" +signed(x) = convert(Signed, x) + + """ unsigned(T) -> Unsigned equivalent to T @@ -168,25 +182,13 @@ julia> unsigned(Int8) UInt8 ``` """ -unsigned(::Type{T}) where {T<:BitSigned} = typeof(convert(Unsigned, zero(T))) -unsigned(x::BitSigned) = reinterpret(unsigned(typeof(x)), x) -unsigned(x::Bool) = convert(Unsigned, x) - -""" - signed(x) - -Convert a number to a signed integer. If the argument is unsigned, it is reinterpreted as -signed without checking for overflow. -""" -signed(x) = convert(Signed, x) - +unsigned(::Type{T}) where {T<:BitSigned} = typeof(unsigned(zero(T))) """ signed(T) -> Signed equivalent to T Get the corresponding signed type for T. """ -signed(::Type{T}) where {T<:Unsigned} = typeof(convert(Signed, zero(T))) -signed(x::Unsigned) = reinterpret(signed(typeof(x)), x) +signed(::Type{T}) where {T<:Unsigned} = typeof(signed(zero(T))) div(x::BitSigned, y::Unsigned) = flipsign(signed(div(unsigned(abs(x)), y)), x) From 6a34de1b3f978eacd359d548335c0f2ee7a3d3e5 Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Wed, 19 Dec 2018 12:54:54 -0500 Subject: [PATCH 04/11] Add tests for [un]signed(T). Fix signed(Int)==Int. Added unit tests, and also added the missing implementations for calling `signed` on already signed types and same for `unsigned`. --- base/int.jl | 2 ++ test/int.jl | 24 ++++++++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/base/int.jl b/base/int.jl index 427474487a4b3..d840679bafd6b 100644 --- a/base/int.jl +++ b/base/int.jl @@ -183,12 +183,14 @@ UInt8 ``` """ unsigned(::Type{T}) where {T<:BitSigned} = typeof(unsigned(zero(T))) +unsigned(::Type{T}) where {T<:Unsigned} = T """ signed(T) -> Signed equivalent to T Get the corresponding signed type for T. """ signed(::Type{T}) where {T<:Unsigned} = typeof(signed(zero(T))) +signed(::Type{T}) where {T<:BitSigned} = T div(x::BitSigned, y::Unsigned) = flipsign(signed(div(unsigned(abs(x)), y)), x) diff --git a/test/int.jl b/test/int.jl index a1f3d51d9bb55..166b47654ca7c 100644 --- a/test/int.jl +++ b/test/int.jl @@ -55,11 +55,27 @@ using Random end end @testset "signed" begin - @test signed(3) == 3 - @test signed(UInt(3)) == 3 + @test signed(3) === 3 + @test signed(UInt(3)) === 3 @test isa(signed(UInt(3)), Int) - @test signed(UInt(0) - 1) == -1 - @test_throws InexactError signed(UInt(-3)) + @test signed(UInt(0) - 1) === -1 + @test_throws InexactError signed(UInt(-3)) # Note that UInt() throws, not signed(). +end +@testset "unsigned" begin + @test unsigned(3) === UInt(3) + @test unsigned(UInt(3)) === UInt(3) + @test isa(unsigned(3), UInt) + @test unsigned(-1) === typemax(UInt) + @test_throws InexactError unsigned(Int(typemax(UInt))) # Int(0xffffffff...) throws +end +@testset "[un]signed(::Type{T})" begin + @testset for (T,UT) in ((Int8,UInt8), (Int,UInt), (Int128,UInt128)) + @test unsigned(T) === UT + @test unsigned(UT) === UT + @test signed(T) === T + @test signed(UT) === T + end + @test unsigned(typeof(3))(3) === unsigned(3) end @testset "bswap" begin @test bswap(Int8(3)) == 3 From 4af0d13c40374eaa53ec002a62285ba39c323ca1 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Thu, 20 Dec 2018 17:49:24 -0500 Subject: [PATCH 05/11] Apply @fredrikekre's suggestions from code review Fixes docstrings for `unsigned(T::Type)` and `signed(T::Type)`. Co-Authored-By: NHDaly --- base/int.jl | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/base/int.jl b/base/int.jl index d840679bafd6b..eef1c2c74d60f 100644 --- a/base/int.jl +++ b/base/int.jl @@ -172,9 +172,12 @@ signed(x) = convert(Signed, x) """ - unsigned(T) -> Unsigned equivalent to T + unsigned(T::Type) -Get the corresponding unsigned type for T. +Return the corresponding unsigned type for type `T`. + +!!! compat "Julia 1.2" + This method requires Julia 1.2 or later. # Examples ```jldoctest @@ -185,9 +188,18 @@ UInt8 unsigned(::Type{T}) where {T<:BitSigned} = typeof(unsigned(zero(T))) unsigned(::Type{T}) where {T<:Unsigned} = T """ - signed(T) -> Signed equivalent to T + signed(T::Type) + +Return the corresponding signed type for type `T`. -Get the corresponding signed type for T. +!!! compat "Julia 1.2" + This method requires Julia 1.2 or later. + +#Examples +```jldoctest +julia> signed(UInt8) +Int8 +``` """ signed(::Type{T}) where {T<:Unsigned} = typeof(signed(zero(T))) signed(::Type{T}) where {T<:BitSigned} = T From 81ae5ec8cc6415b2144924e2f015e2e1224dc98c Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Thu, 20 Dec 2018 17:51:51 -0500 Subject: [PATCH 06/11] Add NEWS.md entry --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index 14dcdd7635aad..7e2979b823601 100644 --- a/NEWS.md +++ b/NEWS.md @@ -6,6 +6,8 @@ New language features * The `extrema` function now accepts a function argument in the same manner as `minimum` and `maximum` ([#30323]). +* There are new method overloads `unsigned(T::Type)` and `signed(T::Type)` that accept a `Type`, + and return its corresponding signed/unsigned equivalent type ([#30445]). Multi-threading changes ----------------------- @@ -49,3 +51,4 @@ Deprecated or removed [#29998]: https://github.com/JuliaLang/julia/issues/29998 [#30323]: https://github.com/JuliaLang/julia/issues/30323 +[#30445]: https://github.com/JuliaLang/julia/issues/30445 From 3a6339c4a243e7698a53d3aa1e96595b3b8845bc Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Wed, 2 Jan 2019 10:25:45 -0500 Subject: [PATCH 07/11] Fix trailing whitespace in docstring Line 202 had trailing whitespace in the docstring which broke the tests. Fixed. --- base/int.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/int.jl b/base/int.jl index eef1c2c74d60f..750b9dcd4c680 100644 --- a/base/int.jl +++ b/base/int.jl @@ -199,7 +199,7 @@ Return the corresponding signed type for type `T`. ```jldoctest julia> signed(UInt8) Int8 -``` +``` """ signed(::Type{T}) where {T<:Unsigned} = typeof(signed(zero(T))) signed(::Type{T}) where {T<:BitSigned} = T From fabe5b02e16697e1338463a76783277862719daa Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Wed, 2 Jan 2019 10:27:42 -0500 Subject: [PATCH 08/11] Remove generated link at bottom of NEWS to fix conflicts Now that I understand we're not supposed to generate these every time, i've removed the generated links to prevent conflicts. --- NEWS.md | 1 - 1 file changed, 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 7e2979b823601..4532ec251a750 100644 --- a/NEWS.md +++ b/NEWS.md @@ -51,4 +51,3 @@ Deprecated or removed [#29998]: https://github.com/JuliaLang/julia/issues/29998 [#30323]: https://github.com/JuliaLang/julia/issues/30323 -[#30445]: https://github.com/JuliaLang/julia/issues/30445 From 8369cfe0dd4d9d38ffe09e3e89214ed1e097afc2 Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Tue, 31 Dec 2019 12:17:57 -0500 Subject: [PATCH 09/11] Update compat note to Julia 1.4 --- base/int.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/int.jl b/base/int.jl index cc67cee6ec126..c7cf6e012a22d 100644 --- a/base/int.jl +++ b/base/int.jl @@ -173,8 +173,8 @@ signed(x::BitUnsigned) = reinterpret(typeof(convert(Signed, zero(x))), x) Return the corresponding unsigned type for type `T`. -!!! compat "Julia 1.2" - This method requires Julia 1.2 or later. +!!! compat "Julia 1.4" + signed(T)/unsigned(T) on Types requires Julia 1.4 or later. # Examples ```jldoctest @@ -189,8 +189,8 @@ unsigned(::Type{T}) where {T<:Unsigned} = T Return the corresponding signed type for type `T`. -!!! compat "Julia 1.2" - This method requires Julia 1.2 or later. +!!! compat "Julia 1.4" + signed(T)/unsigned(T) on Types requires Julia 1.4 or later. #Examples ```jldoctest From 367f744e324bba2d17cbfa6b55c474d147fe4306 Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Tue, 31 Dec 2019 12:22:05 -0500 Subject: [PATCH 10/11] Restrict Base.[un]signed(::Type) to BitInteger by default. Users can extend with their own types, just like for [un]signed(v). --- base/int.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/int.jl b/base/int.jl index c7cf6e012a22d..0b1dbe1397203 100644 --- a/base/int.jl +++ b/base/int.jl @@ -182,8 +182,8 @@ julia> unsigned(Int8) UInt8 ``` """ -unsigned(::Type{T}) where {T<:BitSigned} = typeof(unsigned(zero(T))) unsigned(::Type{T}) where {T<:Unsigned} = T +unsigned(::Type{T}) where {T<:BitSigned} = typeof(unsigned(zero(T))) """ signed(T::Type) @@ -198,8 +198,8 @@ julia> signed(UInt8) Int8 ``` """ -signed(::Type{T}) where {T<:Unsigned} = typeof(signed(zero(T))) -signed(::Type{T}) where {T<:BitSigned} = T +signed(::Type{T}) where {T<:Signed} = T +signed(::Type{T}) where {T<:BitUnsigned} = typeof(signed(zero(T))) div(x::BitSigned, y::Unsigned) = flipsign(signed(div(unsigned(abs(x)), y)), x) From b934adf29d45ac4b4a33cf9a6be1f7003c5f469f Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Tue, 31 Dec 2019 12:33:28 -0500 Subject: [PATCH 11/11] Remove now unneeded extra def of `unsigned(::Type)` in multinverses.jl --- base/multinverses.jl | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/base/multinverses.jl b/base/multinverses.jl index 319072e7214ac..68662714f389f 100644 --- a/base/multinverses.jl +++ b/base/multinverses.jl @@ -2,17 +2,10 @@ module MultiplicativeInverses -import Base: div, divrem, rem, unsigned -using Base: IndexLinear, IndexCartesian, tail +import Base: div, divrem, rem +using Base: IndexLinear, IndexCartesian, tail, unsigned export multiplicativeinverse -unsigned(::Type{Int8}) = UInt8 -unsigned(::Type{Int16}) = UInt16 -unsigned(::Type{Int32}) = UInt32 -unsigned(::Type{Int64}) = UInt64 -unsigned(::Type{Int128}) = UInt128 -unsigned(::Type{T}) where {T<:Unsigned} = T - abstract type MultiplicativeInverse{T} end # Computes integer division by a constant using multiply, add, and bitshift.