diff --git a/libs/algorithm/test/is_heap.cpp b/libs/algorithm/test/is_heap.cpp new file mode 100644 index 00000000..1f175f36 --- /dev/null +++ b/libs/algorithm/test/is_heap.cpp @@ -0,0 +1,85 @@ +#ifndef SPROUT_LIBS_ALGORITHM_TEST_IS_HEAP_CPP +#define SPROUT_LIBS_ALGORITHM_TEST_IS_HEAP_CPP + +#include +#include +#include +#include + +namespace testspr { + static void algorithm_is_heap_test() { + using namespace sprout; + { + SPROUT_STATIC_CONSTEXPR auto arr1 = array{{10, 9, 8, 6, 7, 2, 5, 3, 4, 1}}; + SPROUT_STATIC_CONSTEXPR auto arr2 = array{{10, 9, 8, 6, 7, 2, 5, 13, 14, 11}}; + + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_heap( + sprout::begin(arr1), + sprout::end(arr1) + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_heap( + sprout::begin(arr2), + sprout::end(arr2) + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_heap( + sprout::begin(arr1), + sprout::begin(arr1) + 5 + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_heap( + sprout::begin(arr2), + sprout::begin(arr2) + 5 + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_heap( + sprout::begin(arr1), + sprout::end(arr1), + testspr::less() + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_heap( + sprout::begin(arr2), + sprout::end(arr2), + testspr::less() + ); + TESTSPR_BOTH_ASSERT(!result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_heap( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + testspr::less() + ); + TESTSPR_BOTH_ASSERT(result); + } + { + SPROUT_STATIC_CONSTEXPR auto result = sprout::is_heap( + sprout::begin(arr2), + sprout::begin(arr2) + 5, + testspr::less() + ); + TESTSPR_BOTH_ASSERT(result); + } + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::algorithm_is_heap_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_IS_HEAP_CPP diff --git a/libs/algorithm/test/is_heap_until.cpp b/libs/algorithm/test/is_heap_until.cpp new file mode 100644 index 00000000..8c391097 --- /dev/null +++ b/libs/algorithm/test/is_heap_until.cpp @@ -0,0 +1,85 @@ +#ifndef SPROUT_LIBS_ALGORITHM_TEST_IS_HEAP_UNTIL_CPP +#define SPROUT_LIBS_ALGORITHM_TEST_IS_HEAP_UNTIL_CPP + +#include +#include +#include +#include + +namespace testspr { + static void algorithm_is_heap_until_test() { + using namespace sprout; + { + SPROUT_STATIC_CONSTEXPR auto arr1 = array{{10, 9, 8, 6, 7, 2, 5, 3, 4, 1}}; + SPROUT_STATIC_CONSTEXPR auto arr2 = array{{10, 9, 8, 6, 7, 2, 5, 13, 14, 11}}; + + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::is_heap_until( + sprout::begin(arr1), + sprout::end(arr1) + ); + TESTSPR_BOTH_ASSERT(found == sprout::end(arr1)); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::is_heap_until( + sprout::begin(arr2), + sprout::end(arr2) + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 7); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::is_heap_until( + sprout::begin(arr1), + sprout::begin(arr1) + 5 + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::is_heap_until( + sprout::begin(arr2), + sprout::begin(arr2) + 5 + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr2) + 5); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::is_heap_until( + sprout::begin(arr1), + sprout::end(arr1), + testspr::less() + ); + TESTSPR_BOTH_ASSERT(found == sprout::end(arr1)); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::is_heap_until( + sprout::begin(arr2), + sprout::end(arr2), + testspr::less() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr2) + 7); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::is_heap_until( + sprout::begin(arr1), + sprout::begin(arr1) + 5, + testspr::less() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5); + } + { + SPROUT_STATIC_CONSTEXPR auto found = sprout::is_heap_until( + sprout::begin(arr2), + sprout::begin(arr2) + 5, + testspr::less() + ); + TESTSPR_BOTH_ASSERT(found == sprout::begin(arr2) + 5); + } + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::algorithm_is_heap_until_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_IS_HEAP_UNTIL_CPP diff --git a/libs/algorithm/test/non_modifying.cpp b/libs/algorithm/test/non_modifying.cpp index ce492e87..6ab3a541 100644 --- a/libs/algorithm/test/non_modifying.cpp +++ b/libs/algorithm/test/non_modifying.cpp @@ -32,6 +32,8 @@ #include "./equal_range.cpp" #include "./binary_search.cpp" #include "./includes.cpp" +#include "./is_heap.cpp" +#include "./is_heap_until.cpp" #ifdef TESTSPR_CPP_INCLUDE_DISABLE_SPROUT_LIBS_ALGORITHM_TEST_NON_MODIFYIING_CPP # undef TESTSPR_CPP_INCLUDE @@ -65,6 +67,8 @@ namespace testspr { testspr::algorithm_equal_range_test(); testspr::algorithm_binary_search_test(); testspr::algorithm_includes_test(); + testspr::algorithm_is_heap_test(); + testspr::algorithm_is_heap_until_test(); } } // namespace testspr diff --git a/sprout/algorithm/is_heap.hpp b/sprout/algorithm/is_heap.hpp index 3a94db24..bcf6dc8d 100644 --- a/sprout/algorithm/is_heap.hpp +++ b/sprout/algorithm/is_heap.hpp @@ -1,24 +1,33 @@ #ifndef SPROUT_ALGORITHM_IS_HEAP_HPP #define SPROUT_ALGORITHM_IS_HEAP_HPP +#include #include #include +#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT namespace sprout { // Copyright (C) 2011 RiSK (sscrisk) // 25.4.6.5 is_heap - template - inline SPROUT_CONSTEXPR bool - is_heap(RandomAccessIterator first, RandomAccessIterator last) { - return sprout::is_heap_until(first, last) == last; - } - + // + // recursion depth: + // O(log N) + // template inline SPROUT_CONSTEXPR bool is_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp) { return sprout::is_heap_until(first, last, comp) == last; } + + template + inline SPROUT_CONSTEXPR bool + is_heap(RandomAccessIterator first, RandomAccessIterator last) { + return sprout::is_heap( + first, last, + NS_SSCRISK_CEL_OR_SPROUT::less::value_type>() + ); + } } // namespace sprout #endif // #ifndef SPROUT_ALGORITHM_IS_HEAP_HPP diff --git a/sprout/algorithm/is_heap_until.hpp b/sprout/algorithm/is_heap_until.hpp index feece426..48ccbd11 100644 --- a/sprout/algorithm/is_heap_until.hpp +++ b/sprout/algorithm/is_heap_until.hpp @@ -1,42 +1,70 @@ #ifndef SPROUT_ALGORITHM_IS_HEAP_UNTIL_HPP #define SPROUT_ALGORITHM_IS_HEAP_UNTIL_HPP -#include +#include #include #include #include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT #include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT namespace sprout { - // Copyright (C) 2011 RiSK (sscrisk) - namespace detail { + template + inline SPROUT_CONSTEXPR typename std::iterator_traits::difference_type + is_heap_until_impl( + RandomAccessIterator it, Compare comp, + typename std::iterator_traits::difference_type first, typename std::iterator_traits::difference_type last, + typename std::iterator_traits::difference_type pivot, typename std::iterator_traits::difference_type found + ) + { + return found != first ? found + : pivot == 0 ? (!comp(it[first], it[(first - 1) / 2]) ? first : last) + : sprout::detail::is_heap_until_impl( + it, comp, first + pivot, last, + ((last - first) - pivot) / 2, + sprout::detail::is_heap_until_impl( + it, comp, first, first + pivot, + pivot / 2, + first + ) + ) + ; + } + template inline SPROUT_CONSTEXPR RandomAccessIterator is_heap_until_impl( RandomAccessIterator first, RandomAccessIterator last, Compare comp, - std::size_t n + typename std::iterator_traits::difference_type size ) { - return sprout::next(first, n) == last || !comp(first[n], first[(n - 1) / 2]) ? sprout::next(first, n) - : sprout::detail::is_heap_until_impl(first, last, comp, n + 1) + return size < 2 ? last + : sprout::next(first, sprout::detail::is_heap_until_impl(first, comp, 1, size, (size - 1) / 2, 1)) ; } } // namespace detail // 25.4.6.5 is_heap - template - inline SPROUT_CONSTEXPR RandomAccessIterator - is_heap_until(RandomAccessIterator first, RandomAccessIterator last) { - return sprout::is_heap_until(first, last, NS_SSCRISK_CEL_OR_SPROUT::less()); - } - + // + // recursion depth: + // O(log N) + // template inline SPROUT_CONSTEXPR RandomAccessIterator is_heap_until(RandomAccessIterator first, RandomAccessIterator last, Compare comp) { - return NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) < 2 ? last - : sprout::detail::is_heap_until_impl(first, last, comp, 1) - ; + return sprout::detail::is_heap_until_impl( + first, last, comp, + NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) + ); + } + + template + inline SPROUT_CONSTEXPR RandomAccessIterator + is_heap_until(RandomAccessIterator first, RandomAccessIterator last) { + return sprout::is_heap_until( + first, last, + NS_SSCRISK_CEL_OR_SPROUT::less::value_type>() + ); } } // namespace sprout