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

     1  package wyhash
     2  
     3  import (
     4  	"unsafe"
     5  
     6  	"github.com/zhangyunhao116/sbconv"
     7  	"github.com/zhangyunhao116/wyhash/internal/unalign"
     8  )
     9  
    10  func Sum64V3(data []byte) uint64 {
    11  	return Sum64WithSeedV3(data, DefaultSeed)
    12  }
    13  
    14  func Sum64StringV3(data string) uint64 {
    15  	return Sum64StringWithSeedV3(data, DefaultSeed)
    16  }
    17  
    18  func Sum64WithSeedV3(data []byte, seed uint64) uint64 {
    19  	return Sum64StringWithSeedV3(sbconv.BytesToString(data), seed)
    20  }
    21  
    22  func Sum64StringWithSeedV3(data string, seed uint64) uint64 {
    23  	var (
    24  		a, b uint64
    25  	)
    26  
    27  	length := len(data)
    28  	i := uintptr(len(data))
    29  	paddr := *(*unsafe.Pointer)(unsafe.Pointer(&data))
    30  
    31  	if length <= 16 {
    32  		if length >= 4 {
    33  			// Note: for short string, i == uintptr(length)
    34  			// a=(_wyr4(p)<<32)|_wyr4(p+((len>>3)<<2)); b=(_wyr4(p+len-4)<<32)|_wyr4(p+len-4-((len>>3)<<2));
    35  			a = unalign.Read4(paddr)<<32 | unalign.Read4(add(paddr, (i>>3)<<2))
    36  			b = unalign.Read4(add(paddr, i-4))<<32 | unalign.Read4(add(paddr, i-4-((i>>3)<<2)))
    37  		} else if length > 0 {
    38  			// a=_wyr3(p,len); b=0;
    39  			a = uint64(*(*byte)(paddr))<<16 | uint64(*(*byte)(add(paddr, uintptr(i>>1))))<<8 | uint64(*(*byte)(add(paddr, uintptr(i-1))))
    40  		}
    41  	} else {
    42  		var (
    43  			see1 = seed
    44  			see2 = seed
    45  		)
    46  		if i > 48 {
    47  			for i > 48 {
    48  				// seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed);
    49  				// see1=_wymix(_wyr8(p+16)^secret[2],_wyr8(p+24)^see1);
    50  				// see2=_wymix(_wyr8(p+32)^secret[3],_wyr8(p+40)^see2);
    51  				// p+=48; i-=48;
    52  				seed = _wymix(unalign.Read8(paddr)^s1, unalign.Read8(add(paddr, 8))^seed)
    53  				see1 = _wymix(unalign.Read8(add(paddr, 16))^s2, unalign.Read8(add(paddr, 24))^see1)
    54  				see2 = _wymix(unalign.Read8(add(paddr, 32))^s3, unalign.Read8(add(paddr, 40))^see2)
    55  				paddr = add(paddr, 48)
    56  				i -= 48
    57  			}
    58  			seed ^= see1 ^ see2
    59  		}
    60  		for i > 16 {
    61  			// seed=_wymix(unalign.Read8(p)^secret[1],unalign.Read8(p+8)^seed);  i-=16; p+=16;
    62  			seed = _wymix(unalign.Read8(paddr)^s1, unalign.Read8(add(paddr, 8))^seed)
    63  			paddr = add(paddr, 16)
    64  			i -= 16
    65  		}
    66  		// a=unalign.Read8(p+i-16);  b=unalign.Read8(p+i-8);
    67  		a = unalign.Read8(add(paddr, i-16))
    68  		b = unalign.Read8(add(paddr, i-8))
    69  	}
    70  	// _wymix(secret[1]^len,_wymix(a^secret[1],b^seed));
    71  	return _wymix(s1^uint64(length), _wymix(a^s1, b^seed))
    72  }