forked from boostorg/unordered
Unordered: Hashing policy for 64 bit computers.
[SVN r77066]
This commit is contained in:
@ -18,6 +18,7 @@
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/swap.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
@ -29,7 +30,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
template <typename Types> struct table;
|
||||
template <typename NodePointer> struct bucket;
|
||||
struct ptr_bucket;
|
||||
template <typename A, typename Bucket, typename Node> struct buckets;
|
||||
template <typename A, typename Bucket, typename Node, typename Policy>
|
||||
struct buckets;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@ -179,12 +181,97 @@ namespace boost { namespace unordered { namespace detail {
|
||||
enum { extra_node = false };
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Hash Policy
|
||||
//
|
||||
// Don't really want buckets to derive from this, but will for now.
|
||||
|
||||
template <typename SizeT>
|
||||
struct prime_policy
|
||||
{
|
||||
template <typename Hash, typename T>
|
||||
static inline SizeT apply_hash(Hash const& hf, T const& x) {
|
||||
return hf(x);
|
||||
}
|
||||
|
||||
static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) {
|
||||
return hash % bucket_count;
|
||||
}
|
||||
|
||||
static inline SizeT new_bucket_count(SizeT min) {
|
||||
return boost::unordered::detail::next_prime(min);
|
||||
}
|
||||
|
||||
static inline SizeT prev_bucket_count(SizeT max) {
|
||||
return boost::unordered::detail::prev_prime(max);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename SizeT>
|
||||
struct mix64_policy
|
||||
{
|
||||
template <typename Hash, typename T>
|
||||
static inline SizeT apply_hash(Hash const& hf, T const& x) {
|
||||
SizeT key = hf(x);
|
||||
key = (~key) + (key << 21); // key = (key << 21) - key - 1;
|
||||
key = key ^ (key >> 24);
|
||||
key = (key + (key << 3)) + (key << 8); // key * 265
|
||||
key = key ^ (key >> 14);
|
||||
key = (key + (key << 2)) + (key << 4); // key * 21
|
||||
key = key ^ (key >> 28);
|
||||
key = key + (key << 31);
|
||||
return key;
|
||||
}
|
||||
|
||||
static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) {
|
||||
return hash & (bucket_count - 1);
|
||||
}
|
||||
|
||||
static inline SizeT new_bucket_count(SizeT min) {
|
||||
if (min <= 4) return 4;
|
||||
--min;
|
||||
min |= min >> 1;
|
||||
min |= min >> 2;
|
||||
min |= min >> 4;
|
||||
min |= min >> 8;
|
||||
min |= min >> 16;
|
||||
min |= min >> 32;
|
||||
return min + 1;
|
||||
}
|
||||
|
||||
static inline SizeT prev_bucket_count(SizeT max) {
|
||||
max |= max >> 1;
|
||||
max |= max >> 2;
|
||||
max |= max >> 4;
|
||||
max |= max >> 8;
|
||||
max |= max >> 16;
|
||||
max |= max >> 32;
|
||||
return (max >> 1) + 1;
|
||||
}
|
||||
};
|
||||
|
||||
template <int digits, int radix>
|
||||
struct pick_policy_impl {
|
||||
typedef prime_policy<std::size_t> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct pick_policy_impl<64, 2> {
|
||||
typedef mix64_policy<std::size_t> type;
|
||||
};
|
||||
|
||||
struct pick_policy :
|
||||
pick_policy_impl<
|
||||
std::numeric_limits<std::size_t>::digits,
|
||||
std::numeric_limits<std::size_t>::radix> {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Buckets
|
||||
|
||||
template <typename A, typename Bucket, typename Node>
|
||||
struct buckets
|
||||
template <typename A, typename Bucket, typename Node, typename Policy>
|
||||
struct buckets : Policy
|
||||
{
|
||||
private:
|
||||
buckets(buckets const&);
|
||||
@ -247,7 +334,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
std::size_t max_bucket_count() const
|
||||
{
|
||||
// -1 to account for the start bucket.
|
||||
return boost::unordered::detail::prev_prime(
|
||||
return this->prev_bucket_count(
|
||||
bucket_allocator_traits::max_size(bucket_alloc()) - 1);
|
||||
}
|
||||
|
||||
@ -292,7 +379,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if (!ptr) return 0;
|
||||
|
||||
std::size_t count = 0;
|
||||
while(ptr && ptr->hash_ % this->bucket_count_ == index)
|
||||
while(ptr && this->to_bucket(this->bucket_count_, ptr->hash_) == index)
|
||||
{
|
||||
++count;
|
||||
ptr = static_cast<node_pointer>(ptr->next_);
|
||||
@ -487,7 +574,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
else
|
||||
{
|
||||
bucket_pointer next_bucket = this->get_bucket(
|
||||
next->hash_ % this->bucket_count_);
|
||||
this->to_bucket(this->bucket_count_, next->hash_));
|
||||
|
||||
if (next_bucket != bucket)
|
||||
{
|
||||
@ -513,7 +600,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if (n == end) return;
|
||||
|
||||
std::size_t new_bucket_index =
|
||||
n->hash_ % this->bucket_count_;
|
||||
this->to_bucket(this->bucket_count_, n->hash_);
|
||||
if (bucket_index != new_bucket_index) {
|
||||
bucket_index = new_bucket_index;
|
||||
break;
|
||||
@ -529,7 +616,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if (n == end) break;
|
||||
|
||||
std::size_t new_bucket_index =
|
||||
n->hash_ % this->bucket_count_;
|
||||
this->to_bucket(this->bucket_count_, n->hash_);
|
||||
if (bucket_index != new_bucket_index) {
|
||||
bucket_index = new_bucket_index;
|
||||
this->get_bucket(bucket_index)->next_ = previous_pointer();
|
||||
@ -538,7 +625,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
// Finally fix the bucket containing the trailing node.
|
||||
if (n) {
|
||||
this->get_bucket(n->hash_ % this->bucket_count_)->next_
|
||||
this->get_bucket(this->to_bucket(this->bucket_count_, n->hash_))->next_
|
||||
= prev;
|
||||
}
|
||||
}
|
||||
|
@ -136,6 +136,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
typedef boost::unordered::detail::grouped_table_impl<types> table;
|
||||
typedef boost::unordered::detail::set_extractor<value_type> extractor;
|
||||
|
||||
typedef boost::unordered::detail::pick_policy::type policy;
|
||||
};
|
||||
|
||||
template <typename A, typename K, typename M, typename H, typename P>
|
||||
@ -160,6 +162,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef boost::unordered::detail::grouped_table_impl<types> table;
|
||||
typedef boost::unordered::detail::map_extractor<key_type, value_type>
|
||||
extractor;
|
||||
|
||||
typedef boost::unordered::detail::pick_policy::type policy;
|
||||
};
|
||||
|
||||
template <typename Types>
|
||||
@ -219,7 +223,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
Key const& k,
|
||||
Pred const& eq) const
|
||||
{
|
||||
std::size_t bucket_index = hash % this->bucket_count_;
|
||||
std::size_t bucket_index = this->to_bucket(this->bucket_count_, hash);
|
||||
node_pointer n = this->get_start(bucket_index);
|
||||
|
||||
for (;;)
|
||||
@ -234,7 +238,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (node_hash % this->bucket_count_ != bucket_index)
|
||||
if (this->to_bucket(this->bucket_count_, node_hash) != bucket_index)
|
||||
return node_pointer();
|
||||
}
|
||||
|
||||
@ -397,25 +401,25 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if(pos) {
|
||||
this->add_after_node(n, pos);
|
||||
if (n->next_) {
|
||||
std::size_t next_bucket =
|
||||
static_cast<node_pointer>(n->next_)->hash_ %
|
||||
this->bucket_count_;
|
||||
if (next_bucket != hash % this->bucket_count_) {
|
||||
std::size_t next_bucket = this->to_bucket(
|
||||
this->bucket_count_,
|
||||
static_cast<node_pointer>(n->next_)->hash_);
|
||||
if (next_bucket != this->to_bucket(this->bucket_count_, hash)) {
|
||||
this->get_bucket(next_bucket)->next_ = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
bucket_pointer b = this->get_bucket(hash % this->bucket_count_);
|
||||
bucket_pointer b = this->get_bucket(this->to_bucket(this->bucket_count_, hash));
|
||||
|
||||
if (!b->next_)
|
||||
{
|
||||
previous_pointer start_node = this->get_previous_start();
|
||||
|
||||
if (start_node->next_) {
|
||||
this->get_bucket(
|
||||
this->get_bucket(this->to_bucket(this->bucket_count_,
|
||||
static_cast<node_pointer>(start_node->next_)->hash_
|
||||
% this->bucket_count_)->next_ = n;
|
||||
))->next_ = n;
|
||||
}
|
||||
|
||||
b->next_ = start_node;
|
||||
@ -435,7 +439,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
node_pointer emplace_impl(node_constructor& a)
|
||||
{
|
||||
key_type const& k = this->get_key(a.value());
|
||||
std::size_t hash = this->hash_function()(k);
|
||||
std::size_t hash = this->hash(k);
|
||||
node_pointer position = this->find_node(hash, k);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
@ -447,7 +451,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
void emplace_impl_no_rehash(node_constructor& a)
|
||||
{
|
||||
key_type const& k = this->get_key(a.value());
|
||||
std::size_t hash = this->hash_function()(k);
|
||||
std::size_t hash = this->hash(k);
|
||||
this->add_node(a, hash,
|
||||
this->find_node(hash, k));
|
||||
}
|
||||
@ -523,8 +527,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{
|
||||
if(!this->size_) return 0;
|
||||
|
||||
std::size_t hash = this->hash_function()(k);
|
||||
std::size_t bucket_index = hash % this->bucket_count_;
|
||||
std::size_t hash = this->hash(k);
|
||||
std::size_t bucket_index = this->to_bucket(this->bucket_count_, hash);
|
||||
bucket_pointer bucket = this->get_bucket(bucket_index);
|
||||
|
||||
previous_pointer prev = bucket->next_;
|
||||
@ -535,7 +539,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if (!prev->next_) return 0;
|
||||
std::size_t node_hash =
|
||||
static_cast<node_pointer>(prev->next_)->hash_;
|
||||
if (node_hash % this->bucket_count_ != bucket_index)
|
||||
if (this->to_bucket(this->bucket_count_, node_hash) != bucket_index)
|
||||
return 0;
|
||||
if (node_hash == hash &&
|
||||
this->key_eq()(k, this->get_key(
|
||||
@ -560,7 +564,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
node_pointer next = static_cast<node_pointer>(r->next_);
|
||||
|
||||
bucket_pointer bucket = this->get_bucket(
|
||||
r->hash_ % this->bucket_count_);
|
||||
this->to_bucket(this->bucket_count_, r->hash_));
|
||||
previous_pointer prev = unlink_node(*bucket, r);
|
||||
|
||||
this->fix_buckets(bucket, prev, next);
|
||||
@ -574,7 +578,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{
|
||||
if (r1 == r2) return r2;
|
||||
|
||||
std::size_t bucket_index = r1->hash_ % this->bucket_count_;
|
||||
std::size_t bucket_index = this->to_bucket(this->bucket_count_, r1->hash_);
|
||||
previous_pointer prev = unlink_nodes(
|
||||
*this->get_bucket(bucket_index), r1, r2);
|
||||
this->fix_buckets_range(bucket_index, prev, r1, r2);
|
||||
@ -809,7 +813,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
static previous_pointer place_in_bucket(buckets& dst,
|
||||
previous_pointer prev, node_pointer end)
|
||||
{
|
||||
bucket_pointer b = dst.get_bucket(end->hash_ % dst.bucket_count_);
|
||||
bucket_pointer b = dst.get_bucket(dst.to_bucket(
|
||||
dst.bucket_count_, end->hash_));
|
||||
|
||||
if (!b->next_) {
|
||||
b->next_ = static_cast<node_pointer>(prev);
|
||||
|
@ -24,15 +24,16 @@ namespace boost { namespace unordered { namespace iterator_detail {
|
||||
template <typename NodePointer, typename Value> struct iterator;
|
||||
template <typename ConstNodePointer, typename NodePointer,
|
||||
typename Value> struct c_iterator;
|
||||
template <typename NodePointer, typename Value> struct l_iterator;
|
||||
template <typename NodePointer, typename Value, typename Policy>
|
||||
struct l_iterator;
|
||||
template <typename ConstNodePointer, typename NodePointer,
|
||||
typename Value> struct cl_iterator;
|
||||
typename Value, typename Policy> struct cl_iterator;
|
||||
|
||||
// Local Iterators
|
||||
//
|
||||
// all no throw
|
||||
|
||||
template <typename NodePointer, typename Value>
|
||||
template <typename NodePointer, typename Value, typename Policy>
|
||||
struct l_iterator
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag, Value, std::ptrdiff_t,
|
||||
@ -40,7 +41,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
|
||||
{
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template <typename ConstNodePointer, typename NodePointer2,
|
||||
typename Value2>
|
||||
typename Value2, typename Policy2>
|
||||
friend struct boost::unordered::iterator_detail::cl_iterator;
|
||||
private:
|
||||
#endif
|
||||
@ -66,7 +67,8 @@ namespace boost { namespace unordered { namespace iterator_detail {
|
||||
|
||||
l_iterator& operator++() {
|
||||
ptr_ = static_cast<node_pointer>(ptr_->next_);
|
||||
if (ptr_ && ptr_->hash_ % bucket_count_ != bucket_)
|
||||
if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_)
|
||||
!= bucket_)
|
||||
ptr_ = node_pointer();
|
||||
return *this;
|
||||
}
|
||||
@ -86,14 +88,15 @@ namespace boost { namespace unordered { namespace iterator_detail {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ConstNodePointer, typename NodePointer, typename Value>
|
||||
template <typename ConstNodePointer, typename NodePointer, typename Value,
|
||||
typename Policy>
|
||||
struct cl_iterator
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag, Value, std::ptrdiff_t,
|
||||
ConstNodePointer, Value const&>
|
||||
{
|
||||
friend struct boost::unordered::iterator_detail::l_iterator
|
||||
<NodePointer, Value>;
|
||||
<NodePointer, Value, Policy>;
|
||||
private:
|
||||
|
||||
typedef NodePointer node_pointer;
|
||||
@ -109,7 +112,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
|
||||
ptr_(x), bucket_(b), bucket_count_(c) {}
|
||||
|
||||
cl_iterator(boost::unordered::iterator_detail::l_iterator<
|
||||
NodePointer, Value> const& x) :
|
||||
NodePointer, Value, Policy> const& x) :
|
||||
ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_)
|
||||
{}
|
||||
|
||||
@ -124,7 +127,8 @@ namespace boost { namespace unordered { namespace iterator_detail {
|
||||
|
||||
cl_iterator& operator++() {
|
||||
ptr_ = static_cast<node_pointer>(ptr_->next_);
|
||||
if (ptr_ && ptr_->hash_ % bucket_count_ != bucket_)
|
||||
if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_)
|
||||
!= bucket_)
|
||||
ptr_ = node_pointer();
|
||||
return *this;
|
||||
}
|
||||
@ -302,7 +306,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
boost::unordered::detail::buckets<
|
||||
typename Types::allocator,
|
||||
typename Types::bucket,
|
||||
typename Types::node>,
|
||||
typename Types::node,
|
||||
typename Types::policy>,
|
||||
boost::unordered::detail::functions<
|
||||
typename Types::hasher,
|
||||
typename Types::key_equal>
|
||||
@ -318,6 +323,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename Types::value_type value_type;
|
||||
typedef typename Types::table table_impl;
|
||||
typedef typename Types::link_pointer link_pointer;
|
||||
typedef typename Types::policy policy;
|
||||
|
||||
typedef boost::unordered::detail::functions<
|
||||
typename Types::hasher,
|
||||
@ -326,7 +332,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef boost::unordered::detail::buckets<
|
||||
typename Types::allocator,
|
||||
typename Types::bucket,
|
||||
typename Types::node> buckets;
|
||||
typename Types::node,
|
||||
typename Types::policy> buckets;
|
||||
|
||||
typedef typename buckets::node_allocator node_allocator;
|
||||
typedef typename buckets::node_allocator_traits node_allocator_traits;
|
||||
@ -338,9 +345,9 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef boost::unordered::iterator_detail::
|
||||
c_iterator<const_node_pointer, node_pointer, value_type> c_iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
l_iterator<node_pointer, value_type> l_iterator;
|
||||
l_iterator<node_pointer, value_type, policy> l_iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
cl_iterator<const_node_pointer, node_pointer, value_type>
|
||||
cl_iterator<const_node_pointer, node_pointer, value_type, policy>
|
||||
cl_iterator;
|
||||
|
||||
// Members
|
||||
@ -395,7 +402,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// Or from rehash post-condition:
|
||||
// count > size / mlf_
|
||||
|
||||
return boost::unordered::detail::next_prime(
|
||||
return this->new_bucket_count(
|
||||
boost::unordered::detail::double_to_size(floor(
|
||||
static_cast<double>(size) /
|
||||
static_cast<double>(mlf_))) + 1);
|
||||
@ -408,7 +415,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
hasher const& hf,
|
||||
key_equal const& eq,
|
||||
node_allocator const& a) :
|
||||
buckets(a, boost::unordered::detail::next_prime(num_buckets)),
|
||||
buckets(a, this->new_bucket_count(num_buckets)),
|
||||
functions(hf, eq),
|
||||
mlf_(1.0f),
|
||||
max_load_(0)
|
||||
@ -586,6 +593,11 @@ namespace boost { namespace unordered { namespace detail {
|
||||
return extractor::extract(x);
|
||||
}
|
||||
|
||||
std::size_t hash(key_type const& k) const
|
||||
{
|
||||
return this->apply_hash(this->hash_function(), k);
|
||||
}
|
||||
|
||||
// Find Node
|
||||
|
||||
template <typename Key, typename Hash, typename Pred>
|
||||
@ -596,7 +608,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{
|
||||
if (!this->size_) return node_pointer();
|
||||
return static_cast<table_impl const*>(this)->
|
||||
find_node_impl(hash_function(k), k, eq);
|
||||
find_node_impl(this->apply_hash(hash_function, k), k, eq);
|
||||
}
|
||||
|
||||
node_pointer find_node(
|
||||
@ -612,7 +624,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{
|
||||
if (!this->size_) return node_pointer();
|
||||
return static_cast<table_impl const*>(this)->
|
||||
find_node_impl(this->hash_function()(k), k, this->key_eq());
|
||||
find_node_impl(this->hash(k), k, this->key_eq());
|
||||
}
|
||||
|
||||
node_pointer find_matching_node(node_pointer n) const
|
||||
@ -666,10 +678,10 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
if(!this->size_) {
|
||||
if(this->buckets_) this->delete_buckets();
|
||||
this->bucket_count_ = next_prime(min_buckets);
|
||||
this->bucket_count_ = this->new_bucket_count(min_buckets);
|
||||
}
|
||||
else {
|
||||
min_buckets = next_prime((std::max)(min_buckets,
|
||||
min_buckets = this->new_bucket_count((std::max)(min_buckets,
|
||||
boost::unordered::detail::double_to_size(floor(
|
||||
static_cast<double>(this->size_) /
|
||||
static_cast<double>(mlf_))) + 1));
|
||||
|
@ -132,6 +132,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
typedef boost::unordered::detail::table_impl<types> table;
|
||||
typedef boost::unordered::detail::set_extractor<value_type> extractor;
|
||||
|
||||
typedef boost::unordered::detail::pick_policy::type policy;
|
||||
};
|
||||
|
||||
template <typename A, typename K, typename M, typename H, typename P>
|
||||
@ -156,6 +158,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef boost::unordered::detail::table_impl<types> table;
|
||||
typedef boost::unordered::detail::map_extractor<key_type, value_type>
|
||||
extractor;
|
||||
|
||||
typedef boost::unordered::detail::pick_policy::type policy;
|
||||
};
|
||||
|
||||
template <typename Types>
|
||||
@ -217,7 +221,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
Key const& k,
|
||||
Pred const& eq) const
|
||||
{
|
||||
std::size_t bucket_index = hash % this->bucket_count_;
|
||||
std::size_t bucket_index = this->to_bucket(this->bucket_count_, hash);
|
||||
node_pointer n = this->get_start(bucket_index);
|
||||
|
||||
for (;;)
|
||||
@ -232,7 +236,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (node_hash % this->bucket_count_ != bucket_index)
|
||||
if (this->to_bucket(this->bucket_count_, node_hash) != bucket_index)
|
||||
return node_pointer();
|
||||
}
|
||||
|
||||
@ -298,16 +302,16 @@ namespace boost { namespace unordered { namespace detail {
|
||||
node_pointer n = a.release();
|
||||
n->hash_ = hash;
|
||||
|
||||
bucket_pointer b = this->get_bucket(hash % this->bucket_count_);
|
||||
bucket_pointer b = this->get_bucket(this->to_bucket(this->bucket_count_, hash));
|
||||
|
||||
if (!b->next_)
|
||||
{
|
||||
previous_pointer start_node = this->get_previous_start();
|
||||
|
||||
if (start_node->next_) {
|
||||
this->get_bucket(
|
||||
static_cast<node_pointer>(start_node->next_)->hash_ %
|
||||
this->bucket_count_)->next_ = n;
|
||||
this->get_bucket(this->to_bucket(this->bucket_count_,
|
||||
static_cast<node_pointer>(start_node->next_)->hash_)
|
||||
)->next_ = n;
|
||||
}
|
||||
|
||||
b->next_ = start_node;
|
||||
@ -328,7 +332,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{
|
||||
typedef typename value_type::second_type mapped_type;
|
||||
|
||||
std::size_t hash = this->hash_function()(k);
|
||||
std::size_t hash = this->hash(k);
|
||||
node_pointer pos = this->find_node(hash, k);
|
||||
|
||||
if (pos) return pos->value();
|
||||
@ -389,7 +393,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
emplace_return emplace_impl(key_type const& k,
|
||||
BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
std::size_t hash = this->hash_function()(k);
|
||||
std::size_t hash = this->hash(k);
|
||||
node_pointer pos = this->find_node(hash, k);
|
||||
|
||||
if (pos) return emplace_return(iterator(pos), false);
|
||||
@ -409,7 +413,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
emplace_return emplace_impl_with_node(node_constructor& a)
|
||||
{
|
||||
key_type const& k = this->get_key(a.value());
|
||||
std::size_t hash = this->hash_function()(k);
|
||||
std::size_t hash = this->hash(k);
|
||||
node_pointer pos = this->find_node(hash, k);
|
||||
|
||||
if (pos) return emplace_return(iterator(pos), false);
|
||||
@ -473,7 +477,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
void insert_range_empty(node_constructor& a, key_type const& k,
|
||||
InputIt i, InputIt j)
|
||||
{
|
||||
std::size_t hash = this->hash_function()(k);
|
||||
std::size_t hash = this->hash(k);
|
||||
a.construct_node();
|
||||
a.construct_value2(*i);
|
||||
this->reserve_for_insert(this->size_ +
|
||||
@ -486,7 +490,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
InputIt i, InputIt j)
|
||||
{
|
||||
// No side effects in this initial code
|
||||
std::size_t hash = this->hash_function()(k);
|
||||
std::size_t hash = this->hash(k);
|
||||
node_pointer pos = this->find_node(hash, k);
|
||||
|
||||
if (!pos) {
|
||||
@ -523,8 +527,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{
|
||||
if(!this->size_) return 0;
|
||||
|
||||
std::size_t hash = this->hash_function()(k);
|
||||
std::size_t bucket_index = hash % this->bucket_count_;
|
||||
std::size_t hash = this->hash(k);
|
||||
std::size_t bucket_index = this->to_bucket(this->bucket_count_, hash);
|
||||
bucket_pointer bucket = this->get_bucket(bucket_index);
|
||||
|
||||
previous_pointer prev = bucket->next_;
|
||||
@ -535,7 +539,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if (!prev->next_) return 0;
|
||||
std::size_t node_hash =
|
||||
static_cast<node_pointer>(prev->next_)->hash_;
|
||||
if (node_hash % this->bucket_count_ != bucket_index)
|
||||
if (this->to_bucket(this->bucket_count_, node_hash) != bucket_index)
|
||||
return 0;
|
||||
if (node_hash == hash &&
|
||||
this->key_eq()(k, this->get_key(
|
||||
@ -557,7 +561,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
node_pointer next = static_cast<node_pointer>(r->next_);
|
||||
|
||||
bucket_pointer bucket = this->get_bucket(
|
||||
r->hash_ % this->bucket_count_);
|
||||
this->to_bucket(this->bucket_count_, r->hash_));
|
||||
previous_pointer prev = unlink_node(*bucket, r);
|
||||
|
||||
this->fix_buckets(bucket, prev, next);
|
||||
@ -571,7 +575,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{
|
||||
if (r1 == r2) return r2;
|
||||
|
||||
std::size_t bucket_index = r1->hash_ % this->bucket_count_;
|
||||
std::size_t bucket_index = this->to_bucket(this->bucket_count_, r1->hash_);
|
||||
previous_pointer prev = unlink_nodes(
|
||||
*this->get_bucket(bucket_index), r1, r2);
|
||||
this->fix_buckets_range(bucket_index, prev, r1, r2);
|
||||
@ -689,7 +693,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
previous_pointer prev)
|
||||
{
|
||||
node_pointer n = static_cast<node_pointer>(prev->next_);
|
||||
bucket_pointer b = dst.get_bucket(n->hash_ % dst.bucket_count_);
|
||||
bucket_pointer b = dst.get_bucket(dst.to_bucket(dst.bucket_count_,
|
||||
n->hash_));
|
||||
|
||||
if (!b->next_) {
|
||||
b->next_ = prev;
|
||||
|
@ -465,7 +465,8 @@ namespace unordered
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return table_.hash_function()(k) % table_.bucket_count_;
|
||||
return table_.to_bucket(table_.bucket_count_,
|
||||
table_.hash(k));
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
@ -946,7 +947,8 @@ namespace unordered
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return table_.hash_function()(k) % table_.bucket_count_;
|
||||
return table_.to_bucket(table_.bucket_count_,
|
||||
table_.hash(k));
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
|
@ -450,7 +450,8 @@ namespace unordered
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return table_.hash_function()(k) % table_.bucket_count_;
|
||||
return table_.to_bucket(table_.bucket_count_,
|
||||
table_.hash(k));
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
@ -921,7 +922,8 @@ namespace unordered
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return table_.hash_function()(k) % table_.bucket_count_;
|
||||
return table_.to_bucket(table_.bucket_count_,
|
||||
table_.hash(k));
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
|
Reference in New Issue
Block a user