1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Provides hashing utilities to split a hash value into quotient (slot index)
// and remainder (fingerprint) components for the quotient filter.
use xxh3_64;
/// Generates a 64-bit hash from the given data using xxHash3.
///
/// xxHash3 is a fast, non-cryptographic hash function suitable for
/// filter applications.
///
/// # Arguments
///
/// * `data` - Byte slice to hash
///
/// # Returns
///
/// 64-bit hash value
///
/// # Complexity
///
/// O(n) where n is length of data
/// Splits a hash into quotient (slot index) and remainder (fingerprint) components.
///
/// Given a 64-bit hash, extracts:
/// - Lower `q_bits` bits as quotient (canonical slot address)
/// - Next `r_bits` bits as remainder (fingerprint to store)
///
/// # Arguments
///
/// * `hash` - Input 64-bit hash value
/// * `q_bits` - Number of bits to use for quotient (typically log2(num_slots))
/// * `r_bits` - Number of bits to use for remainder (fingerprint width)
///
/// # Returns
///
/// Tuple of `(quotient, remainder)`
///
/// # Example
///
/// ```
/// use aleph_filter::hash::split_hash;
/// let hash = 0x123456789ABCDEF0u64;
/// let (q, r) = split_hash(hash, 16, 32); // 16-bit quotient, 32-bit remainder
/// ```
/// Combines quotient and remainder back into a single hash value.
///
/// Inverse of `split_hash()`. Places quotient in lower bits,
/// remainder in upper bits.
///
/// # Arguments
///
/// * `quotient` - Slot index (lower bits)
/// * `remainder` - Fingerprint value (upper bits)
/// * `q_bits` - Number of quotient bits (for alignment)
///
/// # Returns
///
/// Combined 64-bit hash value
///
/// Calculates the number of quotient bits needed for a given slot count.
///
/// Computes ceil(log2(num_slots)), which is the minimum number of bits
/// needed to address all slots.
///
/// # Arguments
///
/// * `num_slots` - Number of slots in the filter
///
/// # Returns
///
/// Number of quotion bits (log2 of num_slots, rounded up)
///
/// # Example
///
/// ```
/// use aleph_filter::hash::quotient_bits_for_slots;
/// assert_eq!(quotient_bits_for_slots(8), 3); // 8 = 2^3
/// assert_eq!(quotient_bits_for_slots(10), 4); // 10 needs 4 bits
/// ```
/// Calculates the fingerprint width (in bits) required to achieve a target FPR.
///
/// Uses the relationship: `FPR = 2^(-fingerprint_bits)`
/// Therefore: `fingerprint_bits = ceil(-log2(FPR))`
///
/// # Arguments
///
/// * `fpr` - Desired false positive rate (e.g., 0.01 for 1%)
///
/// # Returns
///
/// Number of fingerprint bits needed
///
/// # Panics
///
/// If `fpr` is not in the range (0, 1).
///
/// # Example
///
/// ```
/// use aleph_filter::hash::fingerprint_bits_for_fpr;
/// assert_eq!(fingerprint_bits_for_fpr(0.01), 7); // 1% FPR needs ~7 bits
/// assert_eq!(fingerprint_bits_for_fpr(0.001), 10); // 0.1% FPR needs ~10 bits
/// ```