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

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