Skip to content

Commit

Permalink
x % Unsigned, x % Signed (#34864)
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffreySarnoff authored Mar 27, 2020
1 parent 3534bc1 commit d31b047
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 4 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]).
Expand Down
40 changes: 36 additions & 4 deletions base/int.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
```
Expand Down Expand Up @@ -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)
Expand Down
9 changes: 9 additions & 0 deletions test/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
11 changes: 11 additions & 0 deletions test/int.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit d31b047

Please sign in to comment.