sparse_hash_map/
growth_policy.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub struct LengthError;
20
21impl core::fmt::Display for LengthError {
22 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
23 f.write_str("the hash table exceeds its maximum size")
24 }
25}
26
27impl std::error::Error for LengthError {}
28
29pub trait GrowthPolicy: Clone {
36 fn new(min_bucket_count: usize) -> Result<(Self, usize), LengthError>;
45
46 fn bucket_for_hash(&self, hash: usize) -> usize;
48
49 fn next_bucket_count(&self) -> Result<usize, LengthError>;
53
54 fn max_bucket_count(&self) -> usize;
56
57 fn clear(&mut self);
59
60 fn is_power_of_two() -> bool {
64 false
65 }
66}
67
68use crate::util::{is_power_of_two, round_up_to_power_of_two};
69
70#[derive(Clone)]
74pub struct PowerOfTwo<const FACTOR: usize = 2> {
75 mask: usize,
76}
77
78impl<const FACTOR: usize> GrowthPolicy for PowerOfTwo<FACTOR> {
79 fn new(min_bucket_count: usize) -> Result<(Self, usize), LengthError> {
80 assert!(
81 is_power_of_two(FACTOR) && FACTOR >= 2,
82 "growth factor must be a power of two >= 2"
83 );
84
85 let max = Self::max_bucket_count_static();
86 if min_bucket_count > max {
87 return Err(LengthError);
88 }
89
90 if min_bucket_count > 0 {
91 let rounded = round_up_to_power_of_two(min_bucket_count);
92 Ok((Self { mask: rounded - 1 }, rounded))
93 } else {
94 Ok((Self { mask: 0 }, 0))
95 }
96 }
97
98 #[inline]
99 fn bucket_for_hash(&self, hash: usize) -> usize {
100 hash & self.mask
101 }
102
103 fn next_bucket_count(&self) -> Result<usize, LengthError> {
104 if (self.mask + 1) > Self::max_bucket_count_static() / FACTOR {
105 return Err(LengthError);
106 }
107 Ok((self.mask + 1) * FACTOR)
108 }
109
110 fn max_bucket_count(&self) -> usize {
111 Self::max_bucket_count_static()
112 }
113
114 fn clear(&mut self) {
115 self.mask = 0;
116 }
117
118 fn is_power_of_two() -> bool {
119 true
120 }
121}
122
123impl<const FACTOR: usize> PowerOfTwo<FACTOR> {
124 #[inline]
125 fn max_bucket_count_static() -> usize {
126 (usize::MAX / 2) + 1
128 }
129}
130
131#[derive(Clone)]
135pub struct Mod<const NUM: usize = 3, const DEN: usize = 2> {
136 modulo: usize,
137}
138
139impl<const NUM: usize, const DEN: usize> Mod<NUM, DEN> {
140 #[inline]
141 fn factor() -> f64 {
142 NUM as f64 / DEN as f64
143 }
144
145 #[inline]
146 fn max_bucket_count_static() -> usize {
147 (usize::MAX as f64 / Self::factor()) as usize
148 }
149}
150
151impl<const NUM: usize, const DEN: usize> GrowthPolicy for Mod<NUM, DEN> {
152 fn new(min_bucket_count: usize) -> Result<(Self, usize), LengthError> {
153 assert!(DEN != 0, "growth factor denominator must be nonzero");
154 assert!(Self::factor() >= 1.1, "growth factor should be >= 1.1");
155
156 if min_bucket_count > Self::max_bucket_count_static() {
157 return Err(LengthError);
158 }
159
160 let modulo = if min_bucket_count > 0 {
161 min_bucket_count
162 } else {
163 1
164 };
165 Ok((Self { modulo }, min_bucket_count))
167 }
168
169 #[inline]
170 fn bucket_for_hash(&self, hash: usize) -> usize {
171 hash % self.modulo
172 }
173
174 fn next_bucket_count(&self) -> Result<usize, LengthError> {
175 let max = Self::max_bucket_count_static();
176 if self.modulo == max {
177 return Err(LengthError);
178 }
179
180 let next = (self.modulo as f64 * Self::factor()).ceil();
181 if !next.is_normal() {
182 return Err(LengthError);
183 }
184
185 if next > max as f64 {
186 Ok(max)
187 } else {
188 Ok(next as usize)
189 }
190 }
191
192 fn max_bucket_count(&self) -> usize {
193 Self::max_bucket_count_static()
194 }
195
196 fn clear(&mut self) {
197 self.modulo = 1;
198 }
199}
200
201#[cfg(test)]
202mod tests {
203 use super::{GrowthPolicy, Mod};
204
205 #[test]
206 #[should_panic(expected = "growth factor denominator must be nonzero")]
207 fn mod_policy_rejects_zero_denominator() {
208 let _ = Mod::<2, 0>::new(0);
209 }
210}
211
212pub const PRIMES_TABLE: [usize; 40] = [
217 1, 5, 17, 29, 37, 53, 67, 79, 97, 131, 193, 257, 389, 521, 769, 1031, 1543, 2053, 3079, 6151,
218 12289, 24593, 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469, 12582917,
219 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741, 3221225473,
220 4294967291,
221];
222
223#[derive(Clone)]
229pub struct Prime {
230 iprime: usize,
231}
232
233impl GrowthPolicy for Prime {
234 fn new(min_bucket_count: usize) -> Result<(Self, usize), LengthError> {
235 let iprime = PRIMES_TABLE.partition_point(|&p| p < min_bucket_count);
237 if iprime == PRIMES_TABLE.len() {
238 return Err(LengthError);
239 }
240
241 let settled = if min_bucket_count > 0 {
242 PRIMES_TABLE[iprime]
243 } else {
244 0
245 };
246 Ok((Self { iprime }, settled))
247 }
248
249 #[inline]
250 fn bucket_for_hash(&self, hash: usize) -> usize {
251 hash % PRIMES_TABLE[self.iprime]
252 }
253
254 fn next_bucket_count(&self) -> Result<usize, LengthError> {
255 if self.iprime + 1 >= PRIMES_TABLE.len() {
256 return Err(LengthError);
257 }
258 Ok(PRIMES_TABLE[self.iprime + 1])
259 }
260
261 fn max_bucket_count(&self) -> usize {
262 PRIMES_TABLE[PRIMES_TABLE.len() - 1]
263 }
264
265 fn clear(&mut self) {
266 self.iprime = 0;
267 }
268}