// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard. // Copyright (C) 2005-2009 Daniel James // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_UNORDERED_DETAIL_HASH_TABLE_HPP_INCLUDED #define BOOST_UNORDERED_DETAIL_HASH_TABLE_HPP_INCLUDED #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif #include #if !defined(BOOST_UNORDERED_EMPLACE_LIMIT) #define BOOST_UNORDERED_EMPLACE_LIMIT 5 #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if !(defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)) #include #include #include #define BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \ BOOST_PP_ENUM_PARAMS_Z(z, n, typename Arg) #define BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \ BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, const& arg) #define BOOST_UNORDERED_CALL_PARAMS(z, n) \ BOOST_PP_ENUM_PARAMS_Z(z, n, arg) #endif #if BOOST_WORKAROUND(__BORLANDC__, <= 0x0582) #define BOOST_UNORDERED_BORLAND_BOOL(x) (bool)(x) #else #define BOOST_UNORDERED_BORLAND_BOOL(x) x #endif #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) #define BOOST_UNORDERED_MSVC_RESET_PTR(x) unordered_detail::reset(x) #else #define BOOST_UNORDERED_MSVC_RESET_PTR(x) #endif namespace boost { namespace unordered_detail { template struct type_wrapper {}; static const std::size_t default_initial_bucket_count = 50; static const float minimum_max_load_factor = 1e-3f; inline std::size_t double_to_size_t(double f) { return f >= static_cast((std::numeric_limits::max)()) ? (std::numeric_limits::max)() : static_cast(f); } // prime number list, accessor template struct prime_list_template { static std::size_t const value[]; static std::ptrdiff_t const length; }; #define BOOST_UNORDERED_PRIMES \ (5ul)(11ul)(17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \ (97ul)(131ul)(193ul)(257ul)(389ul)(521ul)(769ul) \ (1031ul)(1543ul)(2053ul)(3079ul)(6151ul)(12289ul)(24593ul) \ (49157ul)(98317ul)(196613ul)(393241ul)(786433ul) \ (1572869ul)(3145739ul)(6291469ul)(12582917ul)(25165843ul) \ (50331653ul)(100663319ul)(201326611ul)(402653189ul)(805306457ul) \ (1610612741ul)(3221225473ul)(4294967291ul) template std::size_t const prime_list_template::value[] = { BOOST_PP_SEQ_ENUM(BOOST_UNORDERED_PRIMES) }; template std::ptrdiff_t const prime_list_template::length = BOOST_PP_SEQ_SIZE(BOOST_UNORDERED_PRIMES); #undef BOOST_UNORDERED_PRIMES typedef prime_list_template prime_list; // no throw inline std::size_t next_prime(std::size_t n) { std::size_t const* const prime_list_begin = prime_list::value; std::size_t const* const prime_list_end = prime_list_begin + prime_list::length; std::size_t const* bound = std::lower_bound(prime_list_begin, prime_list_end, n); if(bound == prime_list_end) bound--; return *bound; } // no throw inline std::size_t prev_prime(std::size_t n) { std::size_t const* const prime_list_begin = prime_list::value; std::size_t const* const prime_list_end = prime_list_begin + prime_list::length; std::size_t const* bound = std::upper_bound(prime_list_begin,prime_list_end, n); if(bound != prime_list_begin) bound--; return *bound; } // Controls how many buckets are allocated and which buckets hash // values map to. Does not contain the buckets themselves, or ever // deal with them directly. struct bucket_manager { std::size_t bucket_count_; bucket_manager() : bucket_count_(0) {} explicit bucket_manager(std::size_t n) : bucket_count_(next_prime(n)) {} std::size_t bucket_count() const { return bucket_count_; } std::size_t bucket_from_hash(std::size_t hashed) const { return hashed % bucket_count_; } std::size_t max_bucket_count(std::size_t max_size) const { return prev_prime(max_size); } }; // pair_cast - used to convert between pair types. template inline std::pair pair_cast(std::pair const& x) { return std::pair(Dst1(x.first), Dst2(x.second)); } #if !defined(BOOST_NO_STD_DISTANCE) using ::std::distance; #else template inline std::size_t distance(ForwardIterator i, ForwardIterator j) { std::size_t x; std::distance(i, j, x); return x; } #endif struct move_tag {}; // Both hasher and key_equal's copy/assign can throw so double // buffering is used to copy them. template struct buffered_functions { typedef Hash hasher; typedef Pred key_equal; class functions { std::pair functions_; public: functions(hasher const& h, key_equal const& k) : functions_(h, k) {} hasher const& hash_function() const { return functions_.first; } key_equal const& key_eq() const { return functions_.second; } }; typedef functions buffered_functions::*functions_ptr; buffered_functions(hasher const& h, key_equal const& k) : func1_(h, k), func2_(h, k), func_(&buffered_functions::func1_) {} // This copies the given function objects into the currently unused // function objects and returns a pointer, that func_ can later be // set to, to commit the change. // // Strong exception safety (since only usued function objects are // changed). functions_ptr buffer(buffered_functions const& x) { functions_ptr ptr = func_ == &buffered_functions::func1_ ? &buffered_functions::func2_ : &buffered_functions::func1_; this->*ptr = x.current(); return ptr; } void set(functions_ptr ptr) { BOOST_ASSERT(ptr != func_); func_ = ptr; } functions const& current() const { return this->*func_; } private: functions func1_; functions func2_; functions_ptr func_; // The currently active functions. }; #if defined(BOOST_MSVC) # define BOOST_UNORDERED_DESTRUCT(x, type) (x)->~type(); #else # define BOOST_UNORDERED_DESTRUCT(x, type) boost::unordered_detail::destroy(x) template void destroy(T* x) { x->~T(); } #endif } } #define BOOST_UNORDERED_EQUIVALENT_KEYS 1 #include #undef BOOST_UNORDERED_EQUIVALENT_KEYS #define BOOST_UNORDERED_EQUIVALENT_KEYS 0 #include #undef BOOST_UNORDERED_EQUIVALENT_KEYS namespace boost { namespace unordered_detail { class iterator_access { public: template static BOOST_DEDUCED_TYPENAME Iterator::base const& get(Iterator const& it) { return it.base_; } }; template class hash_types_unique_keys { public: typedef BOOST_DEDUCED_TYPENAME boost::unordered_detail::rebind_wrap::type value_allocator; typedef hash_table_unique_keys hash_table; typedef hash_table_data_unique_keys data; typedef BOOST_DEDUCED_TYPENAME data::iterator_base iterator_base; typedef hash_const_local_iterator_unique_keys const_local_iterator; typedef hash_local_iterator_unique_keys local_iterator; typedef hash_const_iterator_unique_keys const_iterator; typedef hash_iterator_unique_keys iterator; typedef BOOST_DEDUCED_TYPENAME data::size_type size_type; typedef std::ptrdiff_t difference_type; }; template class hash_types_equivalent_keys { public: typedef BOOST_DEDUCED_TYPENAME boost::unordered_detail::rebind_wrap::type value_allocator; typedef hash_table_equivalent_keys hash_table; typedef hash_table_data_equivalent_keys data; typedef BOOST_DEDUCED_TYPENAME data::iterator_base iterator_base; typedef hash_const_local_iterator_equivalent_keys const_local_iterator; typedef hash_local_iterator_equivalent_keys local_iterator; typedef hash_const_iterator_equivalent_keys const_iterator; typedef hash_iterator_equivalent_keys iterator; typedef BOOST_DEDUCED_TYPENAME data::size_type size_type; typedef std::ptrdiff_t difference_type; }; } // namespace boost::unordered_detail } // namespace boost #undef BOOST_UNORDERED_BORLAND_BOOL #undef BOOST_UNORDERED_MSVC_RESET_PTR #endif // BOOST_UNORDERED_DETAIL_HASH_TABLE_HPP_INCLUDED