diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index a3f2530e4fef3..97618d987910b 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -76,21 +76,6 @@ Subtraction operator. """ -(x, y) -""" - bits(n) - -A string giving the literal bit representation of a number. - -```jldoctest -julia> bits(4) -"0000000000000000000000000000000000000000000000000000000000000100" - -julia> bits(2.2) -"0100000000000001100110011001100110011001100110011001100110011010" -``` -""" -bits - """ getindex(type[, elements...]) @@ -565,18 +550,6 @@ original string, otherwise they must be from distinct character ranges. """ eachmatch -""" - num2hex(f) - -Get a hexadecimal string of the binary representation of a floating point number. - -```jldoctest -julia> num2hex(2.2) -"400199999999999a" -``` -""" -num2hex - """ truncate(file,n) @@ -1121,13 +1094,6 @@ julia> bin(bswap(1)) """ bswap -""" - maxintfloat(T) - -The largest integer losslessly representable by the given floating-point DataType `T`. -""" -maxintfloat - """ delete!(collection, key) @@ -1360,13 +1326,6 @@ false """ isempty -""" - hex2num(str) - -Convert a hexadecimal string to the floating point number it represents. -""" -hex2num - """ InexactError() @@ -2165,14 +2124,6 @@ Values for `String` can be of that type, or `Vector{UInt8}`. """ isvalid(T,value) -""" - unsigned(x) -> Unsigned - -Convert a number to an unsigned integer. If the argument is signed, it is reinterpreted as -unsigned without checking for negative values. -""" -unsigned - """ reverseind(v, i) diff --git a/base/essentials.jl b/base/essentials.jl index 6e06e23302d1d..11619fb49ff1c 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -138,6 +138,24 @@ convert(::Type{T}, x::T) where {T<:Tuple{Any,Vararg{Any}}} = x oftype(x,c) = convert(typeof(x),c) +""" + unsigned(x) -> Unsigned + +Convert a number to an unsigned integer. If the argument is signed, it is reinterpreted as +unsigned without checking for negative values. + + unsigned(T::Type) -> UnsignedType + +Return the return-type of unsigned(x::T). + +```jldoctest +julia> unsigned(12) +0x000000000000000c + +julia> unsigned(Int) +UInt64 +``` +""" unsigned(x::Int) = reinterpret(UInt, x) signed(x::UInt) = reinterpret(Int, x) diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index a5973c7d99986..9f8384835edcf 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -16,6 +16,11 @@ signbit(x::Float64) = signbit(bitcast(Int64, x)) signbit(x::Float32) = signbit(bitcast(Int32, x)) signbit(x::Float16) = signbit(bitcast(Int16, x)) +""" + maxintfloat(T) + +The largest integer losslessly representable by the given floating-point DataType `T`. +""" maxintfloat(::Type{Float64}) = 9007199254740992. maxintfloat(::Type{Float32}) = Float32(16777216.) maxintfloat(::Type{Float16}) = Float16(2048f0) @@ -24,18 +29,10 @@ maxintfloat() = maxintfloat(Float64) isinteger(x::AbstractFloat) = (x - trunc(x) == 0) -num2hex(x::Float16) = hex(bitcast(UInt16, x), 4) -num2hex(x::Float32) = hex(bitcast(UInt32, x), 8) -num2hex(x::Float64) = hex(bitcast(UInt64, x), 16) - function hex2num(s::AbstractString) - if length(s) <= 4 - return bitcast(Float16, parse(UInt16, s, 16)) - end - if length(s) <= 8 - return bitcast(Float32, parse(UInt32, s, 16)) - end - return bitcast(Float64, parse(UInt64, s, 16)) + l = length(s) + l > 16 && throw(ArgumentError("the passed string must be of length <= 16, got $l")) + hex2num(l <= 4 ? Float16 : l <= 8 ? Float32 : Float64, s) end """ diff --git a/base/int.jl b/base/int.jl index 19b65d5ea8f94..c568335b9f615 100644 --- a/base/int.jl +++ b/base/int.jl @@ -23,6 +23,14 @@ const BitInteger = Union{BitInteger_types...} const BitSigned64T = Union{Type{Int8}, Type{Int16}, Type{Int32}, Type{Int64}} const BitUnsigned64T = Union{Type{UInt8}, Type{UInt16}, Type{UInt32}, Type{UInt64}} +const BitFloat_types = (Float16, Float32, Float64) +const BitFloat = Union{BitFloat_types...} +const BitReal_types = (BitInteger_types..., BitFloat_types...) +const BitReal = Union{BitReal_types...} + +reinterpret(::Type{Unsigned}, x::BitInteger) = unsigned(x) + + ## integer comparisons ## (<)(x::T, y::T) where {T<:BitSigned} = slt_int(x, y) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 50bb11bd47f59..7fd538a9d9986 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -483,7 +483,48 @@ function hex(x::Unsigned, pad::Int, neg::Bool) String(a) end -num2hex(n::Integer) = hex(n, sizeof(n)*2) +""" + num2hex(f) + +An hexadecimal string of the binary representation of a number. +See also the [`bits`](@ref) function, which is similar but gives +a binary string. + +```jldoctest +julia> num2hex(Int64(4)) +"0000000000000004" + +julia> num2hex(2.2) +"400199999999999a" + +``` +""" +num2hex(n::BitReal) = hex(reinterpret(Unsigned, n), sizeof(n)*2) +num2hex(n::Bool) = hex(n) + +""" + hex2num(T::Type, str) + +Interprets a hexadecimal string as the bit representation of a +number of type `T`. See also [`num2hex`](@ref). + +```jldoctest +julia> hex2num(Float64, "400199999999999a") +2.2 + +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)) const base36digits = ['0':'9';'a':'z'] const base62digits = ['0':'9';'A':'Z';'a':'z'] @@ -573,6 +614,21 @@ Convert an integer to a decimal string, optionally specifying a number of digits """ dec +""" + bits(n) + +A string giving the literal bit representation of a number. +See also the [`num2hex`](@ref) function, which is similar but +gives an hexadecimal string. + +```jldoctest +julia> bits(4) +"0000000000000000000000000000000000000000000000000000000000000100" + +julia> bits(2.2) +"0100000000000001100110011001100110011001100110011001100110011010" +``` +""" bits(x::Union{Bool,Int8,UInt8}) = bin(reinterpret(UInt8,x),8) bits(x::Union{Int16,UInt16,Float16}) = bin(reinterpret(UInt16,x),16) bits(x::Union{Char,Int32,UInt32,Float32}) = bin(reinterpret(UInt32,x),32) diff --git a/base/multinverses.jl b/base/multinverses.jl index 5b60e76e40a29..be34348a1a17e 100644 --- a/base/multinverses.jl +++ b/base/multinverses.jl @@ -11,7 +11,10 @@ unsigned(::Type{Int16}) = UInt16 unsigned(::Type{Int32}) = UInt32 unsigned(::Type{Int64}) = UInt64 unsigned(::Type{Int128}) = UInt128 -unsigned{T<:Unsigned}(::Type{T}) = T +unsigned(::Type{T}) where {T<:Unsigned} = T +unsigned(::Type{Float16}) = UInt16 +unsigned(::Type{Float32}) = UInt32 +unsigned(::Type{Float64}) = UInt64 abstract type MultiplicativeInverse{T} end diff --git a/test/floatfuncs.jl b/test/floatfuncs.jl index e246e8df5cac6..96ae477f0fdbd 100644 --- a/test/floatfuncs.jl +++ b/test/floatfuncs.jl @@ -39,7 +39,9 @@ end for elty in (Float16,Float32,Float64), _ = 1:10 x = rand(elty) @test hex2num(num2hex(x)) ≈ x + @test hex2num(elty, num2hex(x)) ≈ x end +@test_throws ArgumentError hex2num(String(rand('a':'f', rand(17:100)))) # round for elty in (Float32,Float64) diff --git a/test/intfuncs.jl b/test/intfuncs.jl index 0c6fc028a11c8..175c0fe5dbbf5 100644 --- a/test/intfuncs.jl +++ b/test/intfuncs.jl @@ -124,6 +124,14 @@ end @test hex(12) == "c" @test hex(-12, 3) == "-00c" @test num2hex(1243) == (Int == Int32 ? "000004db" : "00000000000004db") +@test num2hex(-1243) == (Int == Int32 ? "fffffb25" : "fffffffffffffb25") +@test num2hex(true) == "1" +@test num2hex(false) == "0" + +for elty in Base.BitInteger_types, _ = 1:10 + x = rand(elty) + @test hex2num(elty, num2hex(x)) == x +end @test base(2, 5, 7) == "0000101"