Skip to content

Commit

Permalink
use reinterpret(Unsigned,T) instead of unsigned(T), more docs, more t…
Browse files Browse the repository at this point in the history
…ests
  • Loading branch information
rfourquet committed May 25, 2017
1 parent eedbb7a commit 24a7ae6
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 38 deletions.
8 changes: 0 additions & 8 deletions base/docs/helpdb/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2260,14 +2260,6 @@ for sets of arbitrary objects.
"""
Set

"""
signed(x)
Convert a number to a signed integer. If the argument is unsigned, it is reinterpreted as
signed without checking for overflow.
"""
signed

"""
Val{c}
Expand Down
38 changes: 36 additions & 2 deletions base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -144,20 +144,54 @@ oftype(x,c) = convert(typeof(x),c)
Convert a number to an unsigned integer. If the argument is signed, it is reinterpreted as
unsigned without checking for negative values.
See also [`signed`](@ref).
unsigned(T::Type) -> UnsignedType
Return the return-type of unsigned(x::T).
Return the return-type of `unsigned(x::T)`, so that `unsigned(x)::unsigned(typeof(x))`.
```jldoctest
julia> unsigned(12)
0x000000000000000c
julia> unsigned(Int)
julia> unsigned(Int64)
UInt64
julia> unsigned(2.0)
0x0000000000000002
julia> unsigned(2.2)
ERROR: InexactError()
[...]
```
"""
unsigned(x::Int) = reinterpret(UInt, x)

"""
signed(x)
Convert a number to a signed integer. If the argument is unsigned, it is reinterpreted as
signed without checking for overflow.
See also [`unsigned`](@ref).
signed(T::Type) -> SignedType
Return the return-type of `signed(x::T)`, so that `signed(x)::signed(typeof(x))`.
```jldoctest
julia> signed(0xc)
12
julia> signed(UInt64)
Int64
julia> signed(2.0)
2
julia> signed(2.2)
ERROR: InexactError()
[...]
"""
signed(x::UInt) = reinterpret(Int, x)

# conversions used by ccall
Expand Down
10 changes: 9 additions & 1 deletion base/floatfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,17 @@ maxintfloat() = maxintfloat(Float64)

isinteger(x::AbstractFloat) = (x - trunc(x) == 0)

"""
hex2num(str)
Convert a hexadecimal string to the floating point number it represents.
This function, which is inherently type-unstable, returns a `Float16`,
a `Float32`, or a `Float64` depending on the length of the string `str`
(note that this length must hence be no greater than 16).
"""
function hex2num(s::AbstractString)
l = length(s)
l > 16 && throw(ArgumentError("the passed string must be of length <= 16, got $l"))
l > 16 && throw(ArgumentError("the length of the passed string must be <= 16, got $l"))
hex2num(l <= 4 ? Float16 : l <= 8 ? Float32 : Float64, s)
end

Expand Down
6 changes: 6 additions & 0 deletions base/int.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@ const BitReal_types = (BitInteger_types..., BitFloat_types...)
const BitReal = Union{BitReal_types...}

reinterpret(::Type{Unsigned}, x::BitInteger) = unsigned(x)
reinterpret(::Type{ Signed}, x::BitInteger) = signed(x)

unsigned(::Type{T}) where {T<:Unsigned} = T
signed( ::Type{T}) where {T<:Signed} = T

unsigned(::Type{<:Union{Bool,BitFloat}}) = UInt
signed( ::Type{<:Union{Bool,BitFloat}}) = Int

## integer comparisons ##

Expand Down
31 changes: 22 additions & 9 deletions base/intfuncs.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

# this construction is not available when put in int.jl and running in Core
for (S,U,F) in zip(BitSigned_types, BitUnsigned_types,
(nothing, Float16, Float32, Float64, nothing))
@eval begin
unsigned(::Type{$S}) = $U
unsigned(::Type{$U}) = $U
signed( ::Type{$S}) = $S
signed( ::Type{$U}) = $S
reinterpret(::Type{Unsigned}, ::Type{$S}) = $U
reinterpret(::Type{Unsigned}, ::Type{$U}) = $U
reinterpret(::Type{Signed}, ::Type{$S}) = $S
reinterpret(::Type{Signed}, ::Type{$U}) = $S
end
F === nothing && continue
@eval begin
reinterpret(::Type{Unsigned}, ::Type{$F}) = $U
reinterpret(::Type{Signed}, ::Type{$F}) = $S
end
end

## number-theoretic functions ##

"""
Expand Down Expand Up @@ -488,7 +508,7 @@ end
An hexadecimal string of the binary representation of a number.
See also the [`bits`](@ref) function, which is similar but gives
a binary string.
a binary string, and [`hex2num`] which does the opposite conversion.
```jldoctest
julia> num2hex(Int64(4))
Expand All @@ -515,16 +535,9 @@ julia> hex2num(Float64, "400199999999999a")
julia> hex2num(Int32, "fffffffe")
-2
```
hex2num(str)
Convert a hexadecimal string to the floating point number it represents.
This function, which is inherently type-unstable, returns a `Float16`,
a `Float32`, or a `Float64` depending on the length of the string `str`
(note that this length must hence be no greater than 16).
"""
hex2num(::Type{T}, s::AbstractString) where {T<:BitReal} =
reinterpret(T, parse(unsigned(T), s, 16))
reinterpret(T, parse(reinterpret(Unsigned, T), s, 16))

const base36digits = ['0':'9';'a':'z']
const base62digits = ['0':'9';'A':'Z';'a':'z']
Expand Down
12 changes: 1 addition & 11 deletions base/multinverses.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,10 @@

module MultiplicativeInverses

import Base: div, divrem, rem, unsigned
import Base: div, divrem, rem
using Base: IndexLinear, IndexCartesian, tail
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
unsigned(::Type{Float16}) = UInt16
unsigned(::Type{Float32}) = UInt32
unsigned(::Type{Float64}) = UInt64

abstract type MultiplicativeInverse{T} end

# Computes integer division by a constant using multiply, add, and bitshift.
Expand Down
2 changes: 1 addition & 1 deletion test/floatfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ for elty in (Float16,Float32,Float64), _ = 1:10
@test hex2num(num2hex(x)) x
@test hex2num(elty, num2hex(x)) x
end
@test_throws ArgumentError hex2num(String(rand('a':'f', rand(17:100))))
@test_throws ArgumentError hex2num(String(rand(['a':'f';'0':'1'], rand(17:100))))

# round
for elty in (Float32,Float64)
Expand Down
39 changes: 33 additions & 6 deletions test/int.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

# Test integer conversion routines from int.jl

using Base: BitInteger_types, BitFloat_types

for y in (-4, Float32(-4), -4.0, big(-4.0))
@test flipsign(3, y) == -3
Expand All @@ -18,10 +18,10 @@ for y in (4, Float32(4), 4.0, big(4.0))
end

# Result type must be type of first argument
for T in (Base.BitInteger_types..., BigInt,
for T in (BitInteger_types..., BigInt,
Rational{Int}, Rational{BigInt},
Float16, Float32, Float64)
for U in (Base.BitInteger_types..., BigInt,
for U in (BitInteger_types..., BigInt,
Rational{Int}, Rational{BigInt},
Float16, Float32, Float64)
@test typeof(copysign(T(3), U(4))) === T
Expand Down Expand Up @@ -124,7 +124,7 @@ for T in (UInt8, UInt16, UInt32, UInt64)
end

# Test bit shifts
for T in Base.BitInteger_types
for T in BitInteger_types
nbits = 8*sizeof(T)
issigned = typemin(T) < 0
highbit = T(2) ^ (nbits-1)
Expand Down Expand Up @@ -203,7 +203,34 @@ end
@test unsafe_trunc(Int8, -129) === Int8(127)

# Test x % T returns a T
for T in [Base.BitInteger_types..., BigInt],
U in [Base.BitInteger_types..., BigInt]
for T in [BitInteger_types..., BigInt],
U in [BitInteger_types..., BigInt]
@test typeof(rand(U(0):U(127)) % T) === T
end

@testset "reinterpret and unsigned/signed on $T" for T in BitInteger_types
t = -1 % T
A, B = T <: Unsigned ? (Unsigned, Signed) : (Signed, Unsigned)
@test reinterpret(A, reinterpret(B, t)) == t
@test reinterpret(A, t) == t
@test reinterpret(B, t) != t
@test (T <: Unsigned ? unsigned : signed)(T) === T
@test unsigned(T) <: Unsigned
@test signed(T) <: Signed
end

@testset "unsigned/signed(::Bool)" begin
@test signed(true) === 1
@test signed(false) === 0
@test unsigned(true) === 1 % UInt
@test unsigned(false) === 0 % UInt
@test signed(Bool) === Int
@test unsigned(Bool) === UInt
end

@testset "unsigned/signed(::$T)" for T in BitFloat_types
@test signed(T(1)) === Int(1)
@test unsigned(T(1)) === UInt(1)
@test_throws InexactError signed(T(1.1))
@test_throws InexactError unsigned(T(1.1))
end

0 comments on commit 24a7ae6

Please sign in to comment.