mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-04 19:17:47 +00:00
72 lines
1.8 KiB
Go
72 lines
1.8 KiB
Go
//go:build runtime_memhash_leveldb || (wasip1 && !runtime_memhash_fnv && !runtime_memhash_tsip)
|
|
|
|
// This is the default for WASI, but can also be used on other targets with the
|
|
// right build tag.
|
|
|
|
// This is the hash function from Google's leveldb key-value storage system. It
|
|
// processes 4 bytes at a time making it faster than the FNV hash for buffer
|
|
// lengths > 16 bytes.
|
|
|
|
// https://github.com/google/leveldb
|
|
// https://en.wikipedia.org/wiki/LevelDB
|
|
|
|
package runtime
|
|
|
|
import (
|
|
"unsafe"
|
|
)
|
|
|
|
// leveldb hash
|
|
func hash32(ptr unsafe.Pointer, n, seed uintptr) uint32 {
|
|
|
|
const (
|
|
lseed = 0xbc9f1d34
|
|
m = 0xc6a4a793
|
|
)
|
|
|
|
b := unsafe.Slice((*byte)(ptr), n)
|
|
|
|
h := uint32(lseed^seed) ^ uint32(uint(len(b))*uint(m))
|
|
|
|
for ; len(b) >= 4; b = b[4:] {
|
|
h += uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
|
|
h *= m
|
|
h ^= h >> 16
|
|
}
|
|
switch len(b) {
|
|
case 3:
|
|
h += uint32(b[2]) << 16
|
|
fallthrough
|
|
case 2:
|
|
h += uint32(b[1]) << 8
|
|
fallthrough
|
|
case 1:
|
|
h += uint32(b[0])
|
|
h *= m
|
|
h ^= h >> 24
|
|
}
|
|
|
|
return h
|
|
}
|
|
|
|
// hash64finalizer is a 64-bit integer mixing function from
|
|
// https://web.archive.org/web/20120720045250/http://www.cris.com/~Ttwang/tech/inthash.htm
|
|
func hash64finalizer(key uint64) uint64 {
|
|
key = ^key + (key << 21) // key = (key << 21) - key - 1;
|
|
key = key ^ (key >> 24)
|
|
key = (key + (key << 3)) + (key << 8) // key * 265
|
|
key = key ^ (key >> 14)
|
|
key = (key + (key << 2)) + (key << 4) // key * 21
|
|
key = key ^ (key >> 28)
|
|
key = key + (key << 31)
|
|
return key
|
|
}
|
|
|
|
// hash64 turns hash32 into a 64-bit hash, by use hash64finalizer to
|
|
// mix the result of hash32 function combined with an xorshifted version of
|
|
// the seed.
|
|
func hash64(ptr unsafe.Pointer, n, seed uintptr) uint64 {
|
|
h32 := hash32(ptr, n, seed)
|
|
return hash64finalizer((uint64(h32^xorshift32(uint32(seed))) << 32) | uint64(h32))
|
|
}
|