github.com/bytedance/gopkg@v0.0.0-20240514070511-01b2cbcf35e1/internal/wyhash/wyhash.go (about)

     1  // Copyright 2021 ByteDance Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package wyhash implements https://github.com/wangyi-fudan/wyhash
    16  package wyhash
    17  
    18  import (
    19  	"math/bits"
    20  	"unsafe"
    21  
    22  	"github.com/bytedance/gopkg/internal/hack"
    23  	"github.com/bytedance/gopkg/internal/runtimex"
    24  )
    25  
    26  const (
    27  	DefaultSeed = 0xa0761d6478bd642f // s0
    28  	s1          = 0xe7037ed1a0b428db
    29  	s2          = 0x8ebc6af09c88c6e3
    30  	s3          = 0x589965cc75374cc3
    31  	s4          = 0x1d8e4e27c47d124f
    32  )
    33  
    34  func _wymix(a, b uint64) uint64 {
    35  	hi, lo := bits.Mul64(a, b)
    36  	return hi ^ lo
    37  }
    38  
    39  //go:nosplit
    40  func add(p unsafe.Pointer, x uintptr) unsafe.Pointer {
    41  	return unsafe.Pointer(uintptr(p) + x)
    42  }
    43  
    44  func Sum64(data []byte) uint64 {
    45  	return Sum64WithSeed(data, DefaultSeed)
    46  }
    47  
    48  func Sum64String(data string) uint64 {
    49  	return Sum64StringWithSeed(data, DefaultSeed)
    50  }
    51  
    52  func Sum64WithSeed(data []byte, seed uint64) uint64 {
    53  	return Sum64StringWithSeed(hack.BytesToString(data), seed)
    54  }
    55  
    56  func Sum64StringWithSeed(data string, seed uint64) uint64 {
    57  	var (
    58  		a, b uint64
    59  	)
    60  
    61  	length := len(data)
    62  	i := uintptr(len(data))
    63  	paddr := *(*unsafe.Pointer)(unsafe.Pointer(&data))
    64  
    65  	if i > 64 {
    66  		var see1 = seed
    67  		for i > 64 {
    68  			seed = _wymix(runtimex.ReadUnaligned64(paddr)^s1, runtimex.ReadUnaligned64(add(paddr, 8))^seed) ^ _wymix(runtimex.ReadUnaligned64(add(paddr, 16))^s2, runtimex.ReadUnaligned64(add(paddr, 24))^seed)
    69  			see1 = _wymix(runtimex.ReadUnaligned64(add(paddr, 32))^s3, runtimex.ReadUnaligned64(add(paddr, 40))^see1) ^ _wymix(runtimex.ReadUnaligned64(add(paddr, 48))^s4, runtimex.ReadUnaligned64(add(paddr, 56))^see1)
    70  			paddr = add(paddr, 64)
    71  			i -= 64
    72  		}
    73  		seed ^= see1
    74  	}
    75  
    76  	for i > 16 {
    77  		seed = _wymix(runtimex.ReadUnaligned64(paddr)^s1, runtimex.ReadUnaligned64(add(paddr, 8))^seed)
    78  		paddr = add(paddr, 16)
    79  		i -= 16
    80  	}
    81  
    82  	// i <= 16
    83  	switch {
    84  	case i == 0:
    85  		return _wymix(s1, _wymix(s1, seed))
    86  	case i < 4:
    87  		a = uint64(*(*byte)(paddr))<<16 | uint64(*(*byte)(add(paddr, uintptr(i>>1))))<<8 | uint64(*(*byte)(add(paddr, uintptr(i-1))))
    88  		// b = 0
    89  		return _wymix(s1^uint64(length), _wymix(a^s1, seed))
    90  	case i == 4:
    91  		a = runtimex.ReadUnaligned32(paddr)
    92  		// b = 0
    93  		return _wymix(s1^uint64(length), _wymix(a^s1, seed))
    94  	case i < 8:
    95  		a = runtimex.ReadUnaligned32(paddr)
    96  		b = runtimex.ReadUnaligned32(add(paddr, i-4))
    97  		return _wymix(s1^uint64(length), _wymix(a^s1, b^seed))
    98  	case i == 8:
    99  		a = runtimex.ReadUnaligned64(paddr)
   100  		// b = 0
   101  		return _wymix(s1^uint64(length), _wymix(a^s1, seed))
   102  	default: // 8 < i <= 16
   103  		a = runtimex.ReadUnaligned64(paddr)
   104  		b = runtimex.ReadUnaligned64(add(paddr, i-8))
   105  		return _wymix(s1^uint64(length), _wymix(a^s1, b^seed))
   106  	}
   107  }