github.com/sohaha/zlsgo@v1.7.13-0.20240501141223-10dd1a906f76/zarray/hash.go (about) 1 //go:build go1.18 2 // +build go1.18 3 4 package zarray 5 6 import ( 7 "encoding/binary" 8 "math/bits" 9 "reflect" 10 "unsafe" 11 ) 12 13 const ( 14 // hash input allowed sizes 15 byteSize = 1 << iota 16 wordSize 17 dwordSize 18 qwordSize 19 owordSize 20 ) 21 22 const ( 23 prime1 uint64 = 11400714785074694791 24 prime2 uint64 = 14029467366897019727 25 prime3 uint64 = 1609587929392839161 26 prime4 uint64 = 9650029242287828579 27 prime5 uint64 = 2870177450012600261 28 ) 29 30 var prime1v = prime1 31 32 func u64(b []byte) uint64 { return binary.LittleEndian.Uint64(b) } 33 func u32(b []byte) uint32 { return binary.LittleEndian.Uint32(b) } 34 35 func round(acc, input uint64) uint64 { 36 acc += input * prime2 37 acc = rol31(acc) 38 acc *= prime1 39 return acc 40 } 41 42 func mergeRound(acc, val uint64) uint64 { 43 val = round(0, val) 44 acc ^= val 45 acc = acc*prime1 + prime4 46 return acc 47 } 48 49 func rol1(x uint64) uint64 { return bits.RotateLeft64(x, 1) } 50 func rol7(x uint64) uint64 { return bits.RotateLeft64(x, 7) } 51 func rol11(x uint64) uint64 { return bits.RotateLeft64(x, 11) } 52 func rol12(x uint64) uint64 { return bits.RotateLeft64(x, 12) } 53 func rol18(x uint64) uint64 { return bits.RotateLeft64(x, 18) } 54 func rol23(x uint64) uint64 { return bits.RotateLeft64(x, 23) } 55 func rol27(x uint64) uint64 { return bits.RotateLeft64(x, 27) } 56 func rol31(x uint64) uint64 { return bits.RotateLeft64(x, 31) } 57 58 var ( 59 byteHasher = func(key uint8) uintptr { 60 h := prime5 + 1 61 h ^= uint64(key) * prime5 62 h = bits.RotateLeft64(h, 11) * prime1 63 h ^= h >> 33 64 h *= prime2 65 h ^= h >> 29 66 h *= prime3 67 h ^= h >> 32 68 return uintptr(h) 69 } 70 71 wordHasher = func(key uint16) uintptr { 72 h := prime5 + 2 73 h ^= (uint64(key) & 0xff) * prime5 74 h = bits.RotateLeft64(h, 11) * prime1 75 h ^= ((uint64(key) >> 8) & 0xff) * prime5 76 h = bits.RotateLeft64(h, 11) * prime1 77 h ^= h >> 33 78 h *= prime2 79 h ^= h >> 29 80 h *= prime3 81 h ^= h >> 32 82 return uintptr(h) 83 } 84 85 dwordHasher = func(key uint32) uintptr { 86 h := prime5 + 4 87 h ^= uint64(key) * prime1 88 h = bits.RotateLeft64(h, 23)*prime2 + prime3 89 h ^= h >> 33 90 h *= prime2 91 h ^= h >> 29 92 h *= prime3 93 h ^= h >> 32 94 return uintptr(h) 95 } 96 97 float32Hasher = func(key float32) uintptr { 98 h := prime5 + 4 99 h ^= uint64(*(*uint32)(unsafe.Pointer(&key))) * prime1 100 h = bits.RotateLeft64(h, 23)*prime2 + prime3 101 h ^= h >> 33 102 h *= prime2 103 h ^= h >> 29 104 h *= prime3 105 h ^= h >> 32 106 return uintptr(h) 107 } 108 109 qwordHasher = func(key uint64) uintptr { 110 k1 := key * prime2 111 k1 = bits.RotateLeft64(k1, 31) 112 k1 *= prime1 113 h := (prime5 + 8) ^ k1 114 h = bits.RotateLeft64(h, 27)*prime1 + prime4 115 h ^= h >> 33 116 h *= prime2 117 h ^= h >> 29 118 h *= prime3 119 h ^= h >> 32 120 return uintptr(h) 121 } 122 123 float64Hasher = func(key float64) uintptr { 124 k1 := *(*uint64)(unsafe.Pointer(&key)) * prime2 125 k1 = bits.RotateLeft64(k1, 31) 126 k1 *= prime1 127 h := (prime5 + 8) ^ k1 128 h = bits.RotateLeft64(h, 27)*prime1 + prime4 129 h ^= h >> 33 130 h *= prime2 131 h ^= h >> 29 132 h *= prime3 133 h ^= h >> 32 134 return uintptr(h) 135 } 136 137 complex64Hasher = func(key complex64) uintptr { 138 k1 := *(*uint64)(unsafe.Pointer(&key)) * prime2 139 k1 = bits.RotateLeft64(k1, 31) 140 k1 *= prime1 141 h := (prime5 + 8) ^ k1 142 h = bits.RotateLeft64(h, 27)*prime1 + prime4 143 h ^= h >> 33 144 h *= prime2 145 h ^= h >> 29 146 h *= prime3 147 h ^= h >> 32 148 return uintptr(h) 149 } 150 ) 151 152 func (m *Maper[K, V]) setDefaultHasher() { 153 // default hash functions 154 switch reflect.TypeOf(*new(K)).Kind() { 155 case reflect.String: 156 m.hasher = func(key K) uintptr { 157 sh := (*reflect.StringHeader)(unsafe.Pointer(&key)) 158 b := unsafe.Slice((*byte)(unsafe.Pointer(sh.Data)), sh.Len) 159 n := sh.Len 160 var h uint64 161 162 if n >= 32 { 163 v1 := prime1v + prime2 164 v2 := prime2 165 v3 := uint64(0) 166 v4 := -prime1v 167 for len(b) >= 32 { 168 v1 = round(v1, u64(b[0:8:len(b)])) 169 v2 = round(v2, u64(b[8:16:len(b)])) 170 v3 = round(v3, u64(b[16:24:len(b)])) 171 v4 = round(v4, u64(b[24:32:len(b)])) 172 b = b[32:len(b):len(b)] 173 } 174 h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4) 175 h = mergeRound(h, v1) 176 h = mergeRound(h, v2) 177 h = mergeRound(h, v3) 178 h = mergeRound(h, v4) 179 } else { 180 h = prime5 181 } 182 183 h += uint64(n) 184 185 i, end := 0, len(b) 186 for ; i+8 <= end; i += 8 { 187 k1 := round(0, u64(b[i:i+8:len(b)])) 188 h ^= k1 189 h = rol27(h)*prime1 + prime4 190 } 191 if i+4 <= end { 192 h ^= uint64(u32(b[i:i+4:len(b)])) * prime1 193 h = rol23(h)*prime2 + prime3 194 i += 4 195 } 196 for ; i < end; i++ { 197 h ^= uint64(b[i]) * prime5 198 h = rol11(h) * prime1 199 } 200 201 h ^= h >> 33 202 h *= prime2 203 h ^= h >> 29 204 h *= prime3 205 h ^= h >> 32 206 207 return uintptr(h) 208 } 209 case reflect.Int, reflect.Uint, reflect.Uintptr, reflect.UnsafePointer: 210 switch intSizeBytes { 211 case 2: 212 // word hasher 213 m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&wordHasher)) 214 case 4: 215 // dword hasher 216 m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&dwordHasher)) 217 case 8: 218 // qword hasher 219 m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&qwordHasher)) 220 } 221 case reflect.Int8, reflect.Uint8: 222 // byte hasher 223 m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&byteHasher)) 224 case reflect.Int16, reflect.Uint16: 225 // word hasher 226 m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&wordHasher)) 227 case reflect.Int32, reflect.Uint32: 228 // dword hasher 229 m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&dwordHasher)) 230 case reflect.Float32: 231 // custom float32 dword hasher 232 m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&float32Hasher)) 233 case reflect.Int64, reflect.Uint64: 234 // qword hasher 235 m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&qwordHasher)) 236 case reflect.Float64: 237 // custom float64 qword hasher 238 m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&float64Hasher)) 239 case reflect.Complex64: 240 // custom complex64 qword hasher 241 m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&complex64Hasher)) 242 case reflect.Complex128: 243 // oword hasher, key size -> 16 bytes 244 m.hasher = func(key K) uintptr { 245 b := *(*[owordSize]byte)(unsafe.Pointer(&key)) 246 h := prime5 + 16 247 248 val := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | 249 uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 250 251 k1 := val * prime2 252 k1 = bits.RotateLeft64(k1, 31) 253 k1 *= prime1 254 255 h ^= k1 256 h = bits.RotateLeft64(h, 27)*prime1 + prime4 257 258 val = uint64(b[8]) | uint64(b[9])<<8 | uint64(b[10])<<16 | uint64(b[11])<<24 | 259 uint64(b[12])<<32 | uint64(b[13])<<40 | uint64(b[14])<<48 | uint64(b[15])<<56 260 261 k1 = val * prime2 262 k1 = bits.RotateLeft64(k1, 31) 263 k1 *= prime1 264 265 h ^= k1 266 h = bits.RotateLeft64(h, 27)*prime1 + prime4 267 268 h ^= h >> 33 269 h *= prime2 270 h ^= h >> 29 271 h *= prime3 272 h ^= h >> 32 273 274 return uintptr(h) 275 } 276 } 277 }