Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix hashing regression. #50655

Merged
merged 8 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions base/float.jl
Original file line number Diff line number Diff line change
Expand Up @@ -688,22 +688,19 @@ function hash(x::Real, h::UInt)
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)) + pow
right = pow + den_z
if -1074 <= right
if 0 <= right
if -1074 <= pow
oscardssmith marked this conversation as resolved.
Show resolved Hide resolved
if pow >= 0
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), h)
left <= 1024 && left - pow <= 53 && return hash(ldexp(Float64(num), pow), h)
end
else
h = hash_integer(den, h)
end

# handle generic rational values
h = hash_integer(pow, h)
h = hash_integer(num, h)
Expand Down
3 changes: 2 additions & 1 deletion base/rational.jl
Original file line number Diff line number Diff line change
Expand Up @@ -549,9 +549,10 @@ function hash(x::Rational{<:BitInteger64}, h::UInt)
num, den = Base.numerator(x), Base.denominator(x)
den == 1 && return hash(num, h)
den == 0 && return hash(ifelse(num > 0, Inf, -Inf), h)
if isodd(den)
if isodd(den) # since den != 1, this rational can't be a Float64
pow = trailing_zeros(num)
num >>= pow
h = hash_integer(den, h)
else
pow = trailing_zeros(den)
den >>= pow
Expand Down
15 changes: 15 additions & 0 deletions test/hashing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -310,3 +310,18 @@ struct AUnionParam{T<:Union{Nothing,Float32,Float64}} end
@test Type{AUnionParam{<:Union{Nothing,Float32,Float64}}} === Type{AUnionParam}
@test Type{AUnionParam.body}.hash == 0
@test Type{Base.Broadcast.Broadcasted}.hash != 0


@testset "issue 50628" begin
# test hashing of rationals that equal floats are equal to the float hash
@test hash(5//2) == hash(big(5)//2) == hash(2.5)
# test hashing of rational that are integers hash to the integer
@test hash(5^25) == hash(big(5)^25) == hash(5^25//1) == hash(big(5)^25//1)
# test integer/rational that don't fit in Float64 don't hash as Float64
@test hash(5^25) != hash(5.0^25)
@test hash((5//2)^25) == hash(big(5//2)^25)
# test integer/rational that don't fit in Float64 don't hash as Float64
@test hash((5//2)^25) != hash(2.5^25)
# test hashing of rational with odd denominator
@test hash(5//3) == hash(big(5)//3)
end