24 #ifndef PXR_TSL_ROBIN_GROWTH_POLICY_H
25 #define PXR_TSL_ROBIN_GROWTH_POLICY_H
43 #define PXR_TSL_RH_VERSION_MAJOR 1
46 #define PXR_TSL_RH_VERSION_MINOR 3
49 #define PXR_TSL_RH_VERSION_PATCH 0
52 #define pxr_tsl_rh_assert(expr) assert(expr)
54 #define pxr_tsl_rh_assert(expr) (static_cast<void>(0))
61 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || \
62 (defined(_MSC_VER) && defined(_CPPUNWIND))) && \
63 !defined(PXR_TSL_NO_EXCEPTIONS)
64 #define PXR_TSL_RH_THROW_OR_TERMINATE(ex, msg) throw ex(msg)
66 #define PXR_TSL_RH_NO_EXCEPTIONS
69 #define PXR_TSL_RH_THROW_OR_TERMINATE(ex, msg) \
71 std::cerr << msg << std::endl; \
75 #define PXR_TSL_RH_THROW_OR_TERMINATE(ex, msg) std::terminate()
79 #if defined(__GNUC__) || defined(__clang__)
80 #define PXR_TSL_RH_LIKELY(exp) (__builtin_expect(!!(exp), true))
82 #define PXR_TSL_RH_LIKELY(exp) (exp)
85 #define PXR_TSL_RH_UNUSED(x) static_cast<void>(x)
99 template <std::
size_t GrowthFactor>
113 "The hash table exceeds its maximum size.");
116 if (min_bucket_count_in_out > 0) {
117 min_bucket_count_in_out =
118 round_up_to_power_of_two(min_bucket_count_in_out);
119 m_mask = min_bucket_count_in_out - 1;
139 "The hash table exceeds its maximum size.");
142 return (
m_mask + 1) * GrowthFactor;
161 static std::size_t round_up_to_power_of_two(std::size_t
value) {
162 if (is_power_of_two(value)) {
171 for (std::size_t i = 1; i <
sizeof(std::size_t) * CHAR_BIT; i *= 2) {
178 static constexpr
bool is_power_of_two(std::size_t value) {
179 return value != 0 && (value & (value - 1)) == 0;
183 static_assert(is_power_of_two(GrowthFactor) && GrowthFactor >= 2,
184 "GrowthFactor must be a power of two >= 2.");
194 template <
class GrowthFactor = std::ratio<3, 2>>
200 "The hash table exceeds its maximum size.");
203 if (min_bucket_count_in_out > 0) {
204 m_mod = min_bucket_count_in_out;
217 "The hash table exceeds its maximum size.");
221 std::ceil(
double(m_mod) * REHASH_SIZE_MULTIPLICATION_FACTOR);
222 if (!std::isnormal(next_bucket_count)) {
224 "The hash table exceeds its maximum size.");
230 return std::size_t(next_bucket_count);
236 void clear() noexcept { m_mod = 1; }
239 static constexpr
double REHASH_SIZE_MULTIPLICATION_FACTOR =
240 1.0 * GrowthFactor::num / GrowthFactor::den;
241 static const std::size_t MAX_BUCKET_COUNT =
243 REHASH_SIZE_MULTIPLICATION_FACTOR));
245 static_assert(REHASH_SIZE_MULTIPLICATION_FACTOR >= 1.1,
246 "Growth factor should be >= 1.1.");
253 #if SIZE_MAX >= ULLONG_MAX
254 #define PXR_TSL_RH_NB_PRIMES 51
255 #elif SIZE_MAX >= ULONG_MAX
256 #define PXR_TSL_RH_NB_PRIMES 40
258 #define PXR_TSL_RH_NB_PRIMES 23
261 static constexpr
const std::array<std::size_t, PXR_TSL_RH_NB_PRIMES> PRIMES = {{
285 #if SIZE_MAX >= ULONG_MAX
304 #if SIZE_MAX >= ULLONG_MAX
319 template <
unsigned int IPrime>
320 static constexpr std::size_t
mod(std::size_t hash) {
321 return hash % PRIMES[IPrime];
327 static constexpr
const std::array<std::size_t (*)(std::size_t),
330 &mod<0>, &mod<1>, &mod<2>, &mod<3>, &mod<4>, &mod<5>,
331 &mod<6>, &mod<7>, &mod<8>, &mod<9>, &mod<10>, &mod<11>,
332 &mod<12>, &mod<13>, &mod<14>, &mod<15>, &mod<16>, &mod<17>,
333 &mod<18>, &mod<19>, &mod<20>, &mod<21>, &mod<22>,
334 #if SIZE_MAX >= ULONG_MAX
335 &mod<23>, &mod<24>, &mod<25>, &mod<26>, &mod<27>, &mod<28>,
336 &mod<29>, &mod<30>, &mod<31>, &mod<32>, &mod<33>, &mod<34>,
337 &mod<35>, &mod<36>, &mod<37>, &mod<38>, &mod<39>,
339 #if SIZE_MAX >= ULLONG_MAX
340 &mod<40>, &mod<41>, &mod<42>, &mod<43>, &mod<44>, &mod<45>,
341 &mod<46>, &mod<47>, &mod<48>, &mod<49>, &mod<50>,
377 auto it_prime = std::lower_bound(
378 detail::PRIMES.
begin(), detail::PRIMES.
end(), min_bucket_count_in_out);
379 if (it_prime == detail::PRIMES.
end()) {
381 "The hash table exceeds its maximum size.");
384 m_iprime =
static_cast<unsigned int>(
386 if (min_bucket_count_in_out > 0) {
387 min_bucket_count_in_out = *it_prime;
389 min_bucket_count_in_out = 0;
394 return detail::MOD_PRIME[m_iprime](hash);
398 if (m_iprime + 1 >= detail::PRIMES.
size()) {
400 "The hash table exceeds its maximum size.");
403 return detail::PRIMES[m_iprime + 1];
408 void clear() noexcept { m_iprime = 0; }
411 unsigned int m_iprime;
413 static_assert(std::numeric_limits<decltype(m_iprime)>::
max() >=
414 detail::PRIMES.
size(),
415 "The type of m_iprime is not big enough.");
std::size_t next_bucket_count() const
std::size_t max_bucket_count() const
std::size_t next_bucket_count() const
GLsizei const GLfloat * value
std::size_t bucket_for_hash(std::size_t hash) const noexcept
std::size_t bucket_for_hash(std::size_t hash) const noexcept
std::size_t next_bucket_count() const
#define PXR_TSL_RH_THROW_OR_TERMINATE(ex, msg)
std::size_t bucket_for_hash(std::size_t hash) const noexcept
power_of_two_growth_policy(std::size_t &min_bucket_count_in_out)
IMATH_HOSTDEVICE constexpr int ceil(T x) IMATH_NOEXCEPT
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
std::size_t max_bucket_count() const
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
#define PXR_NAMESPACE_CLOSE_SCOPE
prime_growth_policy(std::size_t &min_bucket_count_in_out)
std::size_t max_bucket_count() const
SIM_API const UT_StringHolder distance
mod_growth_policy(std::size_t &min_bucket_count_in_out)
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
#define PXR_TSL_RH_NB_PRIMES