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  }