From bfc22a86a7dbbff871e5277d8e7d9a334ee9d0aa Mon Sep 17 00:00:00 2001 From: Mitsuru Kariya Date: Wed, 28 Aug 2013 08:34:20 +0900 Subject: [PATCH] Change find_end: 1.Fix for ForwardIterator when [first2, last2) is empty. 2.Fix RandomAccessIterator version.(search from last1) 3.Add BidirectionalIterator version.(search from last1) 4.Add sprout::detail::search_one_rev helper function for BidirectionalIterator version. --- sprout/algorithm/find_end.hpp | 208 ++++++++++++++------- sprout/detail/algorithm/search_one_rev.hpp | 109 +++++++++++ 2 files changed, 250 insertions(+), 67 deletions(-) create mode 100644 sprout/detail/algorithm/search_one_rev.hpp diff --git a/sprout/algorithm/find_end.hpp b/sprout/algorithm/find_end.hpp index 00519edb..511b3b36 100644 --- a/sprout/algorithm/find_end.hpp +++ b/sprout/algorithm/find_end.hpp @@ -16,74 +16,148 @@ #include #include #include +#include namespace sprout { namespace detail { - // !!! -// template -// inline SPROUT_CONSTEXPR RandomAccessIterator1 -// find_end_impl_check_ra(RandomAccessIterator1 first1, RandomAccessIterator1 result, RandomAccessIterator1 searched) { -// return searched == first1 ? searched -// : result -// ; -// } -// template -// inline SPROUT_CONSTEXPR RandomAccessIterator1 -// find_end_impl_ra( -// RandomAccessIterator1 first1, RandomAccessIterator1 last1, -// ForwardIterator2 first2, ForwardIterator2 last2, -// BinaryPredicate pred, -// typename std::iterator_traits::difference_type pivot, RandomAccessIterator1 last1_, RandomAccessIterator1 result, -// RandomAccessIterator1 searched -// ) -// { -// return searched == last1_ ? result -// : searched < first1 ? pivot == 0 -// ? sprout::detail::find_end_impl_check_ra( -// first1, searched, -// sprout::detail::search_one(first1, last1_, first2, last2, pred) -// ) -// : sprout::detail::find_end_impl_ra( -// sprout::next(first1, pivot), last1, first2, last2, pred, -// (sprout::distance(first1, last1) - pivot) / 2, last1_, searched, -// sprout::detail::find_end_impl_ra( -// first1, sprout::next(first1, pivot), first2, last2, pred, -// pivot / 2, last1_, searched, -// first1 -// ) -// ) -// : pivot == 0 ? sprout::detail::search_one(first1, last1_, first2, last2, pred) -// : sprout::detail::find_end_impl_ra( -// sprout::next(first1, pivot), last1, first2, last2, pred, -// (sprout::distance(first1, last1) - pivot) / 2, last1_, result, -// sprout::detail::find_end_impl_ra( -// first1, sprout::next(first1, pivot), first2, last2, pred, -// pivot / 2, last1_, result, -// first1 -// ) -// ) -// ; -// } -// template -// inline SPROUT_CONSTEXPR typename std::enable_if< -// sprout::is_constant_distance_iterator::value, -// RandomAccessIterator1 -// >::type -// find_end( -// RandomAccessIterator1 first1, RandomAccessIterator1 last1, -// ForwardIterator2 first2, ForwardIterator2 last2, -// BinaryPredicate pred, -// std::random_access_iterator_tag* -// ) -// { -// return first1 == last1 ? last1 -// : sprout::detail::find_end_impl_ra( -// first1, last1, first2, last2, pred, -// sprout::distance(first1, last1) / 2, last1, last1, -// first1 -// ) -// ; -// } + template + inline SPROUT_CONSTEXPR RandomAccessIterator1 + find_end_impl_check_ra(RandomAccessIterator1 first1, RandomAccessIterator1 last1_, RandomAccessIterator1 searched) { + return searched == first1 ? searched + : last1_ + ; + } + template + inline SPROUT_CONSTEXPR RandomAccessIterator1 + find_end_impl_ra( + RandomAccessIterator1 first1, RandomAccessIterator1 last1, + RandomAccessIterator2 first2, RandomAccessIterator2 last2, + BinaryPredicate pred, + typename std::iterator_traits::difference_type pivot, RandomAccessIterator1 last1_, + RandomAccessIterator1 searched + ) + { + return searched != last1_ ? searched + : pivot == 0 + ? sprout::detail::find_end_impl_check_ra( + first1, last1_, + sprout::detail::search_one(first1, last1_, first2, last2, pred) + ) + : sprout::detail::find_end_impl_ra( + first1, sprout::next(first1, pivot), first2, last2, pred, + pivot / 2, last1_, + sprout::detail::find_end_impl_ra( + sprout::next(first1, pivot), last1, first2, last2, pred, + (sprout::distance(first1, last1) - pivot) / 2, last1_, + last1_ + ) + ) + ; + } + template + inline SPROUT_CONSTEXPR RandomAccessIterator1 + find_end_impl_ra1( + RandomAccessIterator1 first1, RandomAccessIterator1 last1, + RandomAccessIterator2 first2, RandomAccessIterator2 last2, + BinaryPredicate pred, + typename std::iterator_traits::difference_type len1, + typename std::iterator_traits::difference_type len2 + ) + { + return len1 < len2 ? last1 + : sprout::detail::find_end_impl_ra( + first1, last1 - len2 + 1, first2, last2, pred, + (len1 - len2 + 1) / 2, last1, last1 + ) + ; + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + sprout::is_constant_distance_iterator::value + && sprout::is_constant_distance_iterator::value, + RandomAccessIterator1 + >::type + find_end( + RandomAccessIterator1 first1, RandomAccessIterator1 last1, + RandomAccessIterator2 first2, RandomAccessIterator2 last2, + BinaryPredicate pred, + std::random_access_iterator_tag* + ) + { + return sprout::detail::find_end_impl_ra1( + first1, last1, first2, last2, pred, + sprout::distance(first1, last1), sprout::distance(first2, last2) + ) + ; + } + + template + inline SPROUT_CONSTEXPR sprout::pair + find_end_impl_check_bi( + sprout::pair const& current, + BidirectionalIterator1 first1, sprout::pair searched + ) + { + typedef sprout::pair type; + return searched.second ? type(first1, current.second) + : searched.first == current.first ? type(sprout::prev(current.first), current.second) + : type(current.first, searched.first) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + find_end_impl_bi1( + sprout::pair const& current, + BidirectionalIterator1 first1, BidirectionalIterator1 last1, + BidirectionalIterator2 first2, BidirectionalIterator2 last2, BinaryPredicate pred, + typename std::iterator_traits::difference_type n + ) + { + return current.second != last1 || current.first == first1 ? current + : n == 1 ? sprout::detail::find_end_impl_check_bi( + current, first1, + sprout::detail::search_one_rev(first1, current.first, first2, last2, pred) + ) + : sprout::detail::find_end_impl_bi1( + sprout::detail::find_end_impl_bi1( + current, + first1, last1, first2, last2, pred, n / 2 + ), + first1, last1, first2, last2, pred, n - n / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + find_end_impl_bi( + sprout::pair const& current, + BidirectionalIterator1 first1, BidirectionalIterator1 last1, + BidirectionalIterator2 first2, BidirectionalIterator2 last2, BinaryPredicate pred, + typename std::iterator_traits::difference_type n + ) + { + return current.second != last1 || current.first == first1 ? current + : sprout::detail::find_end_impl_bi( + sprout::detail::find_end_impl_bi1( + current, + first1, last1, first2, last2, pred, n + ), + first1, last1, first2, last2, pred, n * 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR BidirectionalIterator1 + find_end( + BidirectionalIterator1 first1, BidirectionalIterator1 last1, + BidirectionalIterator2 first2, BidirectionalIterator2 last2, + BinaryPredicate pred, + std::bidirectional_iterator_tag* + ) + { + typedef sprout::pair type; + return sprout::detail::find_end_impl_bi(type(last1, last1), first1, last1, first2, last2, pred, 1).second; + } template inline SPROUT_CONSTEXPR sprout::pair @@ -161,8 +235,8 @@ namespace sprout { BinaryPredicate pred ) { - typedef typename std::iterator_traits::iterator_category* category; - return sprout::detail::find_end(first1, last1, first2, last2, pred, category()); + typedef typename sprout::common_iterator_category::type* category; + return first1 == last1 || first2 == last2 ? last1 : sprout::detail::find_end(first1, last1, first2, last2, pred, category()); } template diff --git a/sprout/detail/algorithm/search_one_rev.hpp b/sprout/detail/algorithm/search_one_rev.hpp new file mode 100644 index 00000000..93cd1d85 --- /dev/null +++ b/sprout/detail/algorithm/search_one_rev.hpp @@ -0,0 +1,109 @@ +/*============================================================================= + Copyright (c) 2011-2013 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + 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) +=============================================================================*/ +#ifndef SPROUT_DETAIL_ALGORITHM_SEARCH_ONE_REV_HPP +#define SPROUT_DETAIL_ALGORITHM_SEARCH_ONE_REV_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::tuples::tuple + search_one_rev_impl_1( + sprout::tuples::tuple const& current, + BidirectionalIterator1 first1, BidirectionalIterator2 first2, BinaryPredicate pred, + typename std::iterator_traits::difference_type n + ) + { + typedef sprout::tuples::tuple type; + return sprout::tuples::get<2>(current) ? current + : sprout::tuples::get<1>(current) == first2 ? type(sprout::tuples::get<0>(current), first2, true) + : sprout::tuples::get<0>(current) == first1 ? type(first1, sprout::tuples::get<1>(current), true) + : n == 1 ? pred(*sprout::prev(sprout::tuples::get<0>(current)), *sprout::prev(sprout::tuples::get<1>(current))) + ? type(sprout::prev(sprout::tuples::get<0>(current)), sprout::prev(sprout::tuples::get<1>(current)), false) + : type(sprout::tuples::get<0>(current), sprout::tuples::get<1>(current), true) + : sprout::detail::search_one_rev_impl_1( + sprout::detail::search_one_rev_impl_1( + current, + first1, first2, pred, n / 2 + ), + first1, first2, pred, n - n / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::tuples::tuple + search_one_rev_impl( + sprout::tuples::tuple const& current, + BidirectionalIterator1 first1, BidirectionalIterator2 first2, BinaryPredicate pred, + typename std::iterator_traits::difference_type n + ) + { + typedef sprout::tuples::tuple type; + return sprout::tuples::get<2>(current) ? current + : sprout::tuples::get<1>(current) == first2 ? type(sprout::tuples::get<0>(current), first2, true) + : sprout::tuples::get<0>(current) == first1 ? type(first1, sprout::tuples::get<1>(current), true) + : sprout::detail::search_one_rev_impl( + sprout::detail::search_one_rev_impl_1( + current, + first1, first2, pred, n + ), + first1, first2, pred, n * 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + search_one_rev_check( + sprout::tuples::tuple const& result, + BidirectionalIterator1 first1, BidirectionalIterator1 last1, BidirectionalIterator2 first2 + ) + { + typedef sprout::pair type; + return sprout::tuples::get<1>(result) == first2 ? type(sprout::tuples::get<0>(result), false) + : type(last1, sprout::tuples::get<0>(result) == first1) + ; + } + + // + // search_one_rev + // + // recursion depth: + // O(log(N1+N2)) + // + template + inline SPROUT_CONSTEXPR sprout::pair + search_one_rev( + BidirectionalIterator1 first1, BidirectionalIterator1 last1, + BidirectionalIterator2 first2, BidirectionalIterator2 last2, BinaryPredicate pred + ) + { + typedef sprout::tuples::tuple type; + return sprout::detail::search_one_rev_check( + sprout::detail::search_one_rev_impl(type(last1, last2, false), first1, first2, pred, 1), + first1, last1, first2); + } + template + inline SPROUT_CONSTEXPR sprout::pair + search_one_rev( + BidirectionalIterator1 first1, BidirectionalIterator1 last1, + BidirectionalIterator2 first2, BidirectionalIterator2 last2 + ) + { + return sprout::detail::search_one(first1, last1, first2, last2, sprout::equal_to<>()); + } + } // namespace detail +} // namespace sprout + +#endif // #ifndef SPROUT_DETAIL_ALGORITHM_SEARCH_ONE_REV_HPP