diff --git a/base/char.jl b/base/char.jl index 7a094dec85ce2..05cb6124e1c70 100644 --- a/base/char.jl +++ b/base/char.jl @@ -3,6 +3,10 @@ char(x::FloatingPoint) = char(iround(x)) integer(x::Char) = int(x) +convert(::Type{Char}, x::Float16) = char(convert(Uint32, x)) +convert(::Type{Char}, x::Float32) = char(convert(Uint32, x)) +convert(::Type{Char}, x::Float64) = char(convert(Uint32, x)) + ## char promotions ## promote_rule(::Type{Char}, ::Type{Int8}) = Int32 diff --git a/base/float.jl b/base/float.jl index a43243daf9f08..a4cba309e8c41 100644 --- a/base/float.jl +++ b/base/float.jl @@ -1,16 +1,16 @@ ## conversions to floating-point ## -convert(::Type{Float32}, x::Int128) = float32(uint128(abs(x)))*(1-2(x<0)) -convert(::Type{Float32}, x::Uint128) = float32(uint64(x)) + ldexp(float32(uint64(x>>>64)),64) +convert(::Type{Float32}, x::Int128) = float32(reinterpret(Uint128,abs(x)))*(1-2(x<0)) +convert(::Type{Float32}, x::Uint128) = float32(uint64(x&0xffffffffffffffff)) + ldexp(float32(uint64(x>>>64)),64) promote_rule(::Type{Float32}, ::Type{Int128} ) = Float32 promote_rule(::Type{Float32}, ::Type{Uint128}) = Float32 -convert(::Type{Float64}, x::Int128) = float64(uint128(abs(x)))*(1-2(x<0)) -convert(::Type{Float64}, x::Uint128) = float64(uint64(x)) + ldexp(float64(uint64(x>>>64)),64) +convert(::Type{Float64}, x::Int128) = float64(reinterpret(Uint128,abs(x)))*(1-2(x<0)) +convert(::Type{Float64}, x::Uint128) = float64(uint64(x&0xffffffffffffffff)) + ldexp(float64(uint64(x>>>64)),64) promote_rule(::Type{Float64}, ::Type{Int128} ) = Float64 promote_rule(::Type{Float64}, ::Type{Uint128}) = Float64 -convert(::Type{Float16}, x::Union(Signed,Unsigned)) = convert(Float16, convert(Float32,x)) +convert(::Type{Float16}, x::Integer) = convert(Float16, convert(Float32,x)) for t in (Bool,Char,Int8,Int16,Int32,Int64,Uint8,Uint16,Uint32,Uint64) @eval promote_rule(::Type{Float16}, ::Type{$t}) = Float32 end diff --git a/base/int.jl b/base/int.jl index bed14be303d9e..a4167ad1a9632 100644 --- a/base/int.jl +++ b/base/int.jl @@ -1,13 +1,3 @@ -## type aliases ## - -if Int === Int32 -typealias SmallSigned Union(Int8,Int16) -typealias SmallUnsigned Union(Uint8,Uint16) -else -typealias SmallSigned Union(Int8,Int16,Int32) -typealias SmallUnsigned Union(Uint8,Uint16,Uint32) -end - ## integer arithmetic ## const IntTypes = (Int8, Uint8, Int16, Uint16, Int32, Uint32, @@ -34,11 +24,10 @@ iseven(n::Integer) = !isodd(n) signbit(x::Integer) = x < 0 signbit(x::Unsigned) = false -flipsign(x::Int, y::Int) = box(Int,flipsign_int(unbox(Int,x),unbox(Int,y))) -flipsign(x::Int64, y::Int64) = box(Int64,flipsign_int(unbox(Int64,x),unbox(Int64,y))) -flipsign(x::Int128, y::Int128) = box(Int128,flipsign_int(unbox(Int128,x),unbox(Int128,y))) +for T in (Int8,Int16,Int32,Int64,Int128) + @eval flipsign(x::$T, y::$T) = box($T,flipsign_int(unbox($T,x),unbox($T,y))) +end -flipsign{T<:Signed}(x::T,y::T) = flipsign(int(x),int(y)) flipsign(x::Signed, y::Signed) = flipsign(promote(x,y)...) flipsign(x::Signed, y::Float32) = flipsign(x, reinterpret(Int32,y)) flipsign(x::Signed, y::Float64) = flipsign(x, reinterpret(Int64,y)) @@ -100,9 +89,13 @@ for T in IntTypes ($)(x::$T, y::$T) = box($T,xor_int(unbox($T,x),unbox($T,y))) <<(x::$T, y::Int32) = box($T, shl_int(unbox($T,x),unbox(Int32,y))) - >>(x::$T, y::Int32) = box($T,ashr_int(unbox($T,x),unbox(Int32,y))) >>>(x::$T, y::Int32) = box($T,lshr_int(unbox($T,x),unbox(Int32,y))) end + if issubtype(T,Unsigned) + @eval >>(x::$T, y::Int32) = box($T,lshr_int(unbox($T,x),unbox(Int32,y))) + else + @eval >>(x::$T, y::Int32) = box($T,ashr_int(unbox($T,x),unbox(Int32,y))) + end end bswap(x::Int8) = x @@ -129,29 +122,15 @@ trailing_ones(x::Integer) = trailing_zeros(~x) ## integer comparisons ## -<(x::Int8, y::Int8) = slt_int(unbox(Int8,x),unbox(Int8,y)) -<(x::Int16, y::Int16) = slt_int(unbox(Int16,x),unbox(Int16,y)) -<(x::Int32, y::Int32) = slt_int(unbox(Int32,x),unbox(Int32,y)) -<(x::Int64, y::Int64) = slt_int(unbox(Int64,x),unbox(Int64,y)) -<(x::Int128, y::Int128) = slt_int(unbox(Int128,x),unbox(Int128,y)) - -<(x::Uint8, y::Uint8) = ult_int(unbox(Uint8,x),unbox(Uint8,y)) -<(x::Uint16, y::Uint16) = ult_int(unbox(Uint16,x),unbox(Uint16,y)) -<(x::Uint32, y::Uint32) = ult_int(unbox(Uint32,x),unbox(Uint32,y)) -<(x::Uint64, y::Uint64) = ult_int(unbox(Uint64,x),unbox(Uint64,y)) -<(x::Uint128, y::Uint128) = ult_int(unbox(Uint128,x),unbox(Uint128,y)) - -<=(x::Int8, y::Int8) = sle_int(unbox(Int8,x),unbox(Int8,y)) -<=(x::Int16, y::Int16) = sle_int(unbox(Int16,x),unbox(Int16,y)) -<=(x::Int32, y::Int32) = sle_int(unbox(Int32,x),unbox(Int32,y)) -<=(x::Int64, y::Int64) = sle_int(unbox(Int64,x),unbox(Int64,y)) -<=(x::Int128, y::Int128) = sle_int(unbox(Int128,x),unbox(Int128,y)) - -<=(x::Uint8, y::Uint8) = ule_int(unbox(Uint8,x),unbox(Uint8,y)) -<=(x::Uint16, y::Uint16) = ule_int(unbox(Uint16,x),unbox(Uint16,y)) -<=(x::Uint32, y::Uint32) = ule_int(unbox(Uint32,x),unbox(Uint32,y)) -<=(x::Uint64, y::Uint64) = ule_int(unbox(Uint64,x),unbox(Uint64,y)) -<=(x::Uint128, y::Uint128) = ule_int(unbox(Uint128,x),unbox(Uint128,y)) +for T in IntTypes + if issubtype(T,Signed) + @eval <( x::$T, y::$T) = slt_int(unbox($T,x),unbox($T,y)) + @eval <=(x::$T, y::$T) = sle_int(unbox($T,x),unbox($T,y)) + else + @eval <( x::$T, y::$T) = ult_int(unbox($T,x),unbox($T,y)) + @eval <=(x::$T, y::$T) = ule_int(unbox($T,x),unbox($T,y)) + end +end ==(x::Signed, y::Unsigned) = (x >= 0) & (unsigned(x) == y) ==(x::Unsigned, y::Signed ) = (y >= 0) & (x == unsigned(y)) @@ -162,11 +141,8 @@ trailing_ones(x::Integer) = trailing_zeros(~x) ## integer conversions ## -const _inttypes = (Bool, Int8, Uint8, Int16, Uint16, Int32, Uint32, Char, - Int64, Uint64, Int128, Uint128) - -for to in _inttypes, from in _inttypes - if !(to === from) && !(to === Bool) +for to in tuple(IntTypes...,Char), from in tuple(IntTypes...,Char,Bool) + if !(to === from) if to.size < from.size if issubtype(to, Signed) @eval convert(::Type{$to}, x::($from)) = box($to,checked_trunc_sint($to,unbox($from,x))) @@ -218,21 +194,18 @@ function convert(::Type{Uint128}, x::FloatingPoint) end convert(::Type{Uint128}, x::Float32) = convert(Uint128, float64(x)) -convert(::Type{Char}, x::Float32) = char(convert(Int, x)) -convert(::Type{Char}, x::Float64) = char(convert(Int, x)) - -convert(::Type{Signed}, x::Uint8 ) = convert(Int,x) -convert(::Type{Signed}, x::Uint16 ) = convert(Int,x) -convert(::Type{Signed}, x::Uint32 ) = convert(Int,x) +convert(::Type{Signed}, x::Uint8 ) = convert(Int8,x) +convert(::Type{Signed}, x::Uint16 ) = convert(Int16,x) +convert(::Type{Signed}, x::Uint32 ) = convert(Int32,x) convert(::Type{Signed}, x::Uint64 ) = convert(Int64,x) convert(::Type{Signed}, x::Uint128) = convert(Int128,x) convert(::Type{Signed}, x::Float32) = convert(Int,x) convert(::Type{Signed}, x::Float64) = convert(Int,x) convert(::Type{Signed}, x::Char) = convert(Int,x) -convert(::Type{Unsigned}, x::Int8 ) = convert(Uint,x) -convert(::Type{Unsigned}, x::Int16 ) = convert(Uint,x) -convert(::Type{Unsigned}, x::Int32 ) = convert(Uint,x) +convert(::Type{Unsigned}, x::Int8 ) = convert(Uint8,x) +convert(::Type{Unsigned}, x::Int16 ) = convert(Uint16,x) +convert(::Type{Unsigned}, x::Int32 ) = convert(Uint32,x) convert(::Type{Unsigned}, x::Int64 ) = convert(Uint64,x) convert(::Type{Unsigned}, x::Int128 ) = convert(Uint128,x) convert(::Type{Unsigned}, x::Float32) = convert(Uint,x) @@ -372,12 +345,12 @@ typemax(::Type{Uint64}) = 0xffffffffffffffff typemax(::Type{Int128} ) = $(int128((uint128(-1))>>int32(1))) end -widen(::Type{Int8}) = Int -widen(::Type{Int16}) = Int +widen(::Type{Int8}) = Int16 +widen(::Type{Int16}) = Int32 widen(::Type{Int32}) = Int64 widen(::Type{Int64}) = Int128 -widen(::Type{Uint8}) = Uint -widen(::Type{Uint16}) = Uint +widen(::Type{Uint8}) = Uint16 +widen(::Type{Uint16}) = Uint32 widen(::Type{Uint32}) = Uint64 widen(::Type{Uint64}) = Uint128 @@ -506,10 +479,9 @@ end for T in (Int8,Uint8) @eval function checked_mul(x::$T, y::$T) - xy = x*y - xy8 = convert($T,xy) - xy == xy8 || throw(OverflowError()) - return xy8 + xy = widemul(x,y) + (typemin($T) <= xy <= typemax($T)) || throw(OverflowError()) + return itrunc($T,xy) end end @@ -517,9 +489,8 @@ if WORD_SIZE == 32 for T in (Int64,Uint64) @eval function checked_mul(x::$T, y::$T) xy = int128(x)*int128(y) - xy64 = convert($T,xy) - xy == xy64 || throw(OverflowError()) - return xy64 + (typemin($T) <= xy <= typemax($T)) || throw(OverflowError()) + return itrunc($T,xy) end end else diff --git a/base/random.jl b/base/random.jl index 789015dfe4e23..68f69fb834037 100644 --- a/base/random.jl +++ b/base/random.jl @@ -104,17 +104,17 @@ rand(r::MersenneTwister) = dsfmt_genrand_close_open(r.state) dsfmt_randui32() = dsfmt_gv_genrand_uint32() dsfmt_randui64() = uint64(dsfmt_randui32()) | (uint64(dsfmt_randui32())<<32) -rand(::Type{Uint8}) = uint8(rand(Uint32)) -rand(::Type{Uint16}) = uint16(rand(Uint32)) +rand(::Type{Uint8}) = itrunc(Uint8,rand(Uint32)) +rand(::Type{Uint16}) = itrunc(Uint16,rand(Uint32)) rand(::Type{Uint32}) = dsfmt_randui32() rand(::Type{Uint64}) = dsfmt_randui64() rand(::Type{Uint128}) = uint128(rand(Uint64))<<64 | rand(Uint64) -rand(::Type{Int8}) = int8(rand(Uint8)) -rand(::Type{Int16}) = int16(rand(Uint16)) -rand(::Type{Int32}) = int32(rand(Uint32)) -rand(::Type{Int64}) = int64(rand(Uint64)) -rand(::Type{Int128}) = int128(rand(Uint128)) +rand(::Type{Int8}) = itrunc(Int8,rand(Uint32)) +rand(::Type{Int16}) = itrunc(Int16,rand(Uint32)) +rand(::Type{Int32}) = reinterpret(Int32,rand(Uint32)) +rand(::Type{Int64}) = reinterpret(Int64,rand(Uint64)) +rand(::Type{Int128}) = reinterpret(Int128,rand(Uint128)) # Arrays of random numbers diff --git a/base/reducedim.jl b/base/reducedim.jl index 23b0950298174..23d65ab898c47 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -101,6 +101,14 @@ reducedim_init(f, op::OrFun, A::AbstractArray, region) = reducedim_initarray(A, # specialize to make initialization more efficient for common cases +if Int === Int32 +typealias SmallSigned Union(Int8,Int16) +typealias SmallUnsigned Union(Uint8,Uint16) +else +typealias SmallSigned Union(Int8,Int16,Int32) +typealias SmallUnsigned Union(Uint8,Uint16,Uint32) +end + typealias CommonReduceResult Union(Uint64,Uint128,Int64,Int128,Float32,Float64) for (IT, RT) in ((CommonReduceResult, :(eltype(A))), (SmallSigned, :Int), (SmallUnsigned, :Uint)) diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst index bfc2ca46c3e65..d4f615077c5c1 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -3090,9 +3090,9 @@ Mathematical Functions Returns the nearest integral value of the same type as ``x`` not greater in magnitude than ``x``. ``digits`` and ``base`` work as above. -.. function:: iround(x) -> Integer +.. function:: iround([T,]x) -> Integer - Returns the nearest integer to ``x``. + Returns the nearest integer to ``x``, converted to an integer type, optionally passed as the first argument. .. function:: iceil(x) -> Integer @@ -3102,9 +3102,9 @@ Mathematical Functions Returns the nearest integer not greater than ``x``. -.. function:: itrunc(x) -> Integer +.. function:: itrunc([T,]x) -> Integer - Returns the nearest integer not greater in magnitude than ``x``. + Returns the nearest integer not greater in magnitude than ``x``, converted to an integer type, optionally passed as the first argument. .. function:: signif(x, digits, [base]) diff --git a/test/numbers.jl b/test/numbers.jl index 6e8b9408f27fc..0c6473cd3a747 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -1459,7 +1459,7 @@ end @test -0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 == -(0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001) -@test isa(-0x00,Uint) +@test isa(-0x00,Uint8) @test isa(-0x0000000000000000,Uint64) @test isa(-0x00000000000000000,Uint128) @test isa(-0x00000000000000000000000000000000,Uint128) @@ -1901,9 +1901,9 @@ end for T = (Uint8,Int8,Uint16,Int16,Uint32,Int32,Uint64,Int64,Uint128,Int128) for n = 1:2:1000 - @test convert(T,n*(n^typemax(T))) == one(T) + @test n*(n^typemax(T)) & typemax(T) == 1 n = rand(T) | one(T) - @test convert(T,n*(n^typemax(T))) == one(T) + @test n*(n^typemax(T)) == 1 end end @@ -1931,7 +1931,7 @@ end # widen @test widen(1.5f0) === 1.5 @test widen(int32(42)) === int64(42) -@test widen(Int8) === Int +@test widen(Int8) === Int16 @test widen(Float32) === Float64 ## Note: this should change to e.g. Float128 at some point @test widen(Float64) === BigFloat