@@ -69,17 +69,81 @@ hash(x::UInt64, h::UInt) = hash_uint64(hash_mix_linear(x, h))
6969hash (x:: Int64 , h:: UInt ) = hash (bitcast (UInt64, x), h)
7070hash (x:: Union{Bool, Int8, UInt8, Int16, UInt16, Int32, UInt32} , h:: UInt ) = hash (Int64 (x), h)
7171
72- function hash_integer (n:: Integer , h:: UInt )
73- h ⊻= hash_uint ((n % UInt) ⊻ h)
74- n = abs (n)
75- n >>>= sizeof (UInt) << 3
76- while n != 0
77- h ⊻= hash_uint ((n % UInt) ⊻ h)
78- n >>>= sizeof (UInt) << 3
72+ hash_integer (x:: Integer , h:: UInt ) = _hash_integer (x, UInt64 (h)) % UInt
73+ function _hash_integer (
74+ x:: Integer ,
75+ seed:: UInt64 = HASH_SEED,
76+ secret:: NTuple{3, UInt64} = HASH_SECRET
77+ )
78+ seed ⊻= (x < 0 )
79+ u = abs (x)
80+
81+ # always left-pad to full byte
82+ buflen = UInt (max (cld (top_set_bit (u), 8 ), 1 ))
83+ seed = seed ⊻ (hash_mix (seed ⊻ secret[1 ], secret[2 ]) ⊻ buflen)
84+
85+ a = zero (UInt64)
86+ b = zero (UInt64)
87+
88+ if buflen ≤ 16
89+ if buflen ≥ 4
90+ a = (UInt64 (u % UInt32) << 32 ) |
91+ UInt64 ((u >>> ((buflen - 4 ) * 8 )) % UInt32)
92+
93+ delta = (buflen & 24 ) >>> (buflen >>> 3 )
94+
95+ b = (UInt64 ((u >>> (8 * delta)) % UInt32) << 32 ) |
96+ UInt64 ((u >>> (8 * (buflen - 4 - delta))) % UInt32)
97+ else # buflen > 0
98+ b0 = u % UInt8
99+ b1 = (u >>> (8 * div (buflen, 2 ))) % UInt8
100+ b2 = (u >>> (8 * (buflen - 1 ))) % UInt8
101+ a = (UInt64 (b0) << 56 ) |
102+ (UInt64 (b1) << 32 ) |
103+ UInt64 (b2)
104+ end
105+ else
106+ a = (u >>> 8 (buflen - 16 )) % UInt
107+ b = (u >>> 8 (buflen - 8 )) % UInt
108+
109+ i = buflen
110+ if i > 48
111+ see1 = seed
112+ see2 = seed
113+ while i ≥ 48
114+ l0 = u % UInt; u >>>= 64
115+ l1 = u % UInt; u >>>= 64
116+ l2 = u % UInt; u >>>= 64
117+ l3 = u % UInt; u >>>= 64
118+ l4 = u % UInt; u >>>= 64
119+ l5 = u % UInt; u >>>= 64
120+
121+ seed = hash_mix (l0 ⊻ secret[1 ], l1 ⊻ seed)
122+ see1 = hash_mix (l2 ⊻ secret[2 ], l3 ⊻ see1)
123+ see2 = hash_mix (l4 ⊻ secret[3 ], l5 ⊻ see2)
124+ i -= 48
125+ end
126+ seed = seed ⊻ see1 ⊻ see2
127+ end
128+ if i > 16
129+ l0 = u % UInt; u >>>= 64
130+ l1 = u % UInt; u >>>= 64
131+ seed = hash_mix (l0 ⊻ secret[3 ], l1 ⊻ seed ⊻ secret[2 ])
132+ if i > 32
133+ l2 = u % UInt; u >>>= 64
134+ l3 = u % UInt; u >>>= 64
135+ seed = hash_mix (l2 ⊻ secret[3 ], l3 ⊻ seed)
136+ end
137+ end
79138 end
80- return h
139+
140+ a = a ⊻ secret[2 ]
141+ b = b ⊻ seed
142+ b, a = mul_parts (a, b)
143+ return hash_mix (a ⊻ secret[1 ] ⊻ buflen, b ⊻ secret[2 ])
81144end
82145
146+
83147# # efficient value-based hashing of floats ##
84148
85149const hx_NaN = hash (reinterpret (UInt64, NaN ))
@@ -117,6 +181,7 @@ function hash(x::Float16, h::UInt)
117181end
118182
119183# # generic hashing for rational values ##
184+ _hash_shl! (x, n) = (x << n)
120185function hash (x:: Real , h:: UInt )
121186 # decompose x as num*2^pow/den
122187 num, pow, den = decompose (x)
@@ -132,6 +197,7 @@ function hash(x::Real, h::UInt)
132197 den = - den
133198 end
134199 num_z = trailing_zeros (num)
200+
135201 num >>= num_z
136202 den_z = trailing_zeros (den)
137203 den >>= den_z
@@ -156,7 +222,10 @@ function hash(x::Real, h::UInt)
156222 end
157223 # handle generic rational values
158224 h = hash_integer (pow, h)
159- h = hash_integer (num, h)
225+
226+ # trimming only whole bytes of trailing zeros simplifies greatly
227+ # some specializations for memory-backed bitintegers
228+ h = hash_integer ((pow > 0 ) ? _hash_shl! (num, pow % 8 ) : num, h)
160229 return h
161230end
162231
209278 else
210279 pos = 1
211280 i = buflen
212- while i ≥ 48
281+ if i > 48
213282 see1 = seed
214283 see2 = seed
215284 while i ≥ 48
0 commit comments