@@ -30,8 +30,13 @@ julia> hash(10, a) # only use the output of another hash function as the second
3030
3131See also: [`objectid`](@ref), [`Dict`](@ref), [`Set`](@ref).
3232"""
33- hash (data) = hash (data, HASH_SEED)
34- hash (@nospecialize (data), h:: UInt64 ) = hash (objectid (data), h)
33+ hash (data:: Any ) = hash (data, HASH_SEED)
34+ hash (w:: WeakRef , h:: UInt ) = hash (w. value, h)
35+
36+ # Types can't be deleted, so marking as total allows the compiler to look up the hash
37+ hash (T:: Type , h:: UInt ) =
38+ hash ((Base. @assume_effects :total ccall (:jl_type_hash , UInt, (Any,), T)), h)
39+ hash (@nospecialize (data), h:: UInt ) = hash (objectid (data), h)
3540
3641function mul_parts (a:: UInt64 , b:: UInt64 )
3742 p = widemul (a, b)
4045hash_mix (a:: UInt64 , b:: UInt64 ) = ⊻ (mul_parts (a, b)... )
4146
4247
48+ function hash_64_64 (data:: UInt64 , seed:: UInt64 , secret:: NTuple{3, UInt64} )
49+ return data ⊻ hash_mix (data ⊻ hash_mix (seed, secret[1 ]), secret[2 ])
50+ end
51+
52+ hash_64_32 (data:: UInt64 , seed:: UInt64 , secret:: NTuple{3, UInt64} ) =
53+ hash_64_64 (data, seed, secret) % UInt32
54+ hash_32_32 (data:: UInt32 , seed:: UInt64 , secret:: NTuple{3, UInt64} ) =
55+ hash_64_32 (UInt64 (data), seed, secret)
56+
57+ if UInt === UInt64
58+ const hash_uint64 = hash_64_64
59+ const hash_uint = hash_64_64
60+ else
61+ const hash_uint64 = hash_64_32
62+ const hash_uint = hash_32_32
63+ end
64+
65+ hash (x:: UInt64 , h:: UInt ) = hash_uint64 (promote (x, h)... , HASH_SECRET)
66+ hash (x:: Int64 , h:: UInt ) = hash (bitcast (UInt64, x), h)
67+ hash (x:: Union{Bool, Int8, UInt8, Int16, UInt16, Int32, UInt32} , h:: UInt ) = hash (Int64 (x), h)
68+
69+ function hash_integer (n:: Integer , h:: UInt )
70+ h ⊻= hash ((n % UInt) ⊻ h)
71+ n = abs (n)
72+ n >>>= sizeof (UInt) << 3
73+ while n != 0
74+ h ⊻= hash ((n % UInt) ⊻ h)
75+ n >>>= sizeof (UInt) << 3
76+ end
77+ return h
78+ end
79+
80+ # # symbol & expression hashing ##
81+ if UInt === UInt64
82+ hash (x:: Expr , h:: UInt ) = hash (x. args, hash (x. head, h + 0x83c7900696d26dc6 ))
83+ hash (x:: QuoteNode , h:: UInt ) = hash (x. value, h + 0x2c97bf8b3de87020 )
84+ else
85+ hash (x:: Expr , h:: UInt ) = hash (x. args, hash (x. head, h + 0x96d26dc6 ))
86+ hash (x:: QuoteNode , h:: UInt ) = hash (x. value, h + 0x469d72af )
87+ end
88+
89+ hash (x:: Symbol ) = objectid (x)
90+
91+
4392load_le (:: Type{T} , ptr:: Ptr{UInt8} , i) where {T <: Union{UInt32, UInt64} } =
4493 unsafe_load (convert (Ptr{T}, ptr + i - 1 ))
4594
@@ -49,7 +98,7 @@ function read_small(ptr::Ptr{UInt8}, n::Int)
4998 UInt64 (unsafe_load (ptr, n))
5099end
51100
52- function hash (
101+ function hash_bytes (
53102 ptr:: Ptr{UInt8} ,
54103 n:: Int ,
55104 seed:: UInt64 ,
@@ -119,54 +168,5 @@ function hash(
119168 return hash_mix (a ⊻ secret[1 ] ⊻ buflen, b ⊻ secret[2 ])
120169end
121170
122-
123- function hash_64_64 (data:: UInt64 , seed:: UInt64 , secret:: NTuple{3, UInt64} )
124- return data ⊻ hash_mix (data ⊻ hash_mix (seed, secret[1 ]), secret[2 ])
125- end
126-
127- hash_64_32 (data:: UInt64 , seed:: UInt64 , secret:: NTuple{3, UInt64} ) =
128- hash_64_64 (data, seed, secret) % UInt32
129- hash_32_32 (data:: UInt32 , seed:: UInt64 , secret:: NTuple{3, UInt64} ) =
130- hash_64_32 (UInt64 (data), seed, secret)
131-
132- if UInt === UInt64
133- const hash_uint64 = hash_64_64
134- const hash_uint = hash_64_64
135- else
136- const hash_uint64 = hash_64_32
137- const hash_uint = hash_32_32
138- end
139-
140- hash (x:: UInt64 , h:: UInt ) = hash_uint64 (x, h, HASH_SECRET)
141- hash (x:: Int64 , h:: UInt ) = hash (bitcast (UInt64, x), h)
142- hash (x:: Union{Bool, Int8, UInt8, Int16, UInt16, Int32, UInt32} , h:: UInt ) = hash (Int64 (x), h)
143-
144- function hash_integer (n:: Integer , h:: UInt )
145- h ⊻= hash ((n % UInt) ⊻ h)
146- n = abs (n)
147- n >>>= sizeof (UInt) << 3
148- while n != 0
149- h ⊻= hash ((n % UInt) ⊻ h)
150- n >>>= sizeof (UInt) << 3
151- end
152- return h
153- end
154-
155-
156- if UInt === UInt64
157- hash (x:: Expr , h:: UInt ) = hash (x. args, hash (x. head, h + 0x83c7900696d26dc6 ))
158- hash (x:: QuoteNode , h:: UInt ) = hash (x. value, h + 0x2c97bf8b3de87020 )
159- else
160- hash (x:: Expr , h:: UInt ) = hash (x. args, hash (x. head, h + 0x96d26dc6 ))
161- hash (x:: QuoteNode , h:: UInt ) = hash (x. value, h + 0x469d72af )
162- end
163-
164- # hash(data::String, h::UInt64) = hash(length(data), h)
165- hash (data:: String , h:: UInt64 ) = @assume_effects :total GC. @preserve data hash (pointer (data), sizeof (data), h, HASH_SECRET)
166-
167- hash (w:: WeakRef , h:: UInt64 ) = hash (w. value, h)
168- function hash (T:: Type , h:: UInt64 )
169- return hash ((Base. @assume_effects :total ccall (:jl_type_hash , UInt, (Any,), T)), h)
170- end
171-
172- hash (x:: Symbol ) = objectid (x)
171+ hash (data:: String , h:: UInt ) =
172+ @assume_effects :total GC. @preserve data hash_bytes (pointer (data), sizeof (data), UInt64 (h), HASH_SECRET)
0 commit comments