From d6aaabe45f6b7c27f4da91b837d8a7ab4e0c2892 Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Thu, 16 May 2013 18:37:37 +0900 Subject: [PATCH] add equal algorithm: robust version (N3607) --- libs/algorithm/test/equal.cpp | 235 ++++++++++++++++++++++++++++++++++ sprout/algorithm/equal.hpp | 126 +++++++++++++++++- 2 files changed, 360 insertions(+), 1 deletion(-) diff --git a/libs/algorithm/test/equal.cpp b/libs/algorithm/test/equal.cpp index 55a78521..8811c7c6 100644 --- a/libs/algorithm/test/equal.cpp +++ b/libs/algorithm/test/equal.cpp @@ -225,6 +225,241 @@ namespace testspr { TESTSPR_BOTH_ASSERT(result); } #endif + + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr2), + sprout::end(arr2) + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr3), + sprout::end(arr3) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr2), + sprout::begin(arr2) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr3), + sprout::begin(arr3) + 5 + ); + TESTSPR_BOTH_ASSERT(result); + } + + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr2), + sprout::end(arr2), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + sprout::begin(arr1), + sprout::end(arr1), + sprout::begin(arr3), + sprout::end(arr3), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr2), + sprout::begin(arr2), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + sprout::begin(arr3), + sprout::begin(arr3) + 5, + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(result); + } + + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::end(arr1)), + testspr::reduct_input(sprout::begin(arr2)), + testspr::reduct_input(sprout::end(arr2)) + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::end(arr1)), + testspr::reduct_input(sprout::begin(arr3)), + testspr::reduct_input(sprout::end(arr3)) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::begin(arr1) + 5), + testspr::reduct_input(sprout::begin(arr2)), + testspr::reduct_input(sprout::begin(arr2)) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::begin(arr1) + 5), + testspr::reduct_input(sprout::begin(arr3)), + testspr::reduct_input(sprout::begin(arr3) + 5) + ); + TESTSPR_BOTH_ASSERT(result); + } + + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::end(arr1)), + testspr::reduct_input(sprout::begin(arr2)), + testspr::reduct_input(sprout::end(arr2)), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::end(arr1)), + testspr::reduct_input(sprout::begin(arr3)), + testspr::reduct_input(sprout::end(arr3)), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::begin(arr1) + 5), + testspr::reduct_input(sprout::begin(arr2)), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + testspr::reduct_input(sprout::begin(arr1)), + testspr::reduct_input(sprout::begin(arr1) + 5), + testspr::reduct_input(sprout::begin(arr3)), + testspr::reduct_input(sprout::begin(arr3) + 5), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(result); + } + +#if defined(__clang__) + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::end(arr1)), + testspr::reduct_random_access(sprout::begin(arr2)), + testspr::reduct_random_access(sprout::end(arr2)) + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::end(arr1)), + testspr::reduct_random_access(sprout::begin(arr3)), + testspr::reduct_random_access(sprout::end(arr3)) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::begin(arr1) + 5), + testspr::reduct_random_access(sprout::begin(arr2)), + testspr::reduct_random_access(sprout::begin(arr2)) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::begin(arr1) + 5), + testspr::reduct_random_access(sprout::begin(arr3)), + testspr::reduct_random_access(sprout::begin(arr3) + 5) + ); + TESTSPR_BOTH_ASSERT(result); + } + + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::end(arr1)), + testspr::reduct_random_access(sprout::begin(arr2)), + testspr::reduct_random_access(sprout::end(arr2)), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::end(arr1)), + testspr::reduct_random_access(sprout::begin(arr3)), + testspr::reduct_random_access(sprout::end(arr3)), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::begin(arr1) + 5), + testspr::reduct_random_access(sprout::begin(arr2)), + testspr::reduct_random_access(sprout::begin(arr2)), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::equal( + testspr::reduct_random_access(sprout::begin(arr1)), + testspr::reduct_random_access(sprout::begin(arr1) + 5), + testspr::reduct_random_access(sprout::begin(arr3)), + testspr::reduct_random_access(sprout::begin(arr3) + 5), + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(result); + } +#endif } } } // namespace testspr diff --git a/sprout/algorithm/equal.hpp b/sprout/algorithm/equal.hpp index 1999f654..6ae85cf6 100644 --- a/sprout/algorithm/equal.hpp +++ b/sprout/algorithm/equal.hpp @@ -111,12 +111,136 @@ namespace sprout { typedef typename sprout::common_iterator_category::type* category; return sprout::detail::equal(first1, last1, first2, pred, category()); } - template inline SPROUT_CONSTEXPR bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2) { return sprout::equal(first1, last1, first2, sprout::equal_to<>()); } + + namespace detail { + template + inline SPROUT_CONSTEXPR bool + equal_impl_check(InputIterator1 last1, InputIterator2 last2, sprout::tuples::tuple const& current) { + return sprout::tuples::get<2>(current) && sprout::tuples::get<0>(current) == last1 && sprout::tuples::get<1>(current) == last2; + } + + template + inline SPROUT_CONSTEXPR bool + equal2_impl_ra_1( + RandomAccessIterator1 first1, RandomAccessIterator1 last1, RandomAccessIterator2 first2, RandomAccessIterator2 last2, BinaryPredicate pred, + typename std::iterator_traits::difference_type pivot + ) + { + return pivot == 0 ? pred(*first1, *first2) + : sprout::detail::equal2_impl_ra_1( + first1, sprout::next(first1, pivot), first2, sprout::next(first2, pivot), pred, + pivot / 2 + ) + && sprout::detail::equal2_impl_ra_1( + sprout::next(first1, pivot), last1, sprout::next(first2, pivot), last2, pred, + (sprout::distance(first1, last1) - pivot) / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR bool + equal2_impl_ra( + RandomAccessIterator1 first1, RandomAccessIterator1 last1, RandomAccessIterator2 first2, RandomAccessIterator2 last2, BinaryPredicate pred, + typename std::iterator_traits::difference_type size1, typename std::iterator_traits::difference_type size2 + ) + { + return size1 == size2 + && sprout::detail::equal2_impl_ra_1( + first1, last1, first2, last2, pred, + size1 / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + sprout::is_constant_distance_iterator::value && sprout::is_constant_distance_iterator::value, + bool + >::type + equal( + RandomAccessIterator1 first1, RandomAccessIterator1 last1, RandomAccessIterator2 first2, RandomAccessIterator2 last2, BinaryPredicate pred, + std::random_access_iterator_tag* + ) + { + return sprout::detail::equal2_impl_ra( + first1, last1, first2, last2, pred, + sprout::distance(first1, last1), sprout::distance(first2, last2) + ); + } + + template + inline SPROUT_CONSTEXPR sprout::tuples::tuple + equal2_impl_1( + sprout::tuples::tuple const& current, + InputIterator1 last1, InputIterator2 last2, BinaryPredicate pred, typename std::iterator_traits::difference_type n + ) + { + typedef sprout::tuples::tuple type; + return !sprout::tuples::get<2>(current) || sprout::tuples::get<0>(current) == last1 || sprout::tuples::get<1>(current) == last2 ? current + : n == 1 ? pred(*sprout::tuples::get<0>(current), *sprout::tuples::get<1>(current)) + ? type(sprout::next(sprout::tuples::get<0>(current)), sprout::next(sprout::tuples::get<1>(current)), true) + : type(sprout::tuples::get<0>(current), sprout::tuples::get<1>(current), false) + : sprout::detail::equal2_impl_1( + sprout::detail::equal2_impl_1( + current, + last1, last2, pred, n / 2 + ), + last1, last2, pred, n - n / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::tuples::tuple + equal2_impl( + sprout::tuples::tuple const& current, + InputIterator1 last1, InputIterator2 last2, BinaryPredicate pred, typename std::iterator_traits::difference_type n + ) + { + return !sprout::tuples::get<2>(current) || sprout::tuples::get<0>(current) == last1 || sprout::tuples::get<1>(current) == last2 ? current + : sprout::detail::equal2_impl( + sprout::detail::equal2_impl_1( + current, + last1, last2, pred, n + ), + last1, last2, pred, n * 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR bool + equal( + InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred, + std::input_iterator_tag* + ) + { + typedef sprout::tuples::tuple type; + return sprout::detail::equal_impl_check( + last1, last2, + sprout::detail::equal2_impl(type(first1, first2, true), last1, last2, pred, 1) + ); + } + } // namespace detail + + // 25.2.11 Equal + // + // recursion depth: + // O(log N) + // + template + inline SPROUT_CONSTEXPR bool + equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred) { + typedef typename sprout::common_iterator_category::type* category; + return sprout::detail::equal(first1, last1, first2, last2, pred, category()); + } + template + inline SPROUT_CONSTEXPR bool + equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) { + return sprout::equal(first1, last1, first2, last2, sprout::equal_to<>()); + } } // namespace sprout #endif // #ifndef SPROUT_ALGORITHM_EQUAL_HPP