////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2025-2026. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/container for documentation. // ////////////////////////////////////////////////////////////////////////////// #ifndef BOOST_CONTAINER_EXPERIMENTAL_SEGMENTED_FIND_LAST_HPP #define BOOST_CONTAINER_EXPERIMENTAL_SEGMENTED_FIND_LAST_HPP #ifndef BOOST_CONFIG_HPP # include #endif #if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif #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; BOOST_CONTAINER_SEGMENTED_UNROLL(4) 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; BOOST_CONTAINER_SEGMENTED_UNROLL(4) while (cur != first) { --cur; if (*cur == value) return cur; } return last; } ////////////////////////////////////////////// // 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) { 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 } // namespace boost #include #endif // BOOST_CONTAINER_EXPERIMENTAL_SEGMENTED_FIND_LAST_HPP