24 #ifndef TSL_ROBIN_GROWTH_POLICY_H 25 #define TSL_ROBIN_GROWTH_POLICY_H 40 # define tsl_rh_assert(expr) assert(expr) 42 # define tsl_rh_assert(expr) (static_cast<void>(0
)) 49 #if (defined(__cpp_exceptions
) || defined(__EXCEPTIONS
) || (defined (_MSC_VER) && defined (_CPPUNWIND))) && !defined(TSL_NO_EXCEPTIONS) 50 # define TSL_RH_THROW_OR_TERMINATE(ex, msg) throw ex(msg) 53 # define TSL_RH_THROW_OR_TERMINATE(ex, msg) std::terminate() 56 # define TSL_RH_THROW_OR_TERMINATE(ex, msg) do { std::fprintf(stderr, msg); std::terminate(); } while(0
) 61 #if defined(__GNUC__
) || defined(__clang__
) 62 # define TSL_RH_LIKELY(exp) (__builtin_expect(!!(exp), true)) 64 # define TSL_RH_LIKELY(exp) (exp) 77 template<std::size_t GrowthFactor>
92 if(min_bucket_count_in_out > 0) {
93 min_bucket_count_in_out = round_up_to_power_of_two(min_bucket_count_in_out);
94 m_mask = min_bucket_count_in_out - 1;
117 return (
m_mask + 1) * GrowthFactor;
125 return (std::numeric_limits<std::size_t>::max() / 2) + 1;
137 static std::size_t round_up_to_power_of_two(std::size_t value) {
138 if(is_power_of_two(value)) {
147 for(std::size_t i = 1; i <
sizeof(std::size_t) * CHAR_BIT; i *= 2) {
154 static constexpr bool is_power_of_two(std::size_t value) {
155 return value != 0 && (value & (value - 1)) == 0;
159 static_assert(is_power_of_two(GrowthFactor) && GrowthFactor >= 2,
"GrowthFactor must be a power of two >= 2.");
169 template<
class GrowthFactor = std::ratio<3, 2>>
177 if(min_bucket_count_in_out > 0) {
178 m_mod = min_bucket_count_in_out;
194 const double next_bucket_count = std::ceil(
double(m_mod) * REHASH_SIZE_MULTIPLICATION_FACTOR);
195 if(!std::isnormal(next_bucket_count)) {
203 return std::size_t(next_bucket_count);
208 return MAX_BUCKET_COUNT;
216 static constexpr double REHASH_SIZE_MULTIPLICATION_FACTOR = 1.0 * GrowthFactor::num / GrowthFactor::den;
217 static const std::size_t MAX_BUCKET_COUNT =
219 std::numeric_limits<std::size_t>::max() / REHASH_SIZE_MULTIPLICATION_FACTOR
222 static_assert(REHASH_SIZE_MULTIPLICATION_FACTOR >= 1.1,
"Growth factor should be >= 1.1.");
231 static constexpr const std::array<std::size_t, 40> PRIMES = {{
232 1ul, 5ul, 17ul, 29ul, 37ul, 53ul, 67ul, 79ul, 97ul, 131ul, 193ul, 257ul, 389ul, 521ul, 769ul, 1031ul,
233 1543ul, 2053ul, 3079ul, 6151ul, 12289ul, 24593ul, 49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
234 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul, 50331653ul, 100663319ul, 201326611ul,
235 402653189ul, 805306457ul, 1610612741ul, 3221225473ul, 4294967291ul
238 template<
unsigned int IPrime>
239 static constexpr std::size_t mod(std::size_t hash) {
return hash % PRIMES[IPrime]; }
243 static constexpr const std::array<std::size_t(*)(std::size_t), 40> MOD_PRIME = {{
244 &mod<0>, &mod<1>, &mod<2>, &mod<3>, &mod<4>, &mod<5>, &mod<6>, &mod<7>, &mod<8>, &mod<9>, &mod<10>,
245 &mod<11>, &mod<12>, &mod<13>, &mod<14>, &mod<15>, &mod<16>, &mod<17>, &mod<18>, &mod<19>, &mod<20>,
246 &mod<21>, &mod<22>, &mod<23>, &mod<24>, &mod<25>, &mod<26>, &mod<27>, &mod<28>, &mod<29>, &mod<30>,
247 &mod<31>, &mod<32>, &mod<33>, &mod<34>, &mod<35>, &mod<36>, &mod<37> , &mod<38>, &mod<39>
279 auto it_prime = std::lower_bound(
detail::PRIMES.begin(),
280 detail::PRIMES.end(), min_bucket_count_in_out);
281 if(it_prime ==
detail::PRIMES.end()) {
285 m_iprime =
static_cast<
unsigned int>(std::distance(
detail::PRIMES.begin(), it_prime));
286 if(min_bucket_count_in_out > 0) {
287 min_bucket_count_in_out = *it_prime;
290 min_bucket_count_in_out = 0;
295 return detail::MOD_PRIME[m_iprime](hash);
299 if(m_iprime + 1 >=
detail::PRIMES.size()) {
303 return detail::PRIMES[m_iprime + 1];
307 return detail::PRIMES.back();
315 unsigned int m_iprime;
317 static_assert(std::numeric_limits<
decltype(m_iprime)>::max() >=
detail::PRIMES.size(),
318 "The type of m_iprime is not big enough.");
std::size_t bucket_for_hash(std::size_t hash) const noexcept
Definition: robin_growth_policy.h:105
Definition: robin_growth_policy.h:69
std::size_t next_bucket_count() const
Definition: robin_growth_policy.h:189
std::size_t bucket_for_hash(std::size_t hash) const noexcept
Definition: robin_growth_policy.h:294
void clear() noexcept
Definition: robin_growth_policy.h:211
Definition: robin_growth_policy.h:68
std::size_t max_bucket_count() const
Definition: robin_growth_policy.h:306
mod_growth_policy(std::size_t &min_bucket_count_in_out)
Definition: robin_growth_policy.h:172
void clear() noexcept
Definition: robin_growth_policy.h:132
std::size_t max_bucket_count() const
Definition: robin_growth_policy.h:123
std::size_t next_bucket_count() const
Definition: robin_growth_policy.h:298
Definition: robin_growth_policy.h:170
std::size_t m_mask
Definition: robin_growth_policy.h:159
void clear() noexcept
Definition: robin_growth_policy.h:310
prime_growth_policy(std::size_t &min_bucket_count_in_out)
Definition: robin_growth_policy.h:278
#define TSL_RH_THROW_OR_TERMINATE(ex, msg)
Definition: robin_growth_policy.h:56
power_of_two_growth_policy(std::size_t &min_bucket_count_in_out)
Definition: robin_growth_policy.h:87
std::size_t max_bucket_count() const
Definition: robin_growth_policy.h:207
Definition: robin_growth_policy.h:276
std::size_t next_bucket_count() const
Definition: robin_growth_policy.h:112
Definition: robin_growth_policy.h:229
std::size_t bucket_for_hash(std::size_t hash) const noexcept
Definition: robin_growth_policy.h:185
Definition: robin_growth_policy.h:78