fix rexursion depth: is_pertitioned, partition_point, is_sorted, is_sorted_until

This commit is contained in:
bolero-MURAKAMI 2012-12-15 17:41:20 +09:00
parent d6914ddd72
commit eea1c2bbc1
12 changed files with 410 additions and 50 deletions

View file

@ -0,0 +1,56 @@
#ifndef SPROUT_LIBS_ALGORITHM_TEST_IS_PERTITIONED_CPP
#define SPROUT_LIBS_ALGORITHM_TEST_IS_PERTITIONED_CPP
#include <sprout/algorithm/is_partitioned.hpp>
#include <sprout/array.hpp>
#include <sprout/container.hpp>
#include <testspr/tools.hpp>
namespace testspr {
static void algorithm_is_partitioned_test() {
using namespace sprout;
{
SPROUT_STATIC_CONSTEXPR auto arr1 = array<int, 10>{{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}};
{
SPROUT_STATIC_CONSTEXPR auto result = sprout::is_partitioned(
sprout::begin(arr1),
sprout::end(arr1),
testspr::is_odd<int>()
);
TESTSPR_BOTH_ASSERT(result);
}
{
SPROUT_STATIC_CONSTEXPR auto result = sprout::is_partitioned(
sprout::begin(arr1),
sprout::end(arr1),
testspr::less_than<int>(6)
);
TESTSPR_BOTH_ASSERT(!result);
}
{
SPROUT_STATIC_CONSTEXPR auto result = sprout::is_partitioned(
sprout::begin(arr1),
sprout::begin(arr1) + 5,
testspr::is_odd<int>()
);
TESTSPR_BOTH_ASSERT(result);
}
{
SPROUT_STATIC_CONSTEXPR auto result = sprout::is_partitioned(
sprout::begin(arr1),
sprout::begin(arr1) + 5,
testspr::less_than<int>(6)
);
TESTSPR_BOTH_ASSERT(result);
}
}
}
} // namespace testspr
#ifndef TESTSPR_CPP_INCLUDE
# define TESTSPR_TEST_FUNCTION testspr::algorithm_is_partitioned_test
# include <testspr/include_main.hpp>
#endif
#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_IS_PERTITIONED_CPP

View file

@ -0,0 +1,54 @@
#ifndef SPROUT_LIBS_ALGORITHM_TEST_IS_SORTED_CPP
#define SPROUT_LIBS_ALGORITHM_TEST_IS_SORTED_CPP
#include <sprout/algorithm/is_sorted.hpp>
#include <sprout/array.hpp>
#include <sprout/container.hpp>
#include <testspr/tools.hpp>
namespace testspr {
static void algorithm_is_sorted_test() {
using namespace sprout;
{
SPROUT_STATIC_CONSTEXPR auto arr1 = array<int, 10>{{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}};
{
SPROUT_STATIC_CONSTEXPR auto result = sprout::is_sorted(
sprout::begin(arr1),
sprout::end(arr1)
);
TESTSPR_BOTH_ASSERT(!result);
}
{
SPROUT_STATIC_CONSTEXPR auto result = sprout::is_sorted(
sprout::begin(arr1),
sprout::begin(arr1) + 5
);
TESTSPR_BOTH_ASSERT(result);
}
{
SPROUT_STATIC_CONSTEXPR auto result = sprout::is_sorted(
sprout::begin(arr1),
sprout::end(arr1),
testspr::less<int>()
);
TESTSPR_BOTH_ASSERT(!result);
}
{
SPROUT_STATIC_CONSTEXPR auto result = sprout::is_sorted(
sprout::begin(arr1),
sprout::begin(arr1) + 5,
testspr::less<int>()
);
TESTSPR_BOTH_ASSERT(result);
}
}
}
} // namespace testspr
#ifndef TESTSPR_CPP_INCLUDE
# define TESTSPR_TEST_FUNCTION testspr::algorithm_is_sorted_test
# include <testspr/include_main.hpp>
#endif
#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_IS_SORTED_CPP

View file

@ -0,0 +1,54 @@
#ifndef SPROUT_LIBS_ALGORITHM_TEST_IS_SORTED_UNTIL_CPP
#define SPROUT_LIBS_ALGORITHM_TEST_IS_SORTED_UNTIL_CPP
#include <sprout/algorithm/is_sorted_until.hpp>
#include <sprout/array.hpp>
#include <sprout/container.hpp>
#include <testspr/tools.hpp>
namespace testspr {
static void algorithm_is_sorted_until_test() {
using namespace sprout;
{
SPROUT_STATIC_CONSTEXPR auto arr1 = array<int, 10>{{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}};
{
SPROUT_STATIC_CONSTEXPR auto found = sprout::is_sorted_until(
sprout::begin(arr1),
sprout::end(arr1)
);
TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5);
}
{
SPROUT_STATIC_CONSTEXPR auto found = sprout::is_sorted_until(
sprout::begin(arr1),
sprout::begin(arr1) + 5
);
TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5);
}
{
SPROUT_STATIC_CONSTEXPR auto found = sprout::is_sorted_until(
sprout::begin(arr1),
sprout::end(arr1),
testspr::less<int>()
);
TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5);
}
{
SPROUT_STATIC_CONSTEXPR auto found = sprout::is_sorted_until(
sprout::begin(arr1),
sprout::begin(arr1) + 5,
testspr::less<int>()
);
TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5);
}
}
}
} // namespace testspr
#ifndef TESTSPR_CPP_INCLUDE
# define TESTSPR_TEST_FUNCTION testspr::algorithm_is_sorted_until_test
# include <testspr/include_main.hpp>
#endif
#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_IS_SORTED_UNTIL_CPP

View file

@ -23,6 +23,10 @@
#include "./is_permutation.cpp"
#include "./search.cpp"
#include "./search_n.cpp"
#include "./is_partitioned.cpp"
#include "./partition_point.cpp"
#include "./is_sorted.cpp"
#include "./is_sorted_until.cpp"
#ifdef TESTSPR_CPP_INCLUDE_DISABLE_SPROUT_LIBS_ALGORITHM_TEST_NON_MODIFYIING_CPP
# undef TESTSPR_CPP_INCLUDE
@ -47,6 +51,10 @@ namespace testspr {
testspr::algorithm_is_permutation_test();
testspr::algorithm_search_test();
testspr::algorithm_search_n_test();
testspr::algorithm_is_partitioned_test();
testspr::algorithm_partition_point_test();
testspr::algorithm_is_sorted_test();
testspr::algorithm_is_sorted_until_test();
}
} // namespace testspr

View file

@ -0,0 +1,40 @@
#ifndef SPROUT_LIBS_ALGORITHM_TEST_PERTITION_POINT_CPP
#define SPROUT_LIBS_ALGORITHM_TEST_PERTITION_POINT_CPP
#include <sprout/algorithm/partition_point.hpp>
#include <sprout/array.hpp>
#include <sprout/container.hpp>
#include <testspr/tools.hpp>
namespace testspr {
static void algorithm_partition_point_test() {
using namespace sprout;
{
SPROUT_STATIC_CONSTEXPR auto arr1 = array<int, 10>{{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}};
{
SPROUT_STATIC_CONSTEXPR auto found = sprout::partition_point(
sprout::begin(arr1),
sprout::end(arr1),
testspr::is_odd<int>()
);
TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5);
}
{
SPROUT_STATIC_CONSTEXPR auto found = sprout::partition_point(
sprout::begin(arr1),
sprout::begin(arr1) + 5,
testspr::is_odd<int>()
);
TESTSPR_BOTH_ASSERT(found == sprout::begin(arr1) + 5);
}
}
}
} // namespace testspr
#ifndef TESTSPR_CPP_INCLUDE
# define TESTSPR_TEST_FUNCTION testspr::algorithm_partition_point_test
# include <testspr/include_main.hpp>
#endif
#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_PERTITION_POINT_CPP

View file

@ -4,6 +4,7 @@
#include <iterator>
#include <sprout/config.hpp>
#include <sprout/iterator/operation.hpp>
#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT
#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT
namespace sprout {

View file

@ -6,9 +6,17 @@
#include <sprout/algorithm/search.hpp>
#include <sprout/functional/equal_to.hpp>
#include <sprout/detail/algorithm/search_one.hpp>
#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT
namespace sprout {
namespace detail {
template<typename RandomAccessIterator1>
inline SPROUT_CONSTEXPR RandomAccessIterator1
find_end_impl_ra_1(RandomAccessIterator1 first1, RandomAccessIterator1 result, RandomAccessIterator1 searched) {
return searched == first1 ? searched
: result
;
}
template<typename RandomAccessIterator1, typename ForwardIterator2, typename BinaryPredicate>
inline SPROUT_CONSTEXPR RandomAccessIterator1
find_end_impl_ra(
@ -19,16 +27,21 @@ namespace sprout {
RandomAccessIterator1 searched
)
{
return searched < first1 ? sprout::detail::find_end_impl_ra(
sprout::next(first1, pivot), last1, first2, last2, pred,
(NS_SSCRISK_CEL_OR_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
return searched == last1_ ? result
: searched < first1 ? pivot == 0
? sprout::detail::find_end_impl_ra_1(
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,
(NS_SSCRISK_CEL_OR_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
)
)
)
: searched == last1_ ? result
: 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,

View file

@ -2,28 +2,20 @@
#define SPROUT_ALGORITHM_IS_PARTITIONED_HPP
#include <sprout/config.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/algorithm/none_of.hpp>
#include <sprout/algorithm/find_if_not.hpp>
namespace sprout {
// Copyright (C) 2011 RiSK (sscrisk)
namespace detail {
template<typename InputIterator, typename Predicate>
inline SPROUT_CONSTEXPR bool
is_partitioned_impl(InputIterator first, InputIterator last, Predicate pred, bool cond = true) {
return first == last ? true
: cond ? sprout::detail::is_partitioned_impl(sprout::next(first), last, pred, pred(*first))
: pred(*first) ? false
: sprout::detail::is_partitioned_impl(sprout::next(first), last, pred, false)
;
}
} // namespace detail
// 25.3.13 Partitions
//
// recursion depth:
// [first, last) is RandomAccessIterator -> O(log N)
// otherwise -> O(N)
//
template<typename InputIterator, typename Predicate>
inline SPROUT_CONSTEXPR bool
is_partitioned(InputIterator first, InputIterator last, Predicate pred) {
return sprout::detail::is_partitioned_impl(first, last, pred);
return sprout::none_of(sprout::find_if_not(first, last, pred), last, pred);
}
} // namespace sprout

View file

@ -1,23 +1,75 @@
#ifndef SPROUT_ALGORITHM_IS_SORTED_HPP
#define SPROUT_ALGORITHM_IS_SORTED_HPP
#include <iterator>
#include <sprout/config.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/algorithm/is_sorted_until.hpp>
#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT
#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT
namespace sprout {
// Copyright (C) 2011 RiSK (sscrisk)
namespace detail {
template<typename RandomAccessIterator, typename Compare>
inline SPROUT_CONSTEXPR bool
is_sorted_impl_ra(
RandomAccessIterator first, RandomAccessIterator last, Compare comp,
typename std::iterator_traits<RandomAccessIterator>::difference_type pivot
)
{
return pivot == 0 ? !comp(*last, *first)
: sprout::detail::is_sorted_impl_ra(
first, sprout::next(first, pivot), comp,
pivot / 2
)
&& sprout::detail::is_sorted_impl_ra(
sprout::next(first, pivot), last, comp,
(NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) - pivot) / 2
)
;
}
template<typename RandomAccessIterator, typename Compare>
inline SPROUT_CONSTEXPR bool
is_sorted(
RandomAccessIterator first, RandomAccessIterator last, Compare comp,
std::random_access_iterator_tag*
)
{
return first == last || NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) == 1 ? true
: sprout::detail::is_sorted_impl_ra(
first, sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) - 1), comp,
(NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) - 1) / 2
)
;
}
// Copyright (C) 2011 RiSK (sscrisk)
template<typename ForwardIterator, typename Compare>
inline SPROUT_CONSTEXPR bool
is_sorted(
ForwardIterator first, ForwardIterator last, Compare comp,
void*
)
{
return sprout::is_sorted_until(first, last, comp) == last;
}
} //namespace detail
// 25.4.1.5 is_sorted
template<typename ForwardIterator>
inline SPROUT_CONSTEXPR bool
is_sorted(ForwardIterator first, ForwardIterator last) {
return sprout::is_sorted_until(first, last) == last;
}
template<typename ForwardIterator, typename Compare>
inline SPROUT_CONSTEXPR bool
is_sorted(ForwardIterator first, ForwardIterator last, Compare comp) {
return sprout::is_sorted_until(first, last, comp) == last;
typedef typename std::iterator_traits<ForwardIterator>::iterator_category* category;
return sprout::detail::is_sorted(first, last, comp, category());
}
template<typename ForwardIterator>
inline SPROUT_CONSTEXPR bool
is_sorted(ForwardIterator first, ForwardIterator last) {
return sprout::is_sorted(
first, last,
NS_SSCRISK_CEL_OR_SPROUT::less<typename std::iterator_traits<ForwardIterator>::value_type>()
);
}
} // namespace sprout

View file

@ -1,29 +1,88 @@
#ifndef SPROUT_ALGORITHM_IS_SORTED_UNTIL_HPP
#define SPROUT_ALGORITHM_IS_SORTED_UNTIL_HPP
#include <iterator>
#include <sprout/config.hpp>
#include <sprout/iterator/operation.hpp>
#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT
#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT
namespace sprout {
// Copyright (C) 2011 RiSK (sscrisk)
namespace detail {
template<typename RandomAccessIterator, typename Compare>
inline SPROUT_CONSTEXPR RandomAccessIterator
is_sorted_until_impl_ra(
RandomAccessIterator first, RandomAccessIterator last, Compare comp,
typename std::iterator_traits<RandomAccessIterator>::difference_type pivot, RandomAccessIterator found
)
{
return found != first ? found
: pivot == 0 ? (comp(*last, *first) ? first : last)
: sprout::detail::is_sorted_until_impl_ra(
sprout::next(first, pivot), last, comp,
(NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) - pivot) / 2,
sprout::detail::is_sorted_until_impl_ra(
first, sprout::next(first, pivot), comp,
pivot / 2,
first
)
)
;
}
template<typename RandomAccessIterator, typename Compare>
inline SPROUT_CONSTEXPR RandomAccessIterator
is_sorted_until(
RandomAccessIterator first, RandomAccessIterator last, Compare comp,
std::random_access_iterator_tag*
)
{
return first == last || NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) == 1 ? last
: sprout::next(
sprout::detail::is_sorted_until_impl_ra(
first, sprout::next(first, NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) - 1), comp,
(NS_SSCRISK_CEL_OR_SPROUT::distance(first, last) - 1) / 2, first
)
)
;
}
// Copyright (C) 2011 RiSK (sscrisk)
template<typename ForwardIterator, typename Compare>
inline SPROUT_CONSTEXPR ForwardIterator
is_sorted_until_impl(ForwardIterator first, ForwardIterator next, ForwardIterator last, Compare comp) {
return next == last ? last
: comp(*next, *first) ? first
: sprout::detail::is_sorted_until_impl(next, sprout::next(next), last, comp)
;
}
template<typename ForwardIterator, typename Compare>
inline SPROUT_CONSTEXPR ForwardIterator
is_sorted_until(
ForwardIterator first, ForwardIterator last, Compare comp,
void*
)
{
return first == last ? last
: sprout::detail::is_sorted_until_impl(first, sprout::next(first), last, comp)
;
}
} //namespace detail
// 25.4.1.5 is_sorted
template<typename ForwardIterator>
inline SPROUT_CONSTEXPR ForwardIterator
is_sorted_until(ForwardIterator first, ForwardIterator last) {
return first == last || sprout::next(first) == last ? last
: *(sprout::next(first)) < *first ? sprout::next(first)
: sprout::is_sorted_until(sprout::next(first), last)
;
}
template<typename ForwardIterator, typename Compare>
inline SPROUT_CONSTEXPR ForwardIterator
is_sorted_until(ForwardIterator first, ForwardIterator last, Compare comp) {
return first == last || sprout::next(first) == last ? last
: comp(*(sprout::next(first)), *first) ? sprout::next(first)
: sprout::is_sorted_until(sprout::next(first), last)
;
typedef typename std::iterator_traits<ForwardIterator>::iterator_category* category;
return sprout::detail::is_sorted_until(first, last, comp, category());
}
template<typename ForwardIterator>
inline SPROUT_CONSTEXPR ForwardIterator
is_sorted_until(ForwardIterator first, ForwardIterator last) {
return sprout::is_sorted_until(
first, last,
NS_SSCRISK_CEL_OR_SPROUT::less<typename std::iterator_traits<ForwardIterator>::value_type>()
);
}
} // namespace sprout

View file

@ -26,6 +26,11 @@ namespace sprout {
} // namespace detail
// 25.3.13 Partitions
//
// recursion depth:
// [first, last) is RandomAccessIterator -> O(log N)
// otherwise -> O(N)
//
template<typename ForwardIterator, typename Predicate>
inline SPROUT_CONSTEXPR ForwardIterator
partition_point(ForwardIterator first, ForwardIterator last, Predicate pred) {

View file

@ -2,6 +2,7 @@
#define SPROUT_ITERATOR_DISTANCE_HPP
#include <iterator>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/iterator/next.hpp>
#include <sprout/adl/not_found.hpp>
@ -12,14 +13,34 @@ namespace sprout_adl {
namespace sprout {
namespace iterator_detail {
template<typename RandomAccessIterator>
inline SPROUT_CONSTEXPR typename std::enable_if<
!std::is_pointer<RandomAccessIterator>::value,
typename std::iterator_traits<RandomAccessIterator>::difference_type
>::type
iterator_distance(RandomAccessIterator first, RandomAccessIterator last, std::random_access_iterator_tag*) {
return last - first;
}
// Copyright (C) 2011 RiSK (sscrisk)
template<typename InputIterator>
inline SPROUT_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type
iterator_distance_impl(InputIterator first, InputIterator last) {
return first == last ? 0
: 1 + sprout::iterator_detail::iterator_distance_impl(sprout::next(first), last)
;
}
template<typename InputIterator>
inline SPROUT_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type
iterator_distance(InputIterator first, InputIterator last, void*) {
return sprout::iterator_detail::iterator_distance_impl(first, last);
}
template<typename InputIterator>
inline SPROUT_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type
iterator_distance(InputIterator first, InputIterator last) {
return first == last ? 0
: 1 + sprout::iterator_detail::iterator_distance(sprout::next(first), last)
;
typedef typename std::iterator_traits<InputIterator>::iterator_category* category;
return sprout::iterator_detail::iterator_distance(first, last, category());
}
} // namespace iterator_detail
} // namespace sprout
@ -38,6 +59,11 @@ namespace sprout {
//
// distance
//
// effect:
// ADL callable iterator_distance(first, last) -> iterator_distance(first, last)
// [first, last) is RandomAccessIterator && not Pointer -> last - first
// otherwise -> linearly count: first to last
//
template<typename InputIterator>
inline SPROUT_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type
distance(InputIterator first, InputIterator last) {