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 }