Skip to content

Commit c3ea5dc

Browse files
authored
fix hash(::BigInt) on 32 bit systems (#50076)
* don't define hash(::BigInt) on 32 bit systems
1 parent 4d2f35e commit c3ea5dc

File tree

2 files changed

+8
-16
lines changed

2 files changed

+8
-16
lines changed

base/gmp.jl

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -843,8 +843,8 @@ Base.deepcopy_internal(x::BigInt, stackdict::IdDict) = get!(() -> MPZ.set(x), st
843843

844844
## streamlined hashing for BigInt, by avoiding allocation from shifts ##
845845

846-
if Limb === UInt
847-
# this condition is true most (all?) of the time, and in this case we can define
846+
if Limb === UInt64 === UInt
847+
# On 64 bit systems we can define
848848
# an optimized version for BigInt of hash_integer (used e.g. for Rational{BigInt}),
849849
# and of hash
850850

@@ -854,7 +854,7 @@ if Limb === UInt
854854
GC.@preserve n begin
855855
s = n.size
856856
s == 0 && return hash_integer(0, h)
857-
p = convert(Ptr{UInt}, n.d)
857+
p = convert(Ptr{UInt64}, n.d)
858858
b = unsafe_load(p)
859859
h ⊻= hash_uint(ifelse(s < 0, -b, b) h)
860860
for k = 2:abs(s)
@@ -864,14 +864,11 @@ if Limb === UInt
864864
end
865865
end
866866

867-
_divLimb(n) = UInt === UInt64 ? n >>> 6 : n >>> 5
868-
_modLimb(n) = UInt === UInt64 ? n & 63 : n & 31
869-
870867
function hash(x::BigInt, h::UInt)
871868
GC.@preserve x begin
872869
sz = x.size
873870
sz == 0 && return hash(0, h)
874-
ptr = Ptr{UInt}(x.d)
871+
ptr = Ptr{UInt64}(x.d)
875872
if sz == 1
876873
return hash(unsafe_load(ptr), h)
877874
elseif sz == -1
@@ -880,8 +877,8 @@ if Limb === UInt
880877
end
881878
pow = trailing_zeros(x)
882879
nd = Base.ndigits0z(x, 2)
883-
idx = _divLimb(pow) + 1
884-
shift = _modLimb(pow) % UInt
880+
idx = (pow >>> 6) + 1
881+
shift = (pow & 63) % UInt
885882
upshift = BITS_PER_LIMB - shift
886883
asz = abs(sz)
887884
if shift == 0

test/hashing.jl

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,8 @@ types = Any[
99
Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Float32, Float64,
1010
Rational{Int8}, Rational{UInt8}, Rational{Int16}, Rational{UInt16},
1111
Rational{Int32}, Rational{UInt32}, Rational{Int64}, Rational{UInt64},
12-
BigFloat, #BigInt, # TODO: BigInt hashing is broken on 32-bit systems
12+
BigFloat, BigInt, Rational{BigInt}
1313
]
14-
if Int === Int64
15-
push!(types, BigInt)
16-
else
17-
@test_broken hash(12345678901234) == hash(big(12345678901234))
18-
end
1914
vals = vcat(
2015
typemin(Int64),
2116
-Int64(maxintfloat(Float64)) .+ Int64[-4:1;],
@@ -57,7 +52,7 @@ let collides = 0
5752
collides += eq
5853
end
5954
end
60-
@test collides <= 452
55+
@test collides <= 516
6156
end
6257
@test hash(0.0) != hash(-0.0)
6358

0 commit comments

Comments
 (0)