github.com/zhangyunhao116/wyhash@v0.4.1-0.20220217162229-7d42996fa899/internal/wyhashfv3/wyhash.go (about)

     1  // Package wyhashfv3 implements wyhash final version 3;
     2  // DO NOT USE IT, for test only.
     3  package wyhashfv3
     4  
     5  import (
     6  	"math/bits"
     7  	"reflect"
     8  	"unsafe"
     9  )
    10  
    11  const (
    12  	s0 uint64 = 0xa0761d6478bd642f
    13  	s1 uint64 = 0xe7037ed1a0b428db
    14  	s2 uint64 = 0x8ebc6af09c88c6e3
    15  	s3 uint64 = 0x589965cc75374cc3
    16  	s4 uint64 = 0x1d8e4e27c47d124f
    17  )
    18  
    19  //go:linkname readUnaligned32 runtime.readUnaligned32
    20  func readUnaligned32(p unsafe.Pointer) uint32
    21  
    22  //go:linkname readUnaligned64 runtime.readUnaligned64
    23  func readUnaligned64(p unsafe.Pointer) uint64
    24  
    25  func _wyr8(x []byte) uint64 {
    26  	array := *(*unsafe.Pointer)(unsafe.Pointer(&x))
    27  	return readUnaligned64(array)
    28  }
    29  
    30  func _wyr4(x []byte) uint64 {
    31  	array := *(*unsafe.Pointer)(unsafe.Pointer(&x))
    32  	return uint64(readUnaligned32(array))
    33  }
    34  
    35  func _wyr3(x []byte, k int) uint64 {
    36  	return uint64(x[0])<<16 | uint64(x[k>>1])<<8 | uint64(x[k-1])
    37  }
    38  
    39  func _wymix(a, b uint64) uint64 {
    40  	hi, lo := bits.Mul64(a, b)
    41  	return hi ^ lo
    42  }
    43  
    44  func Sum64(p []byte) uint64 {
    45  	return Sum64WithSeed(p, s0)
    46  }
    47  
    48  func Sum64WithSeed(p []byte, seed uint64) uint64 {
    49  	length := uint64(len(p))
    50  	var a, b uint64
    51  	if length <= 16 {
    52  		if length >= 4 {
    53  			// a=(_wyr4(p)<<32)|_wyr4(p+((len>>3)<<2)); b=(_wyr4(p+len-4)<<32)|_wyr4(p+len-4-((len>>3)<<2));
    54  			a = _wyr4(p)<<32 | _wyr4(p[(length>>3)<<2:])
    55  			b = _wyr4(p[length-4:])<<32 | _wyr4(p[length-4-((length>>3)<<2):])
    56  		} else if length > 0 {
    57  			// a=_wyr3(p,len); b=0;
    58  			a = _wyr3(p, int(length))
    59  		}
    60  	} else {
    61  		var (
    62  			see1 = seed
    63  			see2 = seed
    64  		)
    65  		// Note: the i will be len(p).
    66  		if len(p) > 48 {
    67  			for len(p) > 48 {
    68  				// seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed);
    69  				// see1=_wymix(_wyr8(p+16)^secret[2],_wyr8(p+24)^see1);
    70  				// see2=_wymix(_wyr8(p+32)^secret[3],_wyr8(p+40)^see2);
    71  				// p+=48; i-=48;
    72  				seed = _wymix(_wyr8(p)^s1, _wyr8(p[8:])^seed)
    73  				see1 = _wymix(_wyr8(p[16:])^s2, _wyr8(p[24:])^see1)
    74  				see2 = _wymix(_wyr8(p[32:])^s3, _wyr8(p[40:])^see2)
    75  				p = p[48:]
    76  			}
    77  			seed ^= see1 ^ see2
    78  		}
    79  		for len(p) > 16 {
    80  			// seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed);  i-=16; p+=16;
    81  			seed = _wymix(_wyr8(p)^s1, _wyr8(p[8:])^seed)
    82  			p = p[16:]
    83  		}
    84  		// a=_wyr8(p+i-16);  b=_wyr8(p+i-8);
    85  		// HACK
    86  		var ap, bp []byte
    87  		ph := (*reflect.SliceHeader)(unsafe.Pointer(&p))
    88  		aph := (*reflect.SliceHeader)(unsafe.Pointer(&ap))
    89  		bph := (*reflect.SliceHeader)(unsafe.Pointer(&bp))
    90  		aph.Cap, aph.Len, bph.Cap, bph.Len = 16, 16, 16, 16
    91  		aph.Data = uintptr(uint64(ph.Data) + uint64(len(p)) - 16)
    92  		bph.Data = uintptr(uint64(ph.Data) + uint64(len(p)) - 8)
    93  		a = _wyr8(ap)
    94  		b = _wyr8(bp)
    95  	}
    96  	return _wymix(s1^length, _wymix(a^s1, b^seed))
    97  }