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 }