diff --git a/base/gmp.jl b/base/gmp.jl index 3f809fd99d1cc..b80be35c25fcd 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -843,8 +843,8 @@ Base.deepcopy_internal(x::BigInt, stackdict::IdDict) = get!(() -> MPZ.set(x), st ## streamlined hashing for BigInt, by avoiding allocation from shifts ## -if Limb === UInt - # this condition is true most (all?) of the time, and in this case we can define +if Limb === UInt64 === UInt + # On 64 bit systems we can define # an optimized version for BigInt of hash_integer (used e.g. for Rational{BigInt}), # and of hash @@ -854,7 +854,7 @@ if Limb === UInt GC.@preserve n begin s = n.size s == 0 && return hash_integer(0, h) - p = convert(Ptr{UInt}, n.d) + p = convert(Ptr{UInt64}, n.d) b = unsafe_load(p) h ⊻= hash_uint(ifelse(s < 0, -b, b) ⊻ h) for k = 2:abs(s) @@ -864,14 +864,11 @@ if Limb === UInt end end - _divLimb(n) = UInt === UInt64 ? n >>> 6 : n >>> 5 - _modLimb(n) = UInt === UInt64 ? n & 63 : n & 31 - function hash(x::BigInt, h::UInt) GC.@preserve x begin sz = x.size sz == 0 && return hash(0, h) - ptr = Ptr{UInt}(x.d) + ptr = Ptr{UInt64}(x.d) if sz == 1 return hash(unsafe_load(ptr), h) elseif sz == -1 @@ -880,8 +877,8 @@ if Limb === UInt end pow = trailing_zeros(x) nd = Base.ndigits0z(x, 2) - idx = _divLimb(pow) + 1 - shift = _modLimb(pow) % UInt + idx = (pow >>> 6) + 1 + shift = (pow & 63) % UInt upshift = BITS_PER_LIMB - shift asz = abs(sz) if shift == 0 diff --git a/test/hashing.jl b/test/hashing.jl index de64cd80cb49d..1c7c37d00f93b 100644 --- a/test/hashing.jl +++ b/test/hashing.jl @@ -9,13 +9,8 @@ types = Any[ 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}, - BigFloat, #BigInt, # TODO: BigInt hashing is broken on 32-bit systems + BigFloat, BigInt, Rational{BigInt} ] -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;], @@ -57,7 +52,7 @@ let collides = 0 collides += eq end end - @test collides <= 452 + @test collides <= 516 end @test hash(0.0) != hash(-0.0)