From dd1308fd0e75e8f9cccd526f16c33507abfb8634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 4 May 2026 16:03:32 +0200 Subject: [PATCH] Reimplemented to avoid aliasing issues. --- .../experimental/segmented_find_last.hpp | 193 +++++++++++++++++- 1 file changed, 190 insertions(+), 3 deletions(-) diff --git a/include/boost/container/experimental/segmented_find_last.hpp b/include/boost/container/experimental/segmented_find_last.hpp index 44960df..0896823 100644 --- a/include/boost/container/experimental/segmented_find_last.hpp +++ b/include/boost/container/experimental/segmented_find_last.hpp @@ -20,19 +20,206 @@ #include #include -#include -#include +#include +#include namespace boost { namespace container { +template +FwdIt segmented_find_last(FwdIt first, Sent last, const T& value); + +namespace detail_algo { + +////////////////////////////////////////////// +// Non-segmented scans +////////////////////////////////////////////// + +template +BOOST_CONTAINER_FORCEINLINE +FwdIt find_last_scan(FwdIt first, Sent last, const T& value, + non_segmented_iterator_tag, const std::forward_iterator_tag&) +{ + FwdIt result = last; + for (; first != last; ++first) + if (*first == value) + result = first; + return result; +} + +template +BOOST_CONTAINER_FORCEINLINE +BidirIt find_last_scan(BidirIt first, BidirIt last, const T& value, + non_segmented_iterator_tag, const std::bidirectional_iterator_tag&) +{ + BidirIt cur = last; + while (cur != first) { + --cur; + if (*cur == value) + return cur; + } + return last; +} + +#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING) + +template +BOOST_CONTAINER_FORCEINLINE +RAIter find_last_scan(RAIter first, RAIter const last, const T& value, + non_segmented_iterator_tag, const std::random_access_iterator_tag&) +{ + typedef typename iterator_traits::difference_type difference_type; + + RAIter cur = last; + difference_type n = cur - first; + while (n >= difference_type(4)) { + --cur; + if (*cur == value) + goto found; + --cur; + if (*cur == value) + goto found; + --cur; + if (*cur == value) + goto found; + --cur; + if (*cur == value) + goto found; + n -= 4; + } + + switch(n) { + case 3: + --cur; + if (*cur == value) + goto found; + BOOST_FALLTHROUGH; + case 2: + --cur; + if (*cur == value) + goto found; + BOOST_FALLTHROUGH; + case 1: + --cur; + if (*cur == value) + goto found; + BOOST_FALLTHROUGH; + default: + break; + } + return last; + found: + return cur; +} + +#endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING + +////////////////////////////////////////////// +// Segmented forward scan +////////////////////////////////////////////// + +template +SegIt find_last_scan(SegIt first, SegIt last, const T& value, + segmented_iterator_tag, const std::forward_iterator_tag&) +{ + typedef segmented_iterator_traits traits; + typedef typename traits::local_iterator local_iterator; + typedef typename traits::segment_iterator segment_iterator; + typedef typename segmented_iterator_traits::is_segmented_iterator is_local_seg_t; + typedef typename iterator_traits::iterator_category local_cat_t; + + SegIt result = last; + segment_iterator sfirst = traits::segment(first); + const segment_iterator slast = traits::segment(last); + + if (sfirst == slast) { + return traits::compose + (sfirst, find_last_scan(traits::local(first), traits::local(last), value, is_local_seg_t(), local_cat_t())); + } + else { + { // First segment + const local_iterator le = traits::end(sfirst); + const local_iterator r = find_last_scan(traits::local(first), le, value, is_local_seg_t(), local_cat_t()); + if (r != le) + result = traits::compose(sfirst, r); + } + // Middle segments + for (++sfirst; sfirst != slast; ++sfirst) { + const local_iterator le = traits::end(sfirst); + const local_iterator r = find_last_scan(traits::begin(sfirst), le, value, is_local_seg_t(), local_cat_t()); + if (r != le) + result = traits::compose(sfirst, r); + } + // Last segment + return traits::compose + (sfirst, find_last_scan(traits::begin(slast), traits::local(last), value, is_local_seg_t(), local_cat_t())); + } +} + +////////////////////////////////////////////// +// Segmented bidirectional scan +////////////////////////////////////////////// + +template +SegIt find_last_scan(SegIt first, SegIt last, const T& value, segmented_iterator_tag, const std::bidirectional_iterator_tag&) +{ + typedef segmented_iterator_traits traits; + typedef typename traits::local_iterator local_iterator; + typedef typename traits::segment_iterator segment_iterator; + typedef typename segmented_iterator_traits::is_segmented_iterator is_local_seg_t; + typedef typename iterator_traits::iterator_category local_cat_t; + + segment_iterator const sfirst = traits::segment(first); + segment_iterator slast = traits::segment(last); + const local_iterator ll = traits::local(last); + + if (sfirst == slast) { + return traits::compose + (sfirst, find_last_scan(traits::local(first), ll, value, is_local_seg_t(), local_cat_t())); + } + + { // Last segment (partial): [begin(slast), local(last)) + local_iterator r = find_last_scan(traits::begin(slast), ll, value, is_local_seg_t(), local_cat_t()); + if (r != ll) + return traits::compose(slast, r); + } + + // Middle segments in reverse + for (--slast; slast != sfirst; --slast) { + const local_iterator le = traits::end(slast); + const local_iterator r = find_last_scan(traits::begin(slast), le, value, is_local_seg_t(), local_cat_t()); + if (r != le) + return traits::compose(slast, r); + } + + { // First segment (partial): [local(first), end(sfirst)) + const local_iterator le = traits::end(sfirst); + const local_iterator r = find_last_scan(traits::local(first), le, value, is_local_seg_t(), local_cat_t()); + if (r != le) + return traits::compose(sfirst, r); + } + + return last; +} + +////////////////////////////////////////////// +// Sentinel / generic fallback +////////////////////////////////////////////// + +} // namespace detail_algo + //! Returns an iterator to the last element equal to \c value //! in [first, last), or \c last if not found. +//! For bidirectional iterators, scans backward for early exit. +//! For forward iterators, scans the entire range and remembers +//! the last match. template BOOST_CONTAINER_FORCEINLINE FwdIt segmented_find_last(FwdIt first, Sent last, const T& value) { - return boost::container::segmented_find_last_if(first, last, equal_to_value(value)); + typedef detail_algo::sent_filter sf; + return detail_algo::find_last_scan + ( first, last, value, typename sf::seg_t(), typename sf::cat_t()); } } // namespace container