diff --git a/sprout/algorithm/adjacent_find.hpp b/sprout/algorithm/adjacent_find.hpp index 66fd912b..b5e991ab 100644 --- a/sprout/algorithm/adjacent_find.hpp +++ b/sprout/algorithm/adjacent_find.hpp @@ -76,6 +76,11 @@ namespace sprout { } //namespace detail // 25.2.8 Adjacent find + // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last, BinaryPredicate pred) { diff --git a/sprout/algorithm/all_of.hpp b/sprout/algorithm/all_of.hpp index a7bfcf06..b6e3c07b 100644 --- a/sprout/algorithm/all_of.hpp +++ b/sprout/algorithm/all_of.hpp @@ -58,6 +58,11 @@ namespace sprout { } //namespace detail // 25.2.1 All of + // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR bool all_of(InputIterator first, InputIterator last, Predicate pred) { diff --git a/sprout/algorithm/any_of.hpp b/sprout/algorithm/any_of.hpp index c469e474..759d9668 100644 --- a/sprout/algorithm/any_of.hpp +++ b/sprout/algorithm/any_of.hpp @@ -58,6 +58,11 @@ namespace sprout { } //namespace detail // 25.2.2 Any of + // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR bool any_of(InputIterator first, InputIterator last, Predicate pred) { diff --git a/sprout/algorithm/count.hpp b/sprout/algorithm/count.hpp index 2a2ba6e2..44c416c1 100644 --- a/sprout/algorithm/count.hpp +++ b/sprout/algorithm/count.hpp @@ -58,6 +58,11 @@ namespace sprout { } //namespace detail // 25.2.9 Count + // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR typename std::iterator_traits::difference_type count(InputIterator first, InputIterator last, T const& value) { diff --git a/sprout/algorithm/count_if.hpp b/sprout/algorithm/count_if.hpp index e49f9b77..85d4be22 100644 --- a/sprout/algorithm/count_if.hpp +++ b/sprout/algorithm/count_if.hpp @@ -58,6 +58,11 @@ namespace sprout { } //namespace detail // 25.2.9 Count + // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR typename std::iterator_traits::difference_type count_if(InputIterator first, InputIterator last, Predicate pred) { diff --git a/sprout/algorithm/equal.hpp b/sprout/algorithm/equal.hpp index daabd085..b9dee566 100644 --- a/sprout/algorithm/equal.hpp +++ b/sprout/algorithm/equal.hpp @@ -62,6 +62,11 @@ namespace sprout { } //namespace detail // 25.2.11 Equal + // + // recursion depth: + // [first1, last1), first2 are RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate pred) { diff --git a/sprout/algorithm/find.hpp b/sprout/algorithm/find.hpp index b6a01719..d2f2cf5a 100644 --- a/sprout/algorithm/find.hpp +++ b/sprout/algorithm/find.hpp @@ -60,6 +60,11 @@ namespace sprout { } //namespace detail // 25.2.5 Find + // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR InputIterator find(InputIterator first, InputIterator last, T const& value) { diff --git a/sprout/algorithm/find_first_of.hpp b/sprout/algorithm/find_first_of.hpp index 2ddd934f..9d09bacf 100644 --- a/sprout/algorithm/find_first_of.hpp +++ b/sprout/algorithm/find_first_of.hpp @@ -77,6 +77,13 @@ namespace sprout { } //namespace detail // 25.2.7 Find first + // + // recursion depth: + // [first1, last1) is RandomAccessIterator -> O(log N1) + // otherwise -> O(N1) + // [first2, last2) is RandomAccessIterator -> O(log N2) + // otherwise -> O(N2) + // template inline SPROUT_CONSTEXPR InputIterator1 find_first_of( diff --git a/sprout/algorithm/find_if.hpp b/sprout/algorithm/find_if.hpp index 052353da..0c8bb621 100644 --- a/sprout/algorithm/find_if.hpp +++ b/sprout/algorithm/find_if.hpp @@ -60,6 +60,11 @@ namespace sprout { } //namespace detail // 25.2.5 Find + // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR InputIterator find_if(InputIterator first, InputIterator last, Predicate pred) { diff --git a/sprout/algorithm/find_if_not.hpp b/sprout/algorithm/find_if_not.hpp index da3db726..07e98eb1 100644 --- a/sprout/algorithm/find_if_not.hpp +++ b/sprout/algorithm/find_if_not.hpp @@ -60,6 +60,11 @@ namespace sprout { } //namespace detail // 25.2.5 Find + // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR InputIterator find_if_not(InputIterator first, InputIterator last, Predicate pred) { diff --git a/sprout/algorithm/is_permutation.hpp b/sprout/algorithm/is_permutation.hpp index 0eba4f5b..f0e88a17 100644 --- a/sprout/algorithm/is_permutation.hpp +++ b/sprout/algorithm/is_permutation.hpp @@ -76,6 +76,11 @@ namespace sprout { } // namespace detail // 25.2.12 Is permutation + // + // recursion depth: + // [first1, last1), first2 are RandomAccessIterator -> O(log N) + // otherwise -> O(N^2) + // template inline SPROUT_CONSTEXPR bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate pred) { diff --git a/sprout/algorithm/mismatch.hpp b/sprout/algorithm/mismatch.hpp index 8ba6c148..233f219d 100644 --- a/sprout/algorithm/mismatch.hpp +++ b/sprout/algorithm/mismatch.hpp @@ -77,6 +77,11 @@ namespace sprout { } //namespace detail // 25.2.10 Mismatch + // + // recursion depth: + // [first1, last1), first2 are RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR sprout::pair mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate pred) { diff --git a/sprout/algorithm/none_of.hpp b/sprout/algorithm/none_of.hpp index cbe611c4..5abe3dfb 100644 --- a/sprout/algorithm/none_of.hpp +++ b/sprout/algorithm/none_of.hpp @@ -56,6 +56,11 @@ namespace sprout { } //namespace detail // 25.2.3 None of + // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR bool none_of(InputIterator first, InputIterator last, Predicate pred) { diff --git a/sprout/algorithm/one_of.hpp b/sprout/algorithm/one_of.hpp index 6fafaa56..a218de93 100644 --- a/sprout/algorithm/one_of.hpp +++ b/sprout/algorithm/one_of.hpp @@ -19,6 +19,10 @@ namespace sprout { // // one_of // + // recursion depth: + // [first, last) is RandomAccessIterator -> O(log N) + // otherwise -> O(N) + // template inline SPROUT_CONSTEXPR bool one_of(InputIterator first, InputIterator last, Predicate pred) { diff --git a/sprout/iterator/next.hpp b/sprout/iterator/next.hpp index 6de60faf..3d74f2ee 100644 --- a/sprout/iterator/next.hpp +++ b/sprout/iterator/next.hpp @@ -3,7 +3,10 @@ #include #include +#include #include +#include +#include #include namespace sprout_adl { @@ -38,8 +41,71 @@ namespace sprout { { return it + n; } + + template + inline SPROUT_CONSTEXPR BidirectionalIterator + next_impl_2_neg(BidirectionalIterator const& it, typename std::iterator_traits::difference_type n) { + return n == -1 ? sprout::prev(it) + : sprout::iterator_detail::next_impl_2_neg( + sprout::iterator_detail::next_impl_2_neg(it, n / 2), + n - (n / 2) + ) + ; + } template inline SPROUT_CONSTEXPR ForwardIterator + next_impl_2(ForwardIterator const& it, typename std::iterator_traits::difference_type n) { + return n == 1 ? sprout::next(it) + : sprout::iterator_detail::next_impl_2( + sprout::iterator_detail::next_impl_2(it, n / 2), + n - (n / 2) + ) + ; + } + + template + inline SPROUT_CONSTEXPR BidirectionalIterator + next_impl_1( + BidirectionalIterator const& it, typename std::iterator_traits::difference_type n, + std::bidirectional_iterator_tag* + ) + { + return n == 0 ? it + : n > 0 ? sprout::iterator_detail::next_impl_2(it, n) + : sprout::iterator_detail::next_impl_2_neg(it, n) + ; + } + template + inline SPROUT_CONSTEXPR ForwardIterator + next_impl_1( + ForwardIterator const& it, typename std::iterator_traits::difference_type n, + void* + ) + { + return n == 0 ? it + : n > 0 ? sprout::iterator_detail::next_impl_2(it, n) + : throw std::domain_error("next: nagative distance is invalid ForwardIterator") + ; + } + + template + inline SPROUT_CONSTEXPR typename std::enable_if< + std::is_literal_type::value, + ForwardIterator + >::type + next_impl( + ForwardIterator const& it, typename std::iterator_traits::difference_type n, + void* + ) + { + typedef typename std::iterator_traits::iterator_category* category; + return sprout::iterator_detail::next_impl_1(it, n, category()); + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !std::is_literal_type::value, + ForwardIterator + >::type next_impl( ForwardIterator const& it, typename std::iterator_traits::difference_type n, void* @@ -84,11 +150,23 @@ namespace sprout { // // next // + // effect: + // ADL callable iterator_next(it) -> iterator_next(it) + // it is RandomAccessIterator && LiteralType -> it + 1 + // otherwise -> std::next(it) + // template inline SPROUT_CONSTEXPR ForwardIterator next(ForwardIterator const& it) { return sprout_iterator_detail::next(it); } + // + // effect: + // ADL callable iterator_next(it, n) -> iterator_next(it, n) + // it is RandomAccessIterator && LiteralType -> it + n + // it is LiteralType -> sprout::next(it)... || sprout::prev(it)... + // otherwise -> std::next(it, n) + // template inline SPROUT_CONSTEXPR ForwardIterator next(ForwardIterator const& it, typename std::iterator_traits::difference_type n) { diff --git a/sprout/iterator/next_fwd.hpp b/sprout/iterator/next_fwd.hpp new file mode 100644 index 00000000..6d3fc647 --- /dev/null +++ b/sprout/iterator/next_fwd.hpp @@ -0,0 +1,20 @@ +#ifndef SPROUT_ITERATOR_NEXT_FWD_HPP +#define SPROUT_ITERATOR_NEXT_FWD_HPP + +#include +#include + +namespace sprout { + // + // next + // + template + inline SPROUT_CONSTEXPR ForwardIterator + next(ForwardIterator const& it); + + template + inline SPROUT_CONSTEXPR ForwardIterator + next(ForwardIterator const& it, typename std::iterator_traits::difference_type n); +} // namespace sprout + +#endif // #ifndef SPROUT_ITERATOR_NEXT_FWD_HPP diff --git a/sprout/iterator/prev.hpp b/sprout/iterator/prev.hpp index 5fb3dc67..4dd65906 100644 --- a/sprout/iterator/prev.hpp +++ b/sprout/iterator/prev.hpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include namespace sprout_adl { @@ -38,8 +40,48 @@ namespace sprout { { return it - n; } + template inline SPROUT_CONSTEXPR BidirectionalIterator + prev_impl_1_neg(BidirectionalIterator const& it, typename std::iterator_traits::difference_type n) { + return n == -1 ? sprout::next(it) + : sprout::iterator_detail::prev_impl_1_neg( + sprout::iterator_detail::prev_impl_1_neg(it, n / 2), + n - (n / 2) + ) + ; + } + template + inline SPROUT_CONSTEXPR BidirectionalIterator + prev_impl_1(BidirectionalIterator const& it, typename std::iterator_traits::difference_type n) { + return n == 1 ? sprout::prev(it) + : sprout::iterator_detail::prev_impl_1( + sprout::iterator_detail::prev_impl_1(it, n / 2), + n - (n / 2) + ) + ; + } + + template + inline SPROUT_CONSTEXPR typename std::enable_if< + std::is_literal_type::value, + BidirectionalIterator + >::type + prev_impl( + BidirectionalIterator const& it, typename std::iterator_traits::difference_type n, + void* + ) + { + return n == 0 ? it + : n > 0 ? sprout::iterator_detail::prev_impl_1(it, n) + : sprout::iterator_detail::prev_impl_1_neg(it, n) + ; + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !std::is_literal_type::value, + BidirectionalIterator + >::type prev_impl( BidirectionalIterator const& it, typename std::iterator_traits::difference_type n, void* @@ -84,11 +126,23 @@ namespace sprout { // // prev // + // effect: + // ADL callable iterator_prev(it) -> iterator_prev(it) + // it is RandomAccessIterator && LiteralType -> it - 1 + // otherwise -> std::prev(it) + // template inline SPROUT_CONSTEXPR BidirectionalIterator prev(BidirectionalIterator const& it) { return sprout_iterator_detail::prev(it); } + // + // effect: + // ADL callable iterator_prev(it, n) -> iterator_prev(it, n) + // it is RandomAccessIterator && LiteralType -> it - n + // it is LiteralType -> sprout::prev(it)... || sprout::next(it)... + // otherwise -> std::prev(it, n) + // template inline SPROUT_CONSTEXPR BidirectionalIterator prev(BidirectionalIterator const& it, typename std::iterator_traits::difference_type n) { diff --git a/sprout/iterator/prev_fwd.hpp b/sprout/iterator/prev_fwd.hpp new file mode 100644 index 00000000..4a097dca --- /dev/null +++ b/sprout/iterator/prev_fwd.hpp @@ -0,0 +1,20 @@ +#ifndef SPROUT_ITERATOR_PREV_FWD_HPP +#define SPROUT_ITERATOR_PREV_FWD_HPP + +#include +#include + +namespace sprout { + // + // prev + // + template + inline SPROUT_CONSTEXPR BidirectionalIterator + prev(BidirectionalIterator const& it); + + template + inline SPROUT_CONSTEXPR BidirectionalIterator + prev(BidirectionalIterator const& it, typename std::iterator_traits::difference_type n); +} // namespace sprout + +#endif // #ifndef SPROUT_ITERATOR_PREV_FWD_HPP