github.com/panmari/cuckoofilter@v1.0.7-0.20231223155748-763d1d471ee8/util.go (about) 1 package cuckoo 2 3 import ( 4 "encoding/binary" 5 _ "unsafe" // For linking fastrand. 6 7 metro "github.com/dgryski/go-metro" 8 ) 9 10 // fastrand is a fast thread local random function. 11 // 12 //go:linkname fastrandn runtime.fastrandn 13 func fastrandn(n uint32) uint32 14 15 // randi returns either i1 or i2 randomly. 16 func randi(i1, i2 uint) uint { 17 if fastrandn(2) == 0 { 18 return i1 19 } 20 return i2 21 } 22 23 func getAltIndex(fp fingerprint, i uint, bucketIndexMask uint) uint { 24 b := make([]byte, 2) 25 binary.LittleEndian.PutUint16(b, uint16(fp)) 26 hash := uint(metro.Hash64(b, 1337)) 27 return (i ^ hash) & bucketIndexMask 28 } 29 30 func getFingerprint(hash uint64) fingerprint { 31 // Use most significant bits for fingerprint. 32 shifted := hash >> (64 - fingerprintSizeBits) 33 // Valid fingerprints are in range [1, maxFingerprint], leaving 0 as the special empty state. 34 fp := shifted%(maxFingerprint-1) + 1 35 return fingerprint(fp) 36 } 37 38 // getIndexAndFingerprint returns the primary bucket index and fingerprint to be used 39 func getIndexAndFingerprint(data []byte, bucketIndexMask uint) (uint, fingerprint) { 40 hash := metro.Hash64(data, 1337) 41 f := getFingerprint(hash) 42 // Use least significant bits for deriving index. 43 i1 := uint(hash) & bucketIndexMask 44 return i1, f 45 } 46 47 func getNextPow2(n uint64) uint { 48 n-- 49 n |= n >> 1 50 n |= n >> 2 51 n |= n >> 4 52 n |= n >> 8 53 n |= n >> 16 54 n |= n >> 32 55 n++ 56 return uint(n) 57 }