github.com/andy2046/gopie@v0.7.0/pkg/jumphash/jumphash.go (about)

     1  // Package jumphash provides a jump consistent hash implementation.
     2  package jumphash
     3  
     4  import (
     5  	"hash/crc64"
     6  	"io"
     7  )
     8  
     9  var (
    10  	// hashCRC64 uses the 64-bit Cyclic Redundancy Check (CRC-64) with the ECMA polynomial.
    11  	hashCRC64 = crc64.New(crc64.MakeTable(crc64.ECMA))
    12  )
    13  
    14  // Hash takes a key and the number of buckets, returns an integer in the range [0, buckets).
    15  // If the number of buckets is not greater than 1 then 1 is used.
    16  func Hash(key uint64, buckets int) int {
    17  	var b, j int64
    18  
    19  	if buckets <= 0 {
    20  		buckets = 1
    21  	}
    22  
    23  	for j < int64(buckets) {
    24  		b = j
    25  		key = key*2862933555777941757 + 1
    26  		j = int64(float64(b+1) * (float64(int64(1)<<31) / float64((key>>33)+1)))
    27  	}
    28  
    29  	return int(b)
    30  }
    31  
    32  // HashString takes string as key instead of integer and uses CRC-64 to generate key.
    33  func HashString(key string, buckets int) int {
    34  	hashCRC64.Reset()
    35  	_, err := io.WriteString(hashCRC64, key)
    36  	if err != nil {
    37  		panic(err)
    38  	}
    39  	return Hash(hashCRC64.Sum64(), buckets)
    40  }
    41  
    42  // Hasher represents a jump consistent Hasher using a string as key.
    43  type Hasher struct {
    44  	n int32
    45  }
    46  
    47  // New returns a new instance of of Hasher.
    48  func New(n int) *Hasher {
    49  	if n <= 0 {
    50  		panic("the number of buckets must be positive int")
    51  	}
    52  	return &Hasher{int32(n)}
    53  }
    54  
    55  // N returns the number of buckets the hasher can assign to.
    56  func (h *Hasher) N() int {
    57  	return int(h.n)
    58  }
    59  
    60  // Hash returns the integer hash for the given key.
    61  func (h *Hasher) Hash(key string) int {
    62  	return HashString(key, int(h.n))
    63  }