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!(Self::factor() >= 1.1, "growth factor should be >= 1.1");
154
155 if min_bucket_count > Self::max_bucket_count_static() {
156 return Err(LengthError);
157 }
158
159 let modulo = if min_bucket_count > 0 {
160 min_bucket_count
161 } else {
162 1
163 };
164 Ok((Self { modulo }, min_bucket_count))
166 }
167
168 #[inline]
169 fn bucket_for_hash(&self, hash: usize) -> usize {
170 hash % self.modulo
171 }
172
173 fn next_bucket_count(&self) -> Result<usize, LengthError> {
174 let max = Self::max_bucket_count_static();
175 if self.modulo == max {
176 return Err(LengthError);
177 }
178
179 let next = (self.modulo as f64 * Self::factor()).ceil();
180 if !next.is_normal() {
181 return Err(LengthError);
182 }
183
184 if next > max as f64 {
185 Ok(max)
186 } else {
187 Ok(next as usize)
188 }
189 }
190
191 fn max_bucket_count(&self) -> usize {
192 Self::max_bucket_count_static()
193 }
194
195 fn clear(&mut self) {
196 self.modulo = 1;
197 }
198}
199
200pub const PRIMES_TABLE: [usize; 40] = [
205 1, 5, 17, 29, 37, 53, 67, 79, 97, 131, 193, 257, 389, 521, 769, 1031, 1543, 2053, 3079, 6151,
206 12289, 24593, 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469, 12582917,
207 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741, 3221225473,
208 4294967291,
209];
210
211#[derive(Clone)]
217pub struct Prime {
218 iprime: usize,
219}
220
221impl GrowthPolicy for Prime {
222 fn new(min_bucket_count: usize) -> Result<(Self, usize), LengthError> {
223 let iprime = PRIMES_TABLE.partition_point(|&p| p < min_bucket_count);
225 if iprime == PRIMES_TABLE.len() {
226 return Err(LengthError);
227 }
228
229 let settled = if min_bucket_count > 0 {
230 PRIMES_TABLE[iprime]
231 } else {
232 0
233 };
234 Ok((Self { iprime }, settled))
235 }
236
237 #[inline]
238 fn bucket_for_hash(&self, hash: usize) -> usize {
239 hash % PRIMES_TABLE[self.iprime]
240 }
241
242 fn next_bucket_count(&self) -> Result<usize, LengthError> {
243 if self.iprime + 1 >= PRIMES_TABLE.len() {
244 return Err(LengthError);
245 }
246 Ok(PRIMES_TABLE[self.iprime + 1])
247 }
248
249 fn max_bucket_count(&self) -> usize {
250 PRIMES_TABLE[PRIMES_TABLE.len() - 1]
251 }
252
253 fn clear(&mut self) {
254 self.iprime = 0;
255 }
256}