24 #ifndef TSL_ROBIN_GROWTH_POLICY_H
25 #define TSL_ROBIN_GROWTH_POLICY_H
40 #define TSL_RH_VERSION_MAJOR 1
43 #define TSL_RH_VERSION_MINOR 3
46 #define TSL_RH_VERSION_PATCH 0
49 #define tsl_rh_assert(expr) assert(expr)
51 #define tsl_rh_assert(expr) (static_cast<void>(0))
58 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || \
59 (defined(_MSC_VER) && defined(_CPPUNWIND))) && \
60 !defined(TSL_NO_EXCEPTIONS)
61 #define TSL_RH_THROW_OR_TERMINATE(ex, msg) throw ex(msg)
63 #define TSL_RH_NO_EXCEPTIONS
66 #define TSL_RH_THROW_OR_TERMINATE(ex, msg) \
68 std::cerr << msg << std::endl; \
72 #define TSL_RH_THROW_OR_TERMINATE(ex, msg) std::terminate()
76 #if defined(__GNUC__) || defined(__clang__)
77 #define TSL_RH_LIKELY(exp) (__builtin_expect(!!(exp), true))
79 #define TSL_RH_LIKELY(exp) (exp)
82 #define TSL_RH_UNUSED(x) static_cast<void>(x)
94 template <std::
size_t GrowthFactor>
108 "The hash table exceeds its maximum size.");
111 if (min_bucket_count_in_out > 0) {
112 min_bucket_count_in_out =
114 m_mask = min_bucket_count_in_out - 1;
134 "The hash table exceeds its maximum size.");
137 return (
m_mask + 1) * GrowthFactor;
145 return (std::numeric_limits<std::size_t>::max() / 2) + 1;
166 for (std::size_t i = 1; i <
sizeof(std::size_t) * CHAR_BIT; i *= 2) {
174 return value != 0 && (value & (value - 1)) == 0;
179 "GrowthFactor must be a power of two >= 2.");
189 template <
class GrowthFactor = std::ratio<3, 2>>
195 "The hash table exceeds its maximum size.");
198 if (min_bucket_count_in_out > 0) {
199 m_mod = min_bucket_count_in_out;
212 "The hash table exceeds its maximum size.");
219 "The hash table exceeds its maximum size.");
235 1.0 * GrowthFactor::num / GrowthFactor::den;
237 std::size_t(
double(std::numeric_limits<std::size_t>::max() /
241 "Growth factor should be >= 1.1.");
248 #if SIZE_MAX >= ULLONG_MAX
249 #define TSL_RH_NB_PRIMES 51
250 #elif SIZE_MAX >= ULONG_MAX
251 #define TSL_RH_NB_PRIMES 40
253 #define TSL_RH_NB_PRIMES 23
256 static constexpr
const std::array<std::size_t, TSL_RH_NB_PRIMES>
PRIMES = {{
280 #if SIZE_MAX >= ULONG_MAX
299 #if SIZE_MAX >= ULLONG_MAX
314 template <
unsigned int IPrime>
315 static constexpr std::size_t
mod(std::size_t hash) {
316 return hash %
PRIMES[IPrime];
322 static constexpr
const std::array<std::size_t (*)(std::size_t),
325 &mod<0>, &mod<1>, &mod<2>, &mod<3>, &mod<4>, &mod<5>,
326 &mod<6>, &mod<7>, &mod<8>, &mod<9>, &mod<10>, &mod<11>,
327 &mod<12>, &mod<13>, &mod<14>, &mod<15>, &mod<16>, &mod<17>,
328 &mod<18>, &mod<19>, &mod<20>, &mod<21>, &mod<22>,
329 #if SIZE_MAX >= ULONG_MAX
330 &mod<23>, &mod<24>, &mod<25>, &mod<26>, &mod<27>, &mod<28>,
331 &mod<29>, &mod<30>, &mod<31>, &mod<32>, &mod<33>, &mod<34>,
332 &mod<35>, &mod<36>, &mod<37>, &mod<38>, &mod<39>,
334 #if SIZE_MAX >= ULLONG_MAX
335 &mod<40>, &mod<41>, &mod<42>, &mod<43>, &mod<44>, &mod<45>,
336 &mod<46>, &mod<47>, &mod<48>, &mod<49>, &mod<50>,
372 auto it_prime = std::lower_bound(
376 "The hash table exceeds its maximum size.");
379 m_iprime =
static_cast<unsigned int>(
381 if (min_bucket_count_in_out > 0) {
382 min_bucket_count_in_out = *it_prime;
384 min_bucket_count_in_out = 0;
395 "The hash table exceeds its maximum size.");
408 static_assert(std::numeric_limits<decltype(
m_iprime)>::max() >=
410 "The type of m_iprime is not big enough.");