///|
pub fn BinaryFuseFilter::candidate_locations(
self : BinaryFuseFilter,
hash : Int,
) -> FuseLocations? {
if hash < 0 {
return None
}
let mixed = mix_hash(hash, self.seed)
let (first, second, third) = positions(
mixed,
self.segment_length,
self.segment_count,
)
Some({ first, second, third })
}
///|
pub fn BinaryFuseFilter::slot_fingerprints(
self : BinaryFuseFilter,
hash : Int,
) -> Array[Int] {
match self.candidate_locations(hash) {
None => []
Some(locations) =>
[
self.fingerprints[locations.first],
self.fingerprints[locations.second],
self.fingerprints[locations.third],
]
}
}
///|
pub fn BinaryFuseFilter::fingerprint_stats(
self : BinaryFuseFilter,
) -> FingerprintStats {
let mut occupied_slots = 0
let mut maximum_fingerprint = 0
let mut fingerprint_sum = 0
for value in self.fingerprints {
if value != 0 {
occupied_slots = occupied_slots + 1
}
if value > maximum_fingerprint {
maximum_fingerprint = value
}
fingerprint_sum = fingerprint_sum + value
}
{
slot_count: self.fingerprints.length(),
occupied_slots,
empty_slots: self.fingerprints.length() - occupied_slots,
maximum_fingerprint,
fingerprint_sum,
}
}
///|
pub fn BinaryFuseFilter::has_valid_shape(self : BinaryFuseFilter) -> Bool {
if self.key_count <= 0 ||
self.segment_length <= 0 ||
self.segment_count <= 0 ||
self.fingerprints.length() != (self.segment_count + 2) * self.segment_length ||
(self.fingerprint_bits != 8 && self.fingerprint_bits != 16) {
return false
}
let limit = if self.fingerprint_bits == 8 { 256 } else { 65_536 }
for value in self.fingerprints {
if value < 0 || value >= limit {
return false
}
}
true
}
///|
pub fn BinaryFuseFilter::candidate_xor(
self : BinaryFuseFilter,
hash : Int,
) -> Int? {
match self.candidate_locations(hash) {
None => None
Some(locations) =>
Some(
self.fingerprints[locations.first] ^
self.fingerprints[locations.second] ^
self.fingerprints[locations.third],
)
}
}
///|
pub fn BinaryFuseFilter::matches_fingerprint(
self : BinaryFuseFilter,
hash : Int,
) -> Bool {
match self.candidate_xor(hash) {
Some(value) =>
value == fingerprint(mix_hash(hash, self.seed), self.fingerprint_bits)
None => false
}
}