diff --git a/bench/bench_set.cpp b/bench/bench_set.cpp index 5742f3b..5262760 100644 --- a/bench/bench_set.cpp +++ b/bench/bench_set.cpp @@ -229,6 +229,27 @@ cpu_times insert_time(vector &unique_range, vector +bool check_not_end(vector &iterators, Iterator itend, std::size_t number_of_ends = 0) +{ + std::size_t end_count = 0; + for(std::size_t i = 0, max = iterators.size(); i != max; ++i){ + if(iterators[i] == itend && (++end_count > number_of_ends) ) + return false; + } + return true; +} + +template +bool check_all_not_empty(vector< std::pair > &iterator_pairs) +{ + for(std::size_t i = 0, max = iterator_pairs.size(); i != max; ++i){ + if(iterator_pairs[i].first == iterator_pairs[i].second) + return false; + } + return true; +} + template cpu_times search_time(vector &unique_range, const char *RangeType) { @@ -239,72 +260,68 @@ cpu_times search_time(vector &unique_range, const char * cpu_timer total_time; total_time.resume(); + vector v_it(N); + vector< std::pair > v_itp(N); + for(std::size_t i = 0; i != N; ++i){ //Find { - std::size_t found = 0; find_timer.resume(); for(std::size_t rep = 0; rep != 2; ++rep) for(std::size_t i = 0, max = unique_range.size(); i != max; ++i){ - found += static_cast(c.end() != c.find(unique_range[i])); + v_it[i] = c.find(unique_range[i]); } find_timer.stop(); - if(found/2 != c.size()){ + if(!check_not_end(v_it, c.end())){ std::cout << "ERROR! find all elements not found" << std::endl; } } //Lower { - std::size_t found = 0; lower_timer.resume(); for(std::size_t rep = 0; rep != 2; ++rep) for(std::size_t i = 0, max = unique_range.size(); i != max; ++i){ - found += static_cast(c.end() != c.lower_bound(unique_range[i])); + v_it[i] = c.lower_bound(unique_range[i]); } lower_timer.stop(); - if(found/2 != c.size()){ + if(!check_not_end(v_it, c.end())){ std::cout << "ERROR! lower_bound all elements not found" << std::endl; } } //Upper { - std::size_t found = 0; upper_timer.resume(); for(std::size_t rep = 0; rep != 2; ++rep) for(std::size_t i = 0, max = unique_range.size(); i != max; ++i){ - found += static_cast(c.end() != c.upper_bound(unique_range[i])); + v_it[i] = c.upper_bound(unique_range[i]); } upper_timer.stop(); - if(found/2 != (c.size()-1)){ + if(!check_not_end(v_it, c.end(), 1u)){ std::cout << "ERROR! upper_bound all elements not found" << std::endl; } } //Equal { - std::size_t found = 0; - std::pair ret; equal_range_timer.resume(); for(std::size_t rep = 0; rep != 2; ++rep) for(std::size_t i = 0, max = unique_range.size(); i != max; ++i){ - ret = c.equal_range(unique_range[i]); - found += static_cast(ret.first != ret.second); + v_itp[i] = c.equal_range(unique_range[i]); } equal_range_timer.stop(); - if(found/2 != c.size()){ + if(!check_all_not_empty(v_itp)){ std::cout << "ERROR! equal_range all elements not found" << std::endl; } } //Count { - std::size_t found = 0; - std::pair ret; + std::size_t count = 0; count_timer.resume(); for(std::size_t rep = 0; rep != 2; ++rep) for(std::size_t i = 0, max = unique_range.size(); i != max; ++i){ - found += static_cast(c.count(unique_range[i])); + count += c.count(unique_range[i]); } count_timer.stop(); - if(found/2 != c.size()){ + if(count/2 != c.size()){ std::cout << "ERROR! count all elements not found" << std::endl; } } diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index 2d7634f..d3f9ee6 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -743,6 +743,12 @@ class flat_tree std::pair equal_range(const key_type& k) const { return this->priv_equal_range(this->cbegin(), this->cend(), k); } + std::pair lower_bound_range(const key_type& k) + { return this->priv_lower_bound_range(this->begin(), this->end(), k); } + + std::pair lower_bound_range(const key_type& k) const + { return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); } + size_type capacity() const { return this->m_data.m_vect.capacity(); } @@ -958,6 +964,18 @@ class flat_tree return std::pair(first, first); } + template + std::pair priv_lower_bound_range(RanIt first, RanIt last, const key_type& k) const + { + const Compare &key_cmp = this->m_data.get_comp(); + KeyOfValue key_extract; + RanIt lb(this->priv_lower_bound(first, last, k)), ub(lb); + if(lb != last && static_cast(!key_cmp(k, key_extract(*lb)))){ + ++ub; + } + return std::pair(lb, ub); + } + template void priv_insert_equal_loop(InIt first, InIt last) { diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index 661f39c..16db841 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -1071,7 +1071,8 @@ class tree void clear() { AllocHolder::clear(alloc_version()); } - // set operations: + // search operations. Const and non-const overloads even if no iterator is returned + // so splay implementations can to their rebalancing when searching in non-const versions iterator find(const key_type& k) { return iterator(this->icont().find(k, KeyNodeCompare(value_comp()))); } @@ -1108,6 +1109,21 @@ class tree (const_iterator(ret.first), const_iterator(ret.second)); } + std::pair lower_bound_range(const key_type& k) + { + std::pair ret = + this->icont().lower_bound_range(k, KeyNodeCompare(value_comp())); + return std::pair(iterator(ret.first), iterator(ret.second)); + } + + std::pair lower_bound_range(const key_type& k) const + { + std::pair ret = + this->non_const_icont().lower_bound_range(k, KeyNodeCompare(value_comp())); + return std::pair + (const_iterator(ret.first), const_iterator(ret.second)); + } + void rebalance() { intrusive_tree_proxy_t::rebalance(this->icont()); } diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index ff66e5d..0f70e0f 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -857,13 +857,13 @@ class flat_map //! //! Complexity: Logarithmic std::pair equal_range(const key_type& x) - { return container_detail::force_copy >(m_flat_tree.equal_range(x)); } + { return container_detail::force_copy >(m_flat_tree.lower_bound_range(x)); } //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). //! //! Complexity: Logarithmic std::pair equal_range(const key_type& x) const - { return container_detail::force_copy >(m_flat_tree.equal_range(x)); } + { return container_detail::force_copy >(m_flat_tree.lower_bound_range(x)); } //! Effects: Returns true if x and y are equal //! diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp index 9eedfb1..0a1ece6 100644 --- a/include/boost/container/flat_set.hpp +++ b/include/boost/container/flat_set.hpp @@ -604,30 +604,17 @@ class flat_set #endif // #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). //! //! Complexity: Logarithmic std::pair equal_range(const key_type& x) const - { - const_iterator lb = this->lower_bound(x), ub(lb); - if(lb != this->cend() && static_cast(!this->key_comp()(x, *lb))){ - ++ub; - } - return std::pair(lb, ub); - } + { return this->base_t::lower_bound_range(x); } //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). //! //! Complexity: Logarithmic std::pair equal_range(const key_type& x) - { - iterator lb = this->lower_bound(x), ub(lb); - if(lb != this->end() && static_cast(!this->key_comp()(x, *lb))){ - ++ub; - } - return std::pair(lb, ub); - } + { return this->base_t::lower_bound_range(x); } #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp index 934d7db..ffb5d00 100644 --- a/include/boost/container/set.hpp +++ b/include/boost/container/set.hpp @@ -540,6 +540,22 @@ class set //! Complexity: Logarithmic const_iterator upper_bound(const key_type& x) const; + #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair equal_range(const key_type& x) + { return this->base_t::lower_bound_range(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair equal_range(const key_type& x) const + { return this->base_t::lower_bound_range(x); } + + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). //! //! Complexity: Logarithmic