github.com/primecitizens/pcz/std@v0.2.1/core/hash/hash64.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright 2023 The Prime Citizens 3 // 4 // Copyright 2014 The Go Authors. All rights reserved. 5 // Use of this source code is governed by a BSD-style 6 // license that can be found in the LICENSE file. 7 8 // Hashing algorithm inspired by 9 // wyhash: https://github.com/wangyi-fudan/wyhash 10 11 //go:build amd64 || arm64 || mips64 || mips64le || ppc64 || ppc64le || riscv64 || s390x || wasm 12 13 package hash 14 15 import ( 16 "unsafe" 17 18 "github.com/primecitizens/pcz/std/core/math" 19 "github.com/primecitizens/pcz/std/core/mem" 20 ) 21 22 const ( 23 m1 = 0xa0761d6478bd642f 24 m2 = 0xe7037ed1a0b428db 25 m3 = 0x8ebc6af09c88c6e3 26 m4 = 0x589965cc75374cc3 27 m5 = 0x1d8e4e27c47d124f 28 ) 29 30 func MemHash(p unsafe.Pointer, seed, s uintptr) uintptr { 31 var a, b uintptr 32 seed ^= hashkey[0] ^ m1 33 switch { 34 case s == 0: 35 return seed 36 case s < 4: 37 a = uintptr(*(*byte)(p)) 38 a |= uintptr(*(*byte)(unsafe.Add(p, s>>1))) << 8 39 a |= uintptr(*(*byte)(unsafe.Add(p, s-1))) << 16 40 case s == 4: 41 a = r4(p) 42 b = a 43 case s < 8: 44 a = r4(p) 45 b = r4(unsafe.Add(p, s-4)) 46 case s == 8: 47 a = r8(p) 48 b = a 49 case s <= 16: 50 a = r8(p) 51 b = r8(unsafe.Add(p, s-8)) 52 default: 53 l := s 54 if l > 48 { 55 seed1 := seed 56 seed2 := seed 57 for ; l > 48; l -= 48 { 58 seed = mix(r8(p)^m2, r8(unsafe.Add(p, 8))^seed) 59 seed1 = mix(r8(unsafe.Add(p, 16))^m3, r8(unsafe.Add(p, 24))^seed1) 60 seed2 = mix(r8(unsafe.Add(p, 32))^m4, r8(unsafe.Add(p, 40))^seed2) 61 p = unsafe.Add(p, 48) 62 } 63 seed ^= seed1 ^ seed2 64 } 65 for ; l > 16; l -= 16 { 66 seed = mix(r8(p)^m2, r8(unsafe.Add(p, 8))^seed) 67 p = unsafe.Add(p, 16) 68 } 69 a = r8(unsafe.Add(p, l-16)) 70 b = r8(unsafe.Add(p, l-8)) 71 } 72 73 return mix(m5^s, mix(a^m2, b^seed)) 74 } 75 76 func MemHash32(p unsafe.Pointer, seed uintptr) uintptr { 77 a := r4(p) 78 return mix(m5^4, mix(a^m2, a^seed^hashkey[0]^m1)) 79 } 80 81 func MemHash64(p unsafe.Pointer, seed uintptr) uintptr { 82 a := r8(p) 83 return mix(m5^8, mix(a^m2, a^seed^hashkey[0]^m1)) 84 } 85 86 func mix(a, b uintptr) uintptr { 87 hi, lo := math.Mul64(uint64(a), uint64(b)) 88 return uintptr(hi ^ lo) 89 } 90 91 func r4(p unsafe.Pointer) uintptr { 92 return uintptr(mem.ReadUnaligned32(p)) 93 } 94 95 func r8(p unsafe.Pointer) uintptr { 96 return uintptr(mem.ReadUnaligned64(p)) 97 }