diff --git a/libs/algorithm/test/non_modifying.cpp b/libs/algorithm/test/non_modifying.cpp index 1799a515..033c8043 100644 --- a/libs/algorithm/test/non_modifying.cpp +++ b/libs/algorithm/test/non_modifying.cpp @@ -22,6 +22,7 @@ #include "./equal.cpp" #include "./is_permutation.cpp" #include "./search.cpp" +#include "./search_n.cpp" #ifdef TESTSPR_CPP_INCLUDE_DISABLE_SPROUT_LIBS_ALGORITHM_TEST_NON_MODIFYIING_CPP # undef TESTSPR_CPP_INCLUDE @@ -45,6 +46,7 @@ namespace testspr { testspr::algorithm_equal_test(); testspr::algorithm_is_permutation_test(); testspr::algorithm_search_test(); + testspr::algorithm_search_n_test(); } } // namespace testspr diff --git a/libs/algorithm/test/search_n.cpp b/libs/algorithm/test/search_n.cpp new file mode 100644 index 00000000..65f773ed --- /dev/null +++ b/libs/algorithm/test/search_n.cpp @@ -0,0 +1,101 @@ +#ifndef SPROUT_LIBS_ALGORITHM_TEST_SEARCH_N_CPP +#define SPROUT_LIBS_ALGORITHM_TEST_SEARCH_N_CPP + +#include +#include +#include +#include + +namespace testspr { + static void algorithm_search_n_test() { + using namespace sprout; + { + SPROUT_STATIC_CONSTEXPR auto arr1 = array{{1, 2, 3, 5, 5, 5, 5, 8, 9, 10}}; + + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::search_n( + sprout::begin(arr1), + sprout::end(arr1), + 2, + 5 + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 3); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::search_n( + sprout::begin(arr1), + sprout::end(arr1), + 4, + 5 + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 3); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::search_n( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + 2, + 5 + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 3); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::search_n( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + 4, + 5 + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::search_n( + sprout::begin(arr1), + sprout::end(arr1), + 2, + 5, + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 3); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::search_n( + sprout::begin(arr1), + sprout::end(arr1), + 4, + 5, + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 3); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::search_n( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + 2, + 5, + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 3); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::search_n( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + 4, + 5, + testspr::equal_to() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::algorithm_search_n_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_SEARCH_N_CPP diff --git a/sprout/algorithm/search_n.hpp b/sprout/algorithm/search_n.hpp index b189a2bd..4806b30d 100644 --- a/sprout/algorithm/search_n.hpp +++ b/sprout/algorithm/search_n.hpp @@ -3,33 +3,33 @@ #include #include +#include +#include +#include namespace sprout { - // Copyright (C) 2011 RiSK (sscrisk) - // 25.2.13 Search - template - inline SPROUT_CONSTEXPR ForwardIterator - search_n(ForwardIterator first, ForwardIterator last, Size count, T const& value) { - return first == last || count == 0 ? first - : sprout::next(first) == last && count > 1 ? last - : *first == value - && sprout::search_n(sprout::next(first), last, count - 1, value) == sprout::next(first) - ? first - : sprout::search_n(sprout::next(first), last, count, value) - ; - } - + // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, T const& value, BinaryPredicate pred) { - return first == last || count == 0 ? first - : sprout::next(first) == last && count > 1 ? last - : *first == value - && sprout::search_n(sprout::next(first), last, count - 1, value, pred) == sprout::next(first) - ? first - : sprout::search_n(sprout::next(first), last, count, value, pred) - ; + typedef sprout::value_iterator iterator; + typedef typename iterator::difference_type difference_type; + return sprout::search( + first, last, + iterator(value, static_cast(count)), iterator(value, 0), + pred + ); + } + + template + inline SPROUT_CONSTEXPR ForwardIterator + search_n(ForwardIterator first, ForwardIterator last, Size count, T const& value) { + return sprout::search_n(first, last, count, value, sprout::equal_to<>()); } } // namespace sprout