Skip to content

Commit 53bcb39

Browse files
LilithHafnerLilith Hafner
andauthored
Fixup hash(::Real) broken by #49996 (#50067)
* fixup for 49996 and add test from 50065 --------- Co-authored-by: Lilith Hafner <[email protected]>
1 parent 1bb3d26 commit 53bcb39

File tree

2 files changed

+15
-9
lines changed

2 files changed

+15
-9
lines changed

base/float.jl

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -675,27 +675,28 @@ function hash(x::Real, h::UInt)
675675
den = -den
676676
end
677677
num_z = trailing_zeros(num)
678+
num >>= num_z
678679
den_z = trailing_zeros(den)
679680
den >>= den_z
680681
pow += num_z - den_z
681682

682683
# handle values representable as Int64, UInt64, Float64
683684
if den == 1
684-
left = top_set_bit(abs(num)) - den_z
685-
right = pow
685+
left = top_set_bit(abs(num)) + pow
686+
right = pow + den_z
686687
if -1074 <= right
687688
if 0 <= right
688-
left <= 63 && return hash(Int64(num) << Int(pow-num_z), h)
689-
left <= 64 && !signbit(num) && return hash(UInt64(num) << Int(pow-num_z), h)
689+
left <= 63 && return hash(Int64(num) << Int(pow), h)
690+
left <= 64 && !signbit(num) && return hash(UInt64(num) << Int(pow), h)
690691
end # typemin(Int64) handled by Float64 case
691-
left <= 1024 && left - right <= 53 && return hash(ldexp(Float64(num), pow-num_z), h)
692+
left <= 1024 && left - right <= 53 && return hash(ldexp(Float64(num), pow), h)
692693
end
693694
end
694695

695696
# handle generic rational values
696697
h = hash_integer(den, h)
697698
h = hash_integer(pow, h)
698-
h = hash_integer(num >> num_z, h)
699+
h = hash_integer(num, h)
699700
return h
700701
end
701702

test/hashing.jl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,14 @@ types = Any[
88
Bool,
99
Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Float32, Float64,
1010
Rational{Int8}, Rational{UInt8}, Rational{Int16}, Rational{UInt16},
11-
Rational{Int32}, Rational{UInt32}, Rational{Int64}, Rational{UInt64}
11+
Rational{Int32}, Rational{UInt32}, Rational{Int64}, Rational{UInt64},
12+
BigFloat, #BigInt, # TODO: BigInt hashing is broken on 32-bit systems
1213
]
14+
if Int === Int64
15+
push!(types, BigInt)
16+
else
17+
@test_broken hash(12345678901234) == hash(big(12345678901234))
18+
end
1319
vals = vcat(
1420
typemin(Int64),
1521
-Int64(maxintfloat(Float64)) .+ Int64[-4:1;],
@@ -51,8 +57,7 @@ let collides = 0
5157
collides += eq
5258
end
5359
end
54-
# each pair of types has one collision for these values
55-
@test collides <= (length(types) - 1)^2
60+
@test collides <= 452
5661
end
5762
@test hash(0.0) != hash(-0.0)
5863

0 commit comments

Comments
 (0)