From d31b047c8c133b94e4dfb12aee4df93976843407 Mon Sep 17 00:00:00 2001 From: Jeffrey Sarnoff Date: Fri, 27 Mar 2020 16:06:14 -0400 Subject: [PATCH] x % Unsigned, x % Signed (#34864) --- NEWS.md | 2 ++ base/int.jl | 40 ++++++++++++++++++++++++++++++++++++---- test/gmp.jl | 9 +++++++++ test/int.jl | 11 +++++++++++ 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/NEWS.md b/NEWS.md index b5917eab73c9d..8654d94fadcbc 100644 --- a/NEWS.md +++ b/NEWS.md @@ -93,6 +93,8 @@ New library features * `isapprox` (or `≈`) now has a one-argument "curried" method `isapprox(x)` which returns a function, like `isequal` (or `==`)` ([#32305]). * `Ref{NTuple{N,T}}` can be passed to `Ptr{T}`/`Ref{T}` `ccall` signatures ([#34199]) +* `x::Signed % Unsigned` and `x::Unsigned % Signed` are supported for integer bitstypes. +* `signed(unsigned_type)` is supported for integer bitstypes, `unsigned(signed_type)` has been supported. * `accumulate`, `cumsum`, and `cumprod` now support `Tuple` ([#34654]) and arbitrary iterators ([#34656]). * In `splice!` with no replacement, values to be removed can now be specified with an arbitrary iterable (instead of a `UnitRange`) ([#34524]). diff --git a/base/int.jl b/base/int.jl index 169adf424abc9..f349cd0bce233 100644 --- a/base/int.jl +++ b/base/int.jl @@ -44,6 +44,39 @@ const BitUnsigned64T = Union{Type{UInt8}, Type{UInt16}, Type{UInt32}, Type{UIn const BitIntegerType = Union{map(T->Type{T}, BitInteger_types)...} +# >> this use of `unsigned` is defined somewhere else << the docstring should migrate there +""" + unsigned(T::Integer) + +Convert an integer bitstype to the unsigned type of the same size. +# Examples +```jldoctest +julia> unsigned(Int16) +UInt16 +julia> unsigned(UInt64) +UInt64 +``` +""" unsigned + +""" + signed(T::Integer) + +Convert an integer bitstype to the signed type of the same size. +# Examples +```jldoctest +julia> signed(UInt16) +Int16 +julia> signed(UInt64) +Int64 +``` +""" +signed(::Type{UInt8}) = Int8 +signed(::Type{UInt16}) = Int16 +signed(::Type{UInt32}) = Int32 +signed(::Type{UInt64}) = Int64 +signed(::Type{UInt128}) = Int128 +signed(::Type{T}) where {T<:Signed} = T + ## integer comparisons ## (<)(x::T, y::T) where {T<:BitSigned} = slt_int(x, y) @@ -138,19 +171,16 @@ abs(x::Signed) = flipsign(x,x) ~(n::Integer) = -n-1 """ - unsigned(x) -> Unsigned + unsigned(x) Convert a number to an unsigned integer. If the argument is signed, it is reinterpreted as unsigned without checking for negative values. - # Examples ```jldoctest julia> unsigned(-2) 0xfffffffffffffffe - julia> unsigned(2) 0x0000000000000002 - julia> signed(unsigned(-2)) -2 ``` @@ -506,6 +536,8 @@ if nameof(@__MODULE__) === :Base end rem(x::T, ::Type{T}) where {T<:Integer} = x +rem(x::Signed, ::Type{Unsigned}) = x % unsigned(typeof(x)) +rem(x::Unsigned, ::Type{Signed}) = x % signed(typeof(x)) rem(x::Integer, T::Type{<:Integer}) = convert(T, x) # `x % T` falls back to `convert` rem(x::Integer, ::Type{Bool}) = ((x & 1) != 0) mod(x::Integer, ::Type{T}) where {T<:Integer} = rem(x, T) diff --git a/test/gmp.jl b/test/gmp.jl index 078e0f5d5a6aa..748744b04462a 100644 --- a/test/gmp.jl +++ b/test/gmp.jl @@ -451,6 +451,15 @@ end @test big(Int128(-170141183460469231731687303715884105728)) == big"-170141183460469231731687303715884105728" end +@testset "type conversion with Signed, Unsigned" begin + x = BigInt(typemin(Int128)) - 1 + @test x % Signed === x + @test_throws MethodError x % Unsigned + y = BigInt(1) + @test y % Signed === y + @test_throws MethodError y % Unsigned +end + @testset "conversion to Float" begin x = big"2"^256 + big"2"^(256-53) + 1 @test Float64(x) == reinterpret(Float64, 0x4ff0000000000001) diff --git a/test/int.jl b/test/int.jl index 0ed8f3f771912..aa5bd1c0d22d3 100644 --- a/test/int.jl +++ b/test/int.jl @@ -267,6 +267,17 @@ end @test typeof(rand(U(0):U(127)) % T) === T end +@testset "Signed, Unsigned, signed, unsigned for bitstypes" begin + for (S,U) in zip(Base.BitSigned_types, Base.BitUnsigned_types) + @test signed(U) === S + @test unsigned(S) === U + @test typemin(S) % Signed === typemin(S) + @test typemax(U) % Unsigned === typemax(U) + @test -one(S) % Unsigned % Signed === -one(S) + @test ~one(U) % Signed % Unsigned === ~one(U) + end +end + @testset "issue #15489" begin @test 0x00007ffea27edaa0 + (-40) === (-40) + 0x00007ffea27edaa0 === 0x00007ffea27eda78 @test UInt64(1) * Int64(-1) === typemax(UInt64)