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  }