From 9a6b9d8ff8c319ea560632bb08ea3dde434aab83 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Thu, 22 Jun 2017 16:58:22 -0400 Subject: [PATCH] preserve signs for +/-/*/... between IntXX and UIntXX --- base/combinatorics.jl | 2 +- base/float.jl | 14 +++++++------- base/hashing.jl | 4 ++-- base/int.jl | 20 +++++++++++++++++--- base/nofloat_hashing.jl | 2 +- base/parse.jl | 4 ++-- base/regex.jl | 8 ++++---- 7 files changed, 34 insertions(+), 20 deletions(-) diff --git a/base/combinatorics.jl b/base/combinatorics.jl index 645a9499f1c63..84f7a53d969ef 100644 --- a/base/combinatorics.jl +++ b/base/combinatorics.jl @@ -11,7 +11,7 @@ end const _fact_table128 = Vector{UInt128}(34) _fact_table128[1] = 1 for n in 2:34 - _fact_table128[n] = _fact_table128[n-1] * n + _fact_table128[n] = _fact_table128[n-1] * UInt128(n) end function factorial_lookup(n::Integer, table, lim) diff --git a/base/float.jl b/base/float.jl index 65836552b2b31..c2ce617add789 100644 --- a/base/float.jl +++ b/base/float.jl @@ -79,7 +79,7 @@ function convert(::Type{Float64}, x::UInt128) y = ((x % UInt64) << (53-n)) & 0x000f_ffff_ffff_ffff else y = ((x >> (n-54)) % UInt64) & 0x001f_ffff_ffff_ffff # keep 1 extra bit - y = (y+1)>>1 # round, ties up (extra leading bit in case of next exponent) + y = (y+0x01)>>1 # round, ties up (extra leading bit in case of next exponent) y &= ~UInt64(trailing_zeros(x) == (n-54)) # fix last bit to round to even end d = ((n+1022) % UInt64) << 52 @@ -95,7 +95,7 @@ function convert(::Type{Float64}, x::Int128) y = ((x % UInt64) << (53-n)) & 0x000f_ffff_ffff_ffff else y = ((x >> (n-54)) % UInt64) & 0x001f_ffff_ffff_ffff # keep 1 extra bit - y = (y+1)>>1 # round, ties up (extra leading bit in case of next exponent) + y = (y+0x01)>>1 # round, ties up (extra leading bit in case of next exponent) y &= ~UInt64(trailing_zeros(x) == (n-54)) # fix last bit to round to even end d = ((n+1022) % UInt64) << 52 @@ -134,7 +134,7 @@ end function convert(::Type{Float16}, val::Float32) f = reinterpret(UInt32, val) - i = (f >> 23) & 0x1ff + 1 + i = (f >> 23) & 0x1ff + 0x01 sh = shifttable[i] f &= 0x007fffff h::UInt16 = basetable[i] + (f >> sh) @@ -145,7 +145,7 @@ function convert(::Type{Float16}, val::Float32) if nextbit != 0 # Round halfway to even or check lower bits if h&1 == 1 || (f & ((1<<(sh-1))-1)) != 0 - h += 1 + h += 0x01 end end reinterpret(Float16, h) @@ -158,7 +158,7 @@ function convert(::Type{Float32}, val::Float16) local sig::UInt32 = (ival & 0x3ff) >> 0 local ret::UInt32 - if exp == 0 + if exp == 0x00 if sig == 0 sign = sign << 31 ret = sign | exp | sig @@ -186,7 +186,7 @@ function convert(::Type{Float32}, val::Float16) end else sign = sign << 31 - exp = (exp - 15 + 127) << 23 + exp = (exp + 0x70) << 23 sig = sig << (23 - 10) ret = sign | exp | sig end @@ -550,7 +550,7 @@ isinf(x::Real) = !isnan(x) & !isfinite(x) ## hashing small, built-in numeric types ## -hx(a::UInt64, b::Float64, h::UInt) = hash_uint64((3a + reinterpret(UInt64,b)) - h) +hx(a::UInt64, b::Float64, h::UInt) = hash_uint64((0x03a + reinterpret(UInt64,b)) - h) const hx_NaN = hx(UInt64(0), NaN, UInt(0 )) hash(x::UInt64, h::UInt) = hx(x, Float64(x), h) diff --git a/base/hashing.jl b/base/hashing.jl index efc87a46568cd..fe350e576b445 100644 --- a/base/hashing.jl +++ b/base/hashing.jl @@ -7,7 +7,7 @@ hash(w::WeakRef, h::UInt) = hash(w.value, h) ## hashing general objects ## -hash(x::ANY, h::UInt) = hash_uint(3h - object_id(x)) +hash(x::ANY, h::UInt) = hash_uint(0x3h - object_id(x)) ## core data hashing functions ## @@ -27,7 +27,7 @@ function hash_64_32(n::UInt64) local a::UInt64 = n a = ~a + a << 18 a = a ⊻ a >> 31 - a = a * 21 + a = a * 0x15 a = a ⊻ a >> 11 a = a + a << 6 a = a ⊻ a >> 22 diff --git a/base/int.jl b/base/int.jl index 42b8ef82b8072..ca24390ed0fd2 100644 --- a/base/int.jl +++ b/base/int.jl @@ -14,6 +14,8 @@ const BitSigned_types = (BitSigned64_types..., Int128) const BitUnsigned_types = (BitUnsigned64_types..., UInt128) const BitInteger_types = (BitSigned_types..., BitUnsigned_types...) +const BitSigned32 = Union{Int8,Int16,Int32} +const BitUnsigned32 = Union{UInt8,UInt16,UInt32} const BitSigned64 = Union{BitSigned64_types...} const BitUnsigned64 = Union{BitUnsigned64_types...} const BitInteger64 = Union{BitInteger64_types...} @@ -438,15 +440,15 @@ promote_rule(::Type{Int8}, ::Type{Int16}) = Int16 promote_rule(::Type{UInt8}, ::Type{UInt16}) = UInt16 promote_rule(::Type{Int32}, ::Type{<:Union{Int8,Int16}}) = Int32 promote_rule(::Type{UInt32}, ::Type{<:Union{UInt8,UInt16}}) = UInt32 -promote_rule(::Type{Int64}, ::Type{<:Union{Int8,Int16,Int32}}) = Int64 -promote_rule(::Type{UInt64}, ::Type{<:Union{UInt8,UInt16,UInt32}}) = UInt64 +promote_rule(::Type{Int64}, ::Type{<:BitSigned32}) = Int64 +promote_rule(::Type{UInt64}, ::Type{<:BitUnsigned32}) = UInt64 promote_rule(::Type{Int128}, ::Type{<:BitSigned64}) = Int128 promote_rule(::Type{UInt128}, ::Type{<:BitUnsigned64}) = UInt128 for T in BitSigned_types @eval promote_rule(::Type{<:Union{UInt8,UInt16}}, ::Type{$T}) = $(sizeof(T) < sizeof(Int) ? Int : T) end -@eval promote_rule(::Type{UInt32}, ::Type{<:Union{Int8,Int16,Int32}}) = +@eval promote_rule(::Type{UInt32}, ::Type{<:BitSigned32}) = $(Core.sizeof(Int) == 8 ? Int : UInt) promote_rule(::Type{UInt32}, ::Type{Int64}) = Int64 promote_rule(::Type{UInt64}, ::Type{<:BitSigned64}) = UInt64 @@ -579,3 +581,15 @@ else rem(x::Int128, y::Int128) = checked_srem_int(x, y) rem(x::UInt128, y::UInt128) = checked_urem_int(x, y) end + +# operations where we want to preserve sign (#9292) for unsigned ⋆ signed: +for op in (:*, :+, :-, :div, :rem, :mod, ://) + @eval $op(x::UInt64, y::BitSigned64) = $op(Int64(x), y) + @eval $op(x::BitSigned64, y::UInt64) = $op(x, Int64(y)) + @eval $op(x::UInt128, y::BitSigned) = $op(Int128(x), y) + @eval $op(x::BitSigned, y::UInt128) = $op(x, Int128(y)) + if Core.sizeof(Int) == 4 + @eval $op(x::UInt32, y::BitSigned32) = $op(Int32(x), y) + @eval $op(x::BitSigned32, y::UInt32) = $op(x, Int32(y)) + end +end diff --git a/base/nofloat_hashing.jl b/base/nofloat_hashing.jl index 3ef707d1c440f..f45a07ee4ad76 100644 --- a/base/nofloat_hashing.jl +++ b/base/nofloat_hashing.jl @@ -3,7 +3,7 @@ ## hashing small, built-in numeric types ## for a system image built without floating point support -hx(a::UInt64, b::UInt64, h::UInt) = hash_uint64(3a + b - h) +hx(a::UInt64, b::UInt64, h::UInt) = hash_uint64(0x03a + b - h) hash(x::UInt64, h::UInt) = hx(x, x, h) hash(x::Int64, h::UInt) = hx(reinterpret(UInt64,abs(x)), reinterpret(UInt64,x), h) diff --git a/base/parse.jl b/base/parse.jl index 754d670f9d0b8..be3f2ff3738cf 100644 --- a/base/parse.jl +++ b/base/parse.jl @@ -78,7 +78,7 @@ function tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos:: end base = convert(T,base) - m::T = div(typemax(T)-base+1,base) + m::T = div(typemax(T)-base+0x01,base) n::T = 0 a::Int = base <= 36 ? 10 : 36 while n <= m @@ -92,7 +92,7 @@ function tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos:: n *= base n += d if i > endpos - n *= sgn + (T <: Signed) && (n *= sgn) return Nullable{T}(n) end c, i = next(s,i) diff --git a/base/regex.jl b/base/regex.jl index 75e8dcc70e821..694fcad74cecd 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -163,11 +163,11 @@ function match(re::Regex, str::Union{SubString{String}, String}, idx::Integer, a end ovec = re.ovec n = div(length(ovec),2) - 1 - mat = SubString(str, ovec[1]+1, ovec[2]) + mat = SubString(str, ovec[1]+0x01, ovec[2]) cap = Union{Void,SubString{String}}[ - ovec[2i+1] == PCRE.UNSET ? nothing : SubString(str, ovec[2i+1]+1, ovec[2i+2]) for i=1:n ] - off = Int[ ovec[2i+1]+1 for i=1:n ] - RegexMatch(mat, cap, ovec[1]+1, off, re) + ovec[2i+1] == PCRE.UNSET ? nothing : SubString(str, ovec[2i+1]+0x01, ovec[2i+2]) for i=1:n ] + off = Int[ ovec[2i+1]+0x01 for i=1:n ] + RegexMatch(mat, cap, ovec[1]+0x01, off, re) end match(r::Regex, s::AbstractString) = match(r, s, start(s))