forked from boostorg/unordered
made rehash work with exact capacities, refactored capacity calculations
This commit is contained in:
@ -634,6 +634,15 @@ struct pow2_size_policy
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* size index of a group array for a given *element* capacity */
|
||||||
|
|
||||||
|
template<typename Group,typename SizePolicy>
|
||||||
|
static inline std::size_t size_index_for(std::size_t n)
|
||||||
|
{
|
||||||
|
/* n/N+1 == ceil((n+1)/N) (extra +1 for the sentinel) */
|
||||||
|
return SizePolicy::size_index(n/Group::N+1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Quadratic prober over a power-of-two range using triangular numbers.
|
/* Quadratic prober over a power-of-two range using triangular numbers.
|
||||||
* mask in next(mask) must be the range size minus one (and since size is 2^n,
|
* mask in next(mask) must be the range size minus one (and since size is 2^n,
|
||||||
* mask has exactly its n first bits set to 1).
|
* mask has exactly its n first bits set to 1).
|
||||||
@ -847,8 +856,7 @@ struct table_arrays
|
|||||||
{
|
{
|
||||||
using alloc_traits=boost::allocator_traits<Allocator>;
|
using alloc_traits=boost::allocator_traits<Allocator>;
|
||||||
|
|
||||||
/* n/N+1 == ceil((n+1)/N) (extra +1 for the sentinel) */
|
auto groups_size_index=size_index_for<group_type,size_policy>(n);
|
||||||
auto groups_size_index=size_policy::size_index(n/N+1);
|
|
||||||
auto groups_size=size_policy::size(groups_size_index);
|
auto groups_size=size_policy::size(groups_size_index);
|
||||||
table_arrays arrays{groups_size_index,groups_size-1,nullptr,nullptr};
|
table_arrays arrays{groups_size_index,groups_size-1,nullptr,nullptr};
|
||||||
|
|
||||||
@ -1174,7 +1182,8 @@ public:
|
|||||||
if(al()!=x.al())reserve(0);
|
if(al()!=x.al())reserve(0);
|
||||||
copy_assign_if<pocca>(al(),x.al());
|
copy_assign_if<pocca>(al(),x.al());
|
||||||
});
|
});
|
||||||
noshrink_reserve(x.size());
|
/* noshrink: favor memory reuse over tightness */
|
||||||
|
noshrink_reserve(x.size());
|
||||||
x.for_all_elements([this](value_type* p){
|
x.for_all_elements([this](value_type* p){
|
||||||
unchecked_insert(*p);
|
unchecked_insert(*p);
|
||||||
});
|
});
|
||||||
@ -1227,6 +1236,7 @@ public:
|
|||||||
* under noexcept(true) conditions.
|
* under noexcept(true) conditions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* noshrink: favor memory reuse over tightness */
|
||||||
noshrink_reserve(x.size());
|
noshrink_reserve(x.size());
|
||||||
BOOST_TRY{
|
BOOST_TRY{
|
||||||
/* This works because subsequent x.clear() does not depend on the
|
/* This works because subsequent x.clear() does not depend on the
|
||||||
@ -1406,16 +1416,16 @@ public:
|
|||||||
|
|
||||||
void rehash(std::size_t n)
|
void rehash(std::size_t n)
|
||||||
{
|
{
|
||||||
auto c1=std::size_t(std::ceil(float(size())/mlf));
|
auto m=size_t(std::ceil(float(size())/mlf));
|
||||||
auto c2=n?size_policy::size(size_policy::size_index(n/N+1))*N-1:0;
|
if(m>n)n=m;
|
||||||
auto c=c1>c2?c1:c2; /* we avoid std::max to not include <algorithm> */
|
if(n)n=capacity_for(n); /* exact resulting capacity */
|
||||||
|
|
||||||
if(c!=capacity())unchecked_rehash(c);
|
if(n!=capacity())unchecked_rehash(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void reserve(std::size_t n)
|
void reserve(std::size_t n)
|
||||||
{
|
{
|
||||||
rehash(std::size_t(std::ceil(static_cast<float>(n)/mlf)));
|
rehash(std::size_t(std::ceil(float(n)/mlf)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Predicate>
|
template<typename Predicate>
|
||||||
@ -1614,6 +1624,11 @@ private:
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::size_t capacity_for(std::size_t n)
|
||||||
|
{
|
||||||
|
return size_policy::size(size_index_for<group_type,size_policy>(n))*N-1;
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_NOINLINE void unchecked_rehash(std::size_t n)
|
BOOST_NOINLINE void unchecked_rehash(std::size_t n)
|
||||||
{
|
{
|
||||||
auto new_arrays_=new_arrays(n);
|
auto new_arrays_=new_arrays(n);
|
||||||
@ -1653,16 +1668,18 @@ private:
|
|||||||
void noshrink_reserve(std::size_t n)
|
void noshrink_reserve(std::size_t n)
|
||||||
{
|
{
|
||||||
/* used only on assignment after element clearance */
|
/* used only on assignment after element clearance */
|
||||||
BOOST_ASSERT(size_==0);
|
BOOST_ASSERT(empty());
|
||||||
|
|
||||||
auto c=std::size_t(std::ceil(static_cast<float>(n)/mlf));
|
if(n){
|
||||||
if(c) c=size_policy::size(size_policy::size_index(c/N+1))*N-1;
|
n=std::size_t(std::ceil(float(n)/mlf)); /* elements -> slots */
|
||||||
|
n=capacity_for(n); /* exact resulting capacity */
|
||||||
|
|
||||||
if(c>capacity()){
|
if(n>capacity()){
|
||||||
auto new_arrays_=new_arrays(c);
|
auto new_arrays_=new_arrays(n);
|
||||||
delete_arrays(arrays);
|
delete_arrays(arrays);
|
||||||
arrays=new_arrays_;
|
arrays=new_arrays_;
|
||||||
ml=max_load();
|
ml=max_load();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user