Skip to content

Commit 84e54dc

Browse files
oscardssmithKristofferC
authored andcommitted
fix hash(::BigInt) on 32 bit systems (#50076)
* don't define hash(::BigInt) on 32 bit systems (cherry picked from commit c3ea5dc)
1 parent bddf36a commit 84e54dc

File tree

2 files changed

+9
-12
lines changed

2 files changed

+9
-12
lines changed

base/gmp.jl

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

809809
## streamlined hashing for BigInt, by avoiding allocation from shifts ##
810810

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

@@ -819,7 +819,7 @@ if Limb === UInt
819819
GC.@preserve n begin
820820
s = n.size
821821
s == 0 && return hash_integer(0, h)
822-
p = convert(Ptr{UInt}, n.d)
822+
p = convert(Ptr{UInt64}, n.d)
823823
b = unsafe_load(p)
824824
h ⊻= hash_uint(ifelse(s < 0, -b, b) h)
825825
for k = 2:abs(s)
@@ -829,14 +829,11 @@ if Limb === UInt
829829
end
830830
end
831831

832-
_divLimb(n) = UInt === UInt64 ? n >>> 6 : n >>> 5
833-
_modLimb(n) = UInt === UInt64 ? n & 63 : n & 31
834-
835832
function hash(x::BigInt, h::UInt)
836833
GC.@preserve x begin
837834
sz = x.size
838835
sz == 0 && return hash(0, h)
839-
ptr = Ptr{UInt}(x.d)
836+
ptr = Ptr{UInt64}(x.d)
840837
if sz == 1
841838
return hash(unsafe_load(ptr), h)
842839
elseif sz == -1
@@ -845,8 +842,8 @@ if Limb === UInt
845842
end
846843
pow = trailing_zeros(x)
847844
nd = Base.ndigits0z(x, 2)
848-
idx = _divLimb(pow) + 1
849-
shift = _modLimb(pow) % UInt
845+
idx = (pow >>> 6) + 1
846+
shift = (pow & 63) % UInt
850847
upshift = BITS_PER_LIMB - shift
851848
asz = abs(sz)
852849
if shift == 0

test/hashing.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ 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, Rational{BigInt}
1213
]
1314
vals = vcat(
1415
typemin(Int64),
@@ -51,8 +52,7 @@ let collides = 0
5152
collides += eq
5253
end
5354
end
54-
# each pair of types has one collision for these values
55-
@test collides <= (length(types) - 1)^2
55+
@test collides <= 516
5656
end
5757
@test hash(0.0) != hash(-0.0)
5858

0 commit comments

Comments
 (0)