diff --git a/base/float.jl b/base/float.jl index 0f05027b522a2..37f91c1f511bb 100644 --- a/base/float.jl +++ b/base/float.jl @@ -675,27 +675,28 @@ function hash(x::Real, h::UInt) den = -den end num_z = trailing_zeros(num) + num >>= num_z den_z = trailing_zeros(den) den >>= den_z pow += num_z - den_z # handle values representable as Int64, UInt64, Float64 if den == 1 - left = top_set_bit(abs(num)) - den_z - right = pow + left = top_set_bit(abs(num)) + pow + right = pow + den_z if -1074 <= right if 0 <= right - left <= 63 && return hash(Int64(num) << Int(pow-num_z), h) - left <= 64 && !signbit(num) && return hash(UInt64(num) << Int(pow-num_z), h) + left <= 63 && return hash(Int64(num) << Int(pow), h) + left <= 64 && !signbit(num) && return hash(UInt64(num) << Int(pow), h) end # typemin(Int64) handled by Float64 case - left <= 1024 && left - right <= 53 && return hash(ldexp(Float64(num), pow-num_z), h) + left <= 1024 && left - right <= 53 && return hash(ldexp(Float64(num), pow), h) end end # handle generic rational values h = hash_integer(den, h) h = hash_integer(pow, h) - h = hash_integer(num >> num_z, h) + h = hash_integer(num, h) return h end diff --git a/test/hashing.jl b/test/hashing.jl index 5230442354d99..de64cd80cb49d 100644 --- a/test/hashing.jl +++ b/test/hashing.jl @@ -8,8 +8,14 @@ types = Any[ Bool, Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Float32, Float64, Rational{Int8}, Rational{UInt8}, Rational{Int16}, Rational{UInt16}, - Rational{Int32}, Rational{UInt32}, Rational{Int64}, Rational{UInt64} + Rational{Int32}, Rational{UInt32}, Rational{Int64}, Rational{UInt64}, + BigFloat, #BigInt, # TODO: BigInt hashing is broken on 32-bit systems ] +if Int === Int64 + push!(types, BigInt) +else + @test_broken hash(12345678901234) == hash(big(12345678901234)) +end vals = vcat( typemin(Int64), -Int64(maxintfloat(Float64)) .+ Int64[-4:1;], @@ -51,8 +57,7 @@ let collides = 0 collides += eq end end - # each pair of types has one collision for these values - @test collides <= (length(types) - 1)^2 + @test collides <= 452 end @test hash(0.0) != hash(-0.0)