|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- #ifndef RANGES_V3_ALGORITHM_NTH_ELEMENT_HPP
- #define RANGES_V3_ALGORITHM_NTH_ELEMENT_HPP
-
- #include <utility>
-
- #include <range/v3/range_fwd.hpp>
-
- #include <range/v3/algorithm/min_element.hpp>
- #include <range/v3/functional/comparisons.hpp>
- #include <range/v3/functional/identity.hpp>
- #include <range/v3/functional/invoke.hpp>
- #include <range/v3/iterator/concepts.hpp>
- #include <range/v3/iterator/operations.hpp>
- #include <range/v3/iterator/traits.hpp>
- #include <range/v3/range/access.hpp>
- #include <range/v3/range/concepts.hpp>
- #include <range/v3/range/dangling.hpp>
- #include <range/v3/range/traits.hpp>
- #include <range/v3/utility/static_const.hpp>
- #include <range/v3/utility/swap.hpp>
-
- namespace ranges
- {
-
- namespace detail
- {
-
-
- template<typename I, typename C, typename P>
- auto sort3(I x, I y, I z, C & pred, P & proj) -> CPP_ret(unsigned)(
- requires forward_iterator<I> && indirect_relation<C, projected<I, P>>)
- {
- unsigned r = 0;
- if(!invoke(pred, invoke(proj, *y), invoke(proj, *x)))
- {
- if(!invoke(pred, invoke(proj, *z), invoke(proj, *y)))
- return r;
-
- ranges::iter_swap(y, z);
- r = 1;
- if(invoke(pred, invoke(proj, *y), invoke(proj, *x)))
- {
- ranges::iter_swap(x, y);
- r = 2;
- }
- return r;
- }
- if(invoke(pred, invoke(proj, *z), invoke(proj, *y)))
- {
- ranges::iter_swap(x, z);
- r = 1;
- return r;
- }
- ranges::iter_swap(x, y);
- r = 1;
- if(invoke(pred, invoke(proj, *z), invoke(proj, *y)))
- {
- ranges::iter_swap(y, z);
- r = 2;
- }
- return r;
- }
-
- template<typename I, typename C, typename P>
- auto selection_sort(I first, I last, C & pred, P & proj) -> CPP_ret(void)(
- requires bidirectional_iterator<I> && indirect_relation<C, projected<I, P>>)
- {
- RANGES_EXPECT(first != last);
- for(I lm1 = ranges::prev(last); first != lm1; ++first)
- {
- I i = ranges::min_element(first, last, std::ref(pred), std::ref(proj));
- if(i != first)
- ranges::iter_swap(first, i);
- }
- }
- }
-
-
-
-
- RANGES_BEGIN_NIEBLOID(nth_element)
-
-
- template<typename I, typename S, typename C = less, typename P = identity>
- auto RANGES_FUN_NIEBLOID(nth_element)(
- I first, I nth, S end_, C pred = C{}, P proj = P{})
- ->CPP_ret(I)(
- requires random_access_iterator<I> && sortable<I, C, P>)
- {
- I last = ranges::next(nth, end_), end_orig = last;
-
- using difference_type = iter_difference_t<I>;
- difference_type const limit = 7;
- while(true)
- {
- restart:
- if(nth == last)
- return end_orig;
- difference_type len = last - first;
- switch(len)
- {
- case 0:
- case 1:
- return end_orig;
- case 2:
- if(invoke(pred, invoke(proj, *--last), invoke(proj, *first)))
- ranges::iter_swap(first, last);
- return end_orig;
- case 3:
- {
- I m = first;
- detail::sort3(first, ++m, --last, pred, proj);
- return end_orig;
- }
- }
- if(len <= limit)
- {
- detail::selection_sort(first, last, pred, proj);
- return end_orig;
- }
-
- I m = first + len / 2;
- I lm1 = last;
- unsigned n_swaps = detail::sort3(first, m, --lm1, pred, proj);
-
-
-
- I i = first;
- I j = lm1;
-
-
-
- if(!invoke(pred, invoke(proj, *i), invoke(proj, *m)))
- {
-
-
- while(true)
- {
- if(i == --j)
- {
-
-
-
- ++i;
- j = last;
- if(!invoke(
- pred,
- invoke(proj, *first),
- invoke(
- proj,
- *--j)))
- {
- while(true)
- {
- if(i == j)
- return end_orig;
-
- if(invoke(
- pred, invoke(proj, *first), invoke(proj, *i)))
- {
- ranges::iter_swap(i, j);
- ++n_swaps;
- ++i;
- break;
- }
- ++i;
- }
- }
-
-
- if(i == j)
- return end_orig;
- while(true)
- {
- while(
- !invoke(pred, invoke(proj, *first), invoke(proj, *i)))
- ++i;
- while(invoke(
- pred, invoke(proj, *first), invoke(proj, *--j)))
- ;
- if(i >= j)
- break;
- ranges::iter_swap(i, j);
- ++n_swaps;
- ++i;
- }
-
-
- if(nth < i)
- return end_orig;
-
-
- first = i;
- goto restart;
- }
- if(invoke(pred, invoke(proj, *j), invoke(proj, *m)))
- {
- ranges::iter_swap(i, j);
- ++n_swaps;
- break;
-
- }
- }
- }
- ++i;
-
-
- if(i < j)
- {
-
- while(true)
- {
-
- while(invoke(pred, invoke(proj, *i), invoke(proj, *m)))
- ++i;
-
- while(!invoke(pred, invoke(proj, *--j), invoke(proj, *m)))
- ;
- if(i >= j)
- break;
- ranges::iter_swap(i, j);
- ++n_swaps;
-
-
- if(m == i)
- m = j;
- ++i;
- }
- }
-
- if(i != m && invoke(pred, invoke(proj, *m), invoke(proj, *i)))
- {
- ranges::iter_swap(i, m);
- ++n_swaps;
- }
-
- if(nth == i)
- return end_orig;
- if(n_swaps == 0)
- {
-
- if(nth < i)
- {
-
- j = m = first;
- while(++j != i)
- {
- if(invoke(pred, invoke(proj, *j), invoke(proj, *m)))
-
- goto not_sorted;
- m = j;
- }
-
- return end_orig;
- }
- else
- {
-
- j = m = i;
- while(++j != last)
- {
- if(invoke(pred, invoke(proj, *j), invoke(proj, *m)))
-
- goto not_sorted;
- m = j;
- }
-
- return end_orig;
- }
- }
- not_sorted:
-
- if(nth < i)
- {
-
- last = i;
- }
- else
- {
-
- first = ++i;
- }
- }
- return end_orig;
- }
-
-
- template<typename Rng, typename C = less, typename P = identity>
- auto RANGES_FUN_NIEBLOID(nth_element)(
- Rng && rng, iterator_t<Rng> nth, C pred = C{}, P proj = P{})
- ->CPP_ret(safe_iterator_t<Rng>)(
- requires random_access_range<Rng> && sortable<iterator_t<Rng>, C, P>)
- {
- return (*this)(
- begin(rng), std::move(nth), end(rng), std::move(pred), std::move(proj));
- }
-
- RANGES_END_NIEBLOID(nth_element)
-
- namespace cpp20
- {
- using ranges::nth_element;
- }
-
- }
-
- #endif
|