v8.run/go/exp@v0.0.26-0.20230226010534-afcdbd3f782d/hash/wyhash/wyhash.go (about) 1 package wyhash 2 3 import ( 4 "math/bits" 5 "reflect" 6 "unsafe" 7 ) 8 9 func _wymix(A uint64, B uint64) uint64 { 10 B, A = bits.Mul64(A, B) 11 return A ^ B 12 } 13 14 func _wyr8(p *uint8) uint64 { 15 var pp = (*[8]uint8)(unsafe.Pointer(p)) 16 return uint64(pp[0]) | uint64(pp[1])<<8 | uint64(pp[2])<<16 | uint64(pp[3])<<24 | uint64(pp[4])<<32 | uint64(pp[5])<<40 | uint64(pp[6])<<48 | uint64(pp[7])<<56 17 } 18 19 func _wyr4(p *uint8) uint64 { 20 var pp = (*[4]uint8)(unsafe.Pointer(p)) 21 return uint64(uint32(pp[0]) | uint32(pp[1])<<8 | uint32(pp[2])<<16 | uint32(pp[3])<<24) 22 } 23 24 func _wyr3(p *uint8, k uintptr) uint64 { 25 // (((uint64_t)p[0]) << 16) | (((uint64_t)p[k >> 1]) << 8) | p[k - 1]; 26 return (uint64(*p) << 16) | 27 (uint64(*(*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + k>>1))) << 8) | 28 (uint64(*(*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + k - 1)))) 29 } 30 31 var _wyp = [4]uint64{0xa0761d6478bd642f, 0xe7037ed1a0b428db, 0x8ebc6af09c88c6e3, 0x589965cc75374cc3} 32 33 func wyhash(key unsafe.Pointer, len uintptr, seed uint64, secret *[4]uint64) uint64 { 34 var p *uint8 = (*uint8)(key) 35 seed ^= secret[0] 36 var a, b uint64 37 if len <= 16 { 38 if len >= 4 { 39 a = (_wyr4(p) << 32) | _wyr4((*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(p))+((len>>3)<<2)))) 40 b = (_wyr4((*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(p))+len-4))) << 32) | _wyr4((*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(p))+len-4-((len>>3)<<2)))) 41 } else if len > 0 { 42 a = _wyr3(p, len) 43 b = 0 44 } 45 } else { 46 var i = len 47 if i > 48 { 48 var see1, see2 uint64 = seed, seed 49 for { 50 seed = _wymix(_wyr8(p)^secret[1], _wyr8((*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(p))+8)))^seed) 51 see1 = _wymix(_wyr8((*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(p))+16)))^secret[2], _wyr8((*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(p))+24)))^see1) 52 see2 = _wymix(_wyr8((*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(p))+32)))^secret[3], _wyr8((*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(p))+40)))^see2) 53 p = (*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + 48)) 54 i -= 48 55 if i <= 48 { 56 break 57 } 58 } 59 seed ^= see1 ^ see2 60 } 61 for i > 16 { 62 seed = _wymix(_wyr8(p)^secret[1], _wyr8((*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(p))+8)))^seed) 63 i -= 16 64 p = (*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + 16)) 65 } 66 a = _wyr8((*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + i - 16))) 67 b = _wyr8((*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + i - 8))) 68 } 69 return _wymix(secret[1]^uint64(len), _wymix(a^secret[1], b^seed)) 70 } 71 72 func wyrand(seed *uint64) uint64 { 73 *seed += 0xa0761d6478bd642f 74 return _wymix(*seed, *seed^0xe7037ed1a0b428db) 75 } 76 77 func WYRAND(seed *uint64) uint64 { return wyrand(seed) } 78 79 func Hash(b []byte, seed uint64) uint64 { 80 return wyhash( 81 unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&b)).Data), 82 uintptr((*reflect.SliceHeader)(unsafe.Pointer(&b)).Len), 83 seed, 84 &_wyp, 85 ) 86 } 87 88 func HashString(b string, seed uint64) uint64 { 89 return wyhash( 90 unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&b)).Data), 91 uintptr((*reflect.StringHeader)(unsafe.Pointer(&b)).Len), 92 seed, 93 &_wyp, 94 ) 95 } 96 97 func WYHASH_RAW(key unsafe.Pointer, len uintptr, seed uint64) uint64 { 98 return wyhash(key, len, seed, &_wyp) 99 }