/*============================================================================= Copyright (c) 2011-2019 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_ALGORITHM_FIND_DIFFERENCE_HPP #define SPROUT_ALGORITHM_FIND_DIFFERENCE_HPP #include #include #include #include #include #include #include #include namespace sprout { namespace detail { template inline SPROUT_CONSTEXPR sprout::pair find_difference_impl_check( sprout::tuples::tuple const& current, InputIterator1 last1, InputIterator2 last2 ) { return sprout::tuples::get<2>(current) ? sprout::pair( sprout::tuples::get<0>(current), sprout::tuples::get<1>(current) ) : sprout::pair(last1, last2) ; } template inline SPROUT_CONSTEXPR sprout::tuples::tuple find_difference_impl_1( sprout::tuples::tuple const& current, InputIterator1 last1, InputIterator2 last2, Compare comp, typename std::iterator_traits::difference_type n ) { typedef sprout::tuples::tuple type; return sprout::tuples::get<2>(current) || sprout::tuples::get<0>(current) == last1 ? current : n == 1 ? sprout::tuples::get<1>(current) == last2 ? type(sprout::tuples::get<0>(current), sprout::tuples::get<1>(current), true) : comp(*sprout::tuples::get<0>(current), *sprout::tuples::get<1>(current)) ? type(sprout::tuples::get<0>(current), sprout::tuples::get<1>(current), true) : comp(*sprout::tuples::get<1>(current), *sprout::tuples::get<0>(current)) ? type(sprout::tuples::get<0>(current), sprout::next(sprout::tuples::get<1>(current)), false) : type(sprout::next(sprout::tuples::get<0>(current)), sprout::next(sprout::tuples::get<1>(current)), false) : sprout::detail::find_difference_impl_1( sprout::detail::find_difference_impl_1( current, last1, last2, comp, n / 2 ), last1, last2, comp, n - n / 2 ) ; } template inline SPROUT_CONSTEXPR sprout::tuples::tuple find_difference_impl( sprout::tuples::tuple const& current, InputIterator1 last1, InputIterator2 last2, Compare comp, typename std::iterator_traits::difference_type n ) { return sprout::tuples::get<2>(current) || sprout::tuples::get<0>(current) == last1 ? current : sprout::detail::find_difference_impl( sprout::detail::find_difference_impl_1( current, last1, last2, comp, n ), last1, last2, comp, n * 2 ) ; } template inline SPROUT_CONSTEXPR sprout::pair find_difference( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp ) { typedef sprout::tuples::tuple type; return sprout::detail::find_difference_impl_check( sprout::detail::find_difference_impl(type(first1, first2, false), last1, last2, comp, 1), last1, last2 ); } } // namespace detail // // find_difference // // recursion depth: // O(log N) // template inline SPROUT_CONSTEXPR sprout::pair find_difference( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp ) { return sprout::detail::find_difference(first1, last1, first2, last2, comp); } template inline SPROUT_CONSTEXPR sprout::pair find_difference( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2 ) { return sprout::find_difference(first1, last1, first2, last2, sprout::less<>()); } } // namespace sprout #endif // #ifndef SPROUT_ALGORITHM_FIND_DIFFERENCE_HPP