File indexing completed on 2025-01-31 10:03:45
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_UNORDERED_DETAIL_PRIME_FMOD_HPP
0008 #define BOOST_UNORDERED_DETAIL_PRIME_FMOD_HPP
0009
0010 #include <boost/unordered/detail/narrow_cast.hpp>
0011
0012 #include <boost/config.hpp>
0013 #include <boost/cstdint.hpp>
0014
0015 #include <climits>
0016 #include <cstddef>
0017
0018 #if defined(SIZE_MAX)
0019 #if ((((SIZE_MAX >> 16) >> 16) >> 16) >> 15) != 0
0020 #define BOOST_UNORDERED_FCA_HAS_64B_SIZE_T
0021 #endif
0022 #elif defined(UINTPTR_MAX)
0023 #if ((((UINTPTR_MAX >> 16) >> 16) >> 16) >> 15) != 0
0024 #define BOOST_UNORDERED_FCA_HAS_64B_SIZE_T
0025 #endif
0026 #endif
0027
0028 #if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T) && defined(_MSC_VER)
0029 #include <intrin.h>
0030 #endif
0031
0032 namespace boost {
0033 namespace unordered {
0034 namespace detail {
0035 template <class = void> struct prime_fmod_size
0036 {
0037 constexpr static std::size_t const sizes[] = {13ul, 29ul, 53ul, 97ul,
0038 193ul, 389ul, 769ul, 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
0039 49157ul, 98317ul, 196613ul, 393241ul, 786433ul, 1572869ul, 3145739ul,
0040 6291469ul, 12582917ul, 25165843ul, 50331653ul, 100663319ul,
0041 201326611ul, 402653189ul, 805306457ul, 1610612741ul, 3221225473ul,
0042 #if !defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
0043 4294967291ul
0044 #else
0045 6442450939ull, 12884901893ull, 25769803751ull, 51539607551ull,
0046 103079215111ull, 206158430209ull, 412316860441ull, 824633720831ull,
0047 1649267441651ull
0048 #endif
0049 };
0050
0051 constexpr static std::size_t const sizes_len =
0052 sizeof(sizes) / sizeof(sizes[0]);
0053
0054 #if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
0055 constexpr static boost::uint64_t const inv_sizes32[] = {
0056 1418980313362273202ull, 636094623231363849ull, 348051774975651918ull,
0057 190172619316593316ull, 95578984837873325ull, 47420935922132524ull,
0058 23987963684927896ull, 11955116055547344ull, 5991147799191151ull,
0059 2998982941588287ull, 1501077717772769ull, 750081082979285ull,
0060 375261795343686ull, 187625172388393ull, 93822606204624ull,
0061 46909513691883ull, 23456218233098ull, 11728086747027ull,
0062 5864041509391ull, 2932024948977ull, 1466014921160ull, 733007198436ull,
0063 366503839517ull, 183251896093ull, 91625960335ull, 45812983922ull,
0064 22906489714ull, 11453246088ull, 5726623060ull};
0065
0066 constexpr static std::size_t const inv_sizes32_len =
0067 sizeof(inv_sizes32) / sizeof(inv_sizes32[0]);
0068 #endif
0069
0070 template <std::size_t SizeIndex, std::size_t Size = sizes[SizeIndex]>
0071 static std::size_t position(std::size_t hash)
0072 {
0073 return hash % Size;
0074 }
0075
0076 constexpr static std::size_t (*positions[])(std::size_t) = {
0077 #if !defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
0078 position<0, sizes[0]>,
0079 position<1, sizes[1]>,
0080 position<2, sizes[2]>,
0081 position<3, sizes[3]>,
0082 position<4, sizes[4]>,
0083 position<5, sizes[5]>,
0084 position<6, sizes[6]>,
0085 position<7, sizes[7]>,
0086 position<8, sizes[8]>,
0087 position<9, sizes[9]>,
0088 position<10, sizes[10]>,
0089 position<11, sizes[11]>,
0090 position<12, sizes[12]>,
0091 position<13, sizes[13]>,
0092 position<14, sizes[14]>,
0093 position<15, sizes[15]>,
0094 position<16, sizes[16]>,
0095 position<17, sizes[17]>,
0096 position<18, sizes[18]>,
0097 position<19, sizes[19]>,
0098 position<20, sizes[20]>,
0099 position<21, sizes[21]>,
0100 position<22, sizes[22]>,
0101 position<23, sizes[23]>,
0102 position<24, sizes[24]>,
0103 position<25, sizes[25]>,
0104 position<26, sizes[26]>,
0105 position<27, sizes[27]>,
0106 position<28, sizes[28]>,
0107 position<29, sizes[29]>,
0108 #else
0109 position<29, sizes[29]>,
0110 position<30, sizes[30]>,
0111 position<31, sizes[31]>,
0112 position<32, sizes[32]>,
0113 position<33, sizes[33]>,
0114 position<34, sizes[34]>,
0115 position<35, sizes[35]>,
0116 position<36, sizes[36]>,
0117 position<37, sizes[37]>,
0118 #endif
0119 };
0120
0121 static inline std::size_t size_index(std::size_t n)
0122 {
0123 std::size_t i = 0;
0124 for (; i < (sizes_len - 1); ++i) {
0125 if (sizes[i] >= n) {
0126 break;
0127 }
0128 }
0129 return i;
0130 }
0131
0132 static inline std::size_t size(std::size_t size_index)
0133 {
0134 return sizes[size_index];
0135 }
0136
0137 #if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147 static inline boost::uint64_t get_remainder(
0148 boost::uint64_t fractional, boost::uint32_t d)
0149 {
0150 #if defined(_MSC_VER)
0151
0152
0153 return __umulh(fractional, d);
0154 #elif defined(BOOST_HAS_INT128)
0155 return static_cast<boost::uint64_t>(
0156 ((boost::uint128_type)fractional * d) >> 64);
0157 #else
0158
0159
0160
0161 boost::uint64_t r1 = (fractional & UINT32_MAX) * d;
0162 boost::uint64_t r2 = (fractional >> 32) * d;
0163 r2 += r1 >> 32;
0164 return r2 >> 32;
0165 #endif
0166 }
0167
0168 static inline boost::uint32_t fast_modulo(
0169 boost::uint32_t a, boost::uint64_t M, boost::uint32_t d)
0170 {
0171 boost::uint64_t fractional = M * a;
0172 return (boost::uint32_t)(get_remainder(fractional, d));
0173 }
0174 #endif
0175
0176 static inline std::size_t position(
0177 std::size_t hash, std::size_t size_index)
0178 {
0179 #if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
0180 std::size_t sizes_under_32bit = inv_sizes32_len;
0181 if (BOOST_LIKELY(size_index < sizes_under_32bit)) {
0182 return fast_modulo(narrow_cast<boost::uint32_t>(hash) +
0183 narrow_cast<boost::uint32_t>(hash >> 32),
0184 inv_sizes32[size_index], boost::uint32_t(sizes[size_index]));
0185 } else {
0186 return positions[size_index - sizes_under_32bit](hash);
0187 }
0188 #else
0189 return positions[size_index](hash);
0190 #endif
0191 }
0192 };
0193
0194 #if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
0195
0196
0197
0198
0199
0200 template <class T> constexpr std::size_t prime_fmod_size<T>::sizes[];
0201
0202 #if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
0203 template <class T>
0204 constexpr boost::uint64_t prime_fmod_size<T>::inv_sizes32[];
0205 #endif
0206
0207 template <class T>
0208 constexpr std::size_t (*prime_fmod_size<T>::positions[])(std::size_t);
0209 #endif
0210 }
0211 }
0212 }
0213
0214 #endif