From abc50c727596a1e4fc8b3584a46b6a897c4a2282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 19 Jan 2014 19:18:57 +0100 Subject: [PATCH] Improved unique associative container count function. Improved also flat_xxx's equal_range. --- include/boost/container/detail/flat_tree.hpp | 44 ++++++++++---------- include/boost/container/detail/tree.hpp | 2 +- include/boost/container/flat_set.hpp | 31 +++++++++++--- include/boost/container/set.hpp | 8 +++- test/set_test.hpp | 2 - 5 files changed, 55 insertions(+), 32 deletions(-) diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index 457b24c..2d7634f 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -717,6 +717,7 @@ class flat_tree return i; } + // set operations: size_type count(const key_type& k) const { std::pair p = this->equal_range(k); @@ -875,7 +876,7 @@ class flat_tree } template - RanIt priv_lower_bound(RanIt first, RanIt last, + RanIt priv_lower_bound(RanIt first, const RanIt last, const key_type & key) const { const Compare &key_cmp = this->m_data.get_comp(); @@ -884,24 +885,23 @@ class flat_tree RanIt middle; while (len) { - size_type half = len >> 1; + size_type step = len >> 1; middle = first; - middle += half; + middle += step; if (key_cmp(key_extract(*middle), key)) { - ++middle; - first = middle; - len = len - half - 1; + first = ++middle; + len -= step + 1; + } + else{ + len = step; } - else - len = half; } return first; } - template - RanIt priv_upper_bound(RanIt first, RanIt last, + RanIt priv_upper_bound(RanIt first, const RanIt last, const key_type & key) const { const Compare &key_cmp = this->m_data.get_comp(); @@ -910,16 +910,16 @@ class flat_tree RanIt middle; while (len) { - size_type half = len >> 1; + size_type step = len >> 1; middle = first; - middle += half; + middle += step; if (key_cmp(key, key_extract(*middle))) { - len = half; + len = step; } else{ first = ++middle; - len = len - half - 1; + len -= step + 1; } } return first; @@ -935,24 +935,24 @@ class flat_tree RanIt middle; while (len) { - size_type half = len >> 1; + size_type step = len >> 1; middle = first; - middle += half; + middle += step; if (key_cmp(key_extract(*middle), key)){ - first = middle; - ++first; - len = len - half - 1; + first = ++middle; + len -= step + 1; } else if (key_cmp(key, key_extract(*middle))){ - len = half; + len = step; } else { //Middle is equal to key last = first; last += len; - first = this->priv_lower_bound(first, middle, key); - return std::pair (first, this->priv_upper_bound(++middle, last, key)); + return std::pair + ( this->priv_lower_bound(first, middle, key) + , this->priv_upper_bound(++middle, last, key)); } } return std::pair(first, first); diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index 735f49e..661f39c 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -287,7 +287,7 @@ struct intrusive_tree_dispatch ,container_detail::bi::base_hook - ,container_detail::bi::constant_time_size + ,container_detail::bi::floating_point ,container_detail::bi::size_type >::type type; }; diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp index c1b2e57..9eedfb1 100644 --- a/include/boost/container/flat_set.hpp +++ b/include/boost/container/flat_set.hpp @@ -575,7 +575,7 @@ class flat_set //! //! Complexity: log(size())+count(k) size_type count(const key_type& x) const - { return static_cast(this->find(x) != this->cend()); } + { return static_cast(this->base_t::find(x) != this->base_t::cend()); } #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! Returns: An iterator pointing to the first element with key not less @@ -602,15 +602,34 @@ class flat_set //! Complexity: Logarithmic const_iterator upper_bound(const key_type& x) const; - //! 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; + #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); + 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); + } + + //! 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); + } + + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! Effects: Returns true if x and y are equal //! diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp index 99e195b..934d7db 100644 --- a/include/boost/container/set.hpp +++ b/include/boost/container/set.hpp @@ -506,7 +506,13 @@ class set //! //! Complexity: log(size())+count(k) size_type count(const key_type& x) const - { return static_cast(this->find(x) != this->cend()); } + { return static_cast(this->base_t::find(x) != this->base_t::cend()); } + + //! Returns: The number of elements with key equivalent to x. + //! + //! Complexity: log(size())+count(k) + size_type count(const key_type& x) + { return static_cast(this->base_t::find(x) != this->base_t::end()); } #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) diff --git a/test/set_test.hpp b/test/set_test.hpp index 78e771f..56fb4a0 100644 --- a/test/set_test.hpp +++ b/test/set_test.hpp @@ -508,7 +508,6 @@ int set_test () typename MyBoostSet::iterator bs_b = boostset->begin(); typename MyBoostSet::iterator bs_e = boostset->end(); typename MyStdSet::iterator ss_b = stdset->begin(); - typename MyStdSet::iterator ss_e = stdset->end(); std::size_t i = 0; while(bs_b != bs_e){ @@ -555,7 +554,6 @@ int set_test () typename MyBoostMultiSet::iterator bm_b = boostmultiset->begin(); typename MyBoostMultiSet::iterator bm_e = boostmultiset->end(); typename MyStdMultiSet::iterator sm_b = stdmultiset->begin(); - typename MyStdMultiSet::iterator sm_e = stdmultiset->end(); while(bm_b != bm_e){ typename MyBoostMultiSet::iterator bm_i;