github.com/moontrade/nogc@v0.1.7/hash/wyhash.go (about)

     1  package hash
     2  
     3  import "math/bits"
     4  
     5  /////////////////////////////////////////////////////////////////////////////////////////////////////////
     6  // WyHash
     7  /////////////////////////////////////////////////////////////////////////////////////////////////////////
     8  const (
     9  	wyp0 uint64 = 0xa0761d6478bd642f
    10  	wyp1 uint64 = 0xe7037ed1a0b428db
    11  	wyp2 uint64 = 0x8ebc6af09c88c6e3
    12  	wyp3 uint64 = 0x589965cc75374cc3
    13  	wyp4 uint64 = 0x1d8e4e27c47d124f
    14  	wyp5 uint64 = 0xeb44accab455d165
    15  
    16  	wyseed uint64 = 0xeb44accab455d165
    17  	//wyseed uint64 = 0xeb44accab455d16f
    18  	//wyseed uint64 = 0x8ebc6af09c88c6e3
    19  )
    20  
    21  func wymum(A, B uint64) uint64 {
    22  	hi, lo := bits.Mul64(A, B)
    23  	return hi ^ lo
    24  }
    25  
    26  ////go:inline
    27  //func wymum(x, y uint64) uint64 {
    28  //	const mask32 = 1<<32 - 1
    29  //	x0 := x & mask32
    30  //	x1 := x >> 32
    31  //	y0 := y & mask32
    32  //	y1 := y >> 32
    33  //	w0 := x0 * y0
    34  //	t := x1*y0 + w0>>32
    35  //	w1 := t & mask32
    36  //	w2 := t >> 32
    37  //	w1 += x0 * y1
    38  //	return (x1*y1 + w2 + w1>>32) ^ (x * y)
    39  //}
    40  
    41  func WyHash32(v uint32) uint32 {
    42  	return uint32(wymum(wymum(uint64(v)^wyseed^wyp0, uint64(v)^wyseed^wyp1)^wyseed, uint64(4)^wyp4))
    43  }
    44  
    45  func WyHash64(v uint64) uint64 {
    46  	return wymum(wymum(v^wyseed^wyp0, v^wyseed^wyp1)^wyseed, 8^wyp4)
    47  }
    48  
    49  func wyr3(p []byte) uint64 {
    50  	k := len(p)
    51  	return (uint64(p[0]) << 16) | (uint64(p[k>>1]) << 8) | uint64(p[k-1])
    52  }
    53  
    54  func wyr8mix(b []byte) uint64 {
    55  	return uint64(uint32(b[0])|uint32(b[1])<<8|uint32(b[2])<<16|uint32(b[3])<<24)<<32 |
    56  		uint64(uint32(b[4])|uint32(b[5])<<8|uint32(b[6])<<16|uint32(b[7])<<24)
    57  }
    58  
    59  func WyHash(key []byte, wyseed uint64) uint64 {
    60  	p := key
    61  	if len(p) == 0 {
    62  		return wyseed
    63  	}
    64  	switch {
    65  	case len(p) < 4:
    66  		return wymum(wymum(wyr3(p)^wyseed^wyp0, wyseed^wyp1)^wyseed, uint64(len(p))^wyp4)
    67  	case len(p) <= 8:
    68  		return wymum(wymum(uint64(toUint32LE(p[:4]))^wyseed^wyp0, uint64(toUint32LE(p[len(p)-4:len(p)-4+4]))^wyseed^wyp1)^wyseed, uint64(len(p))^wyp4)
    69  	case len(p) <= 16:
    70  		return wymum(wymum(wyr8mix(p)^wyseed^wyp0, wyr8mix(p[len(p)-8:])^wyseed^wyp1)^wyseed, uint64(len(p))^wyp4)
    71  	case len(p) <= 24:
    72  		return wymum(wymum(wyr8mix(p)^wyseed^wyp0, wyr8mix(p[8:])^wyseed^wyp1)^wymum(wyr8mix(p[len(key)-8:])^wyseed^wyp2, wyseed^wyp3), uint64(len(p))^wyp4)
    73  	case len(p) <= 32:
    74  		return wymum(wymum(wyr8mix(p)^wyseed^wyp0, wyr8mix(p[8:])^wyseed^wyp1)^wymum(wyr8mix(p[16:])^wyseed^wyp2, wyr8mix(p[len(key)-8:])^wyseed^wyp3), uint64(len(p))^wyp4)
    75  	}
    76  
    77  	see1 := wyseed
    78  	for len(p) > 256 {
    79  		wyseed = wymum(toUint64LE(p[:8])^wyseed^wyp0, toUint64LE(p[8:8+8])^wyseed^wyp1) ^ wymum(toUint64LE(p[16:16+8])^wyseed^wyp2, toUint64LE(p[24:24+8])^wyseed^wyp3)
    80  		see1 = wymum(toUint64LE(p[32:32+8])^see1^wyp1, toUint64LE(p[40:40+8])^see1^wyp2) ^ wymum(toUint64LE(p[48:48+8])^see1^wyp3, toUint64LE(p[56:56+8])^see1^wyp0)
    81  		wyseed = wymum(toUint64LE(p[64:64+8])^wyseed^wyp0, toUint64LE(p[72:72+8])^wyseed^wyp1) ^ wymum(toUint64LE(p[80:80+8])^wyseed^wyp2, toUint64LE(p[88:88+8])^wyseed^wyp3)
    82  		see1 = wymum(toUint64LE(p[96:96+8])^see1^wyp1, toUint64LE(p[104:104+8])^see1^wyp2) ^ wymum(toUint64LE(p[112:112+8])^see1^wyp3, toUint64LE(p[120:120+8])^see1^wyp0)
    83  		wyseed = wymum(toUint64LE(p[128:128+8])^wyseed^wyp0, toUint64LE(p[136:136+8])^wyseed^wyp1) ^ wymum(toUint64LE(p[144:144+8])^wyseed^wyp2, toUint64LE(p[152:152+8])^wyseed^wyp3)
    84  		see1 = wymum(toUint64LE(p[160:160+8])^see1^wyp1, toUint64LE(p[168:168+8])^see1^wyp2) ^ wymum(toUint64LE(p[176:176+8])^see1^wyp3, toUint64LE(p[184:184+8])^see1^wyp0)
    85  		wyseed = wymum(toUint64LE(p[192:192+8])^wyseed^wyp0, toUint64LE(p[200:200+8])^wyseed^wyp1) ^ wymum(toUint64LE(p[208:208+8])^wyseed^wyp2, toUint64LE(p[216:216+8])^wyseed^wyp3)
    86  		see1 = wymum(toUint64LE(p[224:224+8])^see1^wyp1, toUint64LE(p[232:232+8])^see1^wyp2) ^ wymum(toUint64LE(p[240:240+8])^see1^wyp3, toUint64LE(p[248:248+8])^see1^wyp0)
    87  		p = p[256:]
    88  	}
    89  
    90  	for len(p) > 32 {
    91  		wyseed = wymum(toUint64LE(p[:8])^wyseed^wyp0, toUint64LE(p[8:8+8])^wyseed^wyp1)
    92  		see1 = wymum(toUint64LE(p[16:16+8])^see1^wyp2, toUint64LE(p[24:24+8])^see1^wyp3)
    93  		p = p[32:]
    94  	}
    95  
    96  	switch {
    97  	case len(p) < 4:
    98  		wyseed = wymum(wyr3(p)^wyseed^wyp0, wyseed^wyp1)
    99  	case len(p) <= 8:
   100  		wyseed = wymum(uint64(toUint32LE(p[:4]))^wyseed^wyp0, uint64(toUint32LE(p[len(p)-4:len(p)-4+4]))^wyseed^wyp1)
   101  	case len(p) <= 16:
   102  		wyseed = wymum(wyr8mix(p)^wyseed^wyp0, wyr8mix(p[len(p)-8:])^wyseed^wyp1)
   103  	case len(p) <= 24:
   104  		wyseed = wymum(wyr8mix(p)^wyseed^wyp0, wyr8mix(p[8:])^wyseed^wyp1)
   105  		see1 = wymum(wyr8mix(p[len(p)-8:])^see1^wyp2, see1^wyp3)
   106  	default:
   107  		wyseed = wymum(wyr8mix(p)^wyseed^wyp0, wyr8mix(p[8:])^wyseed^wyp1)
   108  		see1 = wymum(wyr8mix(p[16:])^see1^wyp2, wyr8mix(p[len(p)-8:])^see1^wyp3)
   109  
   110  	}
   111  	return wymum(wyseed^see1, uint64(len(key))^wyp4)
   112  }