Skip to content

Commit 23c7328

Browse files
committed
[libc++][ranges] Implement ranges::nth_element.
Differential Revision: https://reviews.llvm.org/D128149
1 parent 96063bf commit 23c7328

File tree

11 files changed

+416
-17
lines changed

11 files changed

+416
-17
lines changed

libcxx/docs/Status/RangesAlgorithms.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ Permutation,stable_partition,Not assigned,n/a,Not started
7676
Permutation,sort,Konstantin Varlamov,`D127557 <https://llvm.org/D127557>`_,✅
7777
Permutation,stable_sort,Konstantin Varlamov,`D127834 <https://llvm.org/D127834>`_,✅
7878
Permutation,partial_sort,Konstantin Varlamov,n/a,In progress
79-
Permutation,nth_element,Not assigned,n/a,Not started
79+
Permutation,nth_element,Konstantin Varlamov,`D128149 <https://llvm.org/D128149>`_,✅
8080
Permutation,inplace_merge,Not assigned,n/a,Not started
8181
Permutation,make_heap,Not assigned,n/a,Not started
8282
Permutation,push_heap,Not assigned,n/a,Not started

libcxx/include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ set(files
103103
__algorithm/ranges_move.h
104104
__algorithm/ranges_move_backward.h
105105
__algorithm/ranges_none_of.h
106+
__algorithm/ranges_nth_element.h
106107
__algorithm/ranges_remove.h
107108
__algorithm/ranges_remove_if.h
108109
__algorithm/ranges_replace.h

libcxx/include/__algorithm/nth_element.h

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <__debug>
1717
#include <__debug_utils/randomize_range.h>
1818
#include <__iterator/iterator_traits.h>
19+
#include <__utility/move.h>
1920
#include <__utility/swap.h>
2021

2122
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -220,25 +221,35 @@ __nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _Rando
220221
}
221222

222223
template <class _RandomAccessIterator, class _Compare>
223-
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
224-
void
225-
nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare __comp)
226-
{
224+
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
225+
void __nth_element_impl(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last,
226+
_Compare& __comp) {
227+
if (__nth == __last)
228+
return;
229+
227230
std::__debug_randomize_range(__first, __last);
228-
typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
229-
_VSTD::__nth_element<_Comp_ref>(__first, __nth, __last, __comp);
231+
232+
using _Comp_ref = typename __comp_ref_type<_Compare>::type;
233+
std::__nth_element<_Comp_ref>(__first, __nth, __last, __comp);
234+
230235
std::__debug_randomize_range(__first, __nth);
231236
if (__nth != __last) {
232237
std::__debug_randomize_range(++__nth, __last);
233238
}
234239
}
235240

241+
template <class _RandomAccessIterator, class _Compare>
242+
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
243+
void nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last,
244+
_Compare __comp) {
245+
std::__nth_element_impl(std::move(__first), std::move(__nth), std::move(__last), __comp);
246+
}
247+
236248
template <class _RandomAccessIterator>
237-
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
238-
void
239-
nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last)
240-
{
241-
_VSTD::nth_element(__first, __nth, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>());
249+
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
250+
void nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last) {
251+
std::nth_element(std::move(__first), std::move(__nth), std::move(__last), __less<typename
252+
iterator_traits<_RandomAccessIterator>::value_type>());
242253
}
243254

244255
_LIBCPP_END_NAMESPACE_STD
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef _LIBCPP___ALGORITHM_RANGES_NTH_ELEMENT_H
10+
#define _LIBCPP___ALGORITHM_RANGES_NTH_ELEMENT_H
11+
12+
#include <__algorithm/make_projected.h>
13+
#include <__algorithm/nth_element.h>
14+
#include <__config>
15+
#include <__functional/identity.h>
16+
#include <__functional/invoke.h>
17+
#include <__functional/ranges_operations.h>
18+
#include <__iterator/concepts.h>
19+
#include <__iterator/iterator_traits.h>
20+
#include <__iterator/next.h>
21+
#include <__iterator/projected.h>
22+
#include <__iterator/sortable.h>
23+
#include <__ranges/access.h>
24+
#include <__ranges/concepts.h>
25+
#include <__ranges/dangling.h>
26+
#include <__utility/forward.h>
27+
#include <__utility/move.h>
28+
29+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
30+
# pragma GCC system_header
31+
#endif
32+
33+
#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
34+
35+
_LIBCPP_BEGIN_NAMESPACE_STD
36+
37+
namespace ranges {
38+
namespace __nth_element {
39+
40+
struct __fn {
41+
template <class _Iter, class _Sent, class _Comp, class _Proj>
42+
_LIBCPP_HIDE_FROM_ABI constexpr static
43+
_Iter __nth_element_fn_impl(_Iter __first, _Iter __nth, _Sent __last, _Comp& __comp, _Proj& __proj) {
44+
auto __last_iter = ranges::next(__first, __last);
45+
46+
auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
47+
std::__nth_element_impl(std::move(__first), std::move(__nth), __last_iter, __projected_comp);
48+
49+
return __last_iter;
50+
}
51+
52+
template <random_access_iterator _Iter, sentinel_for<_Iter> _Sent, class _Comp = ranges::less, class _Proj = identity>
53+
requires sortable<_Iter, _Comp, _Proj>
54+
_LIBCPP_HIDE_FROM_ABI constexpr
55+
_Iter operator()(_Iter __first, _Iter __nth, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
56+
return __nth_element_fn_impl(std::move(__first), std::move(__nth), std::move(__last), __comp, __proj);
57+
}
58+
59+
template <random_access_range _Range, class _Comp = ranges::less, class _Proj = identity>
60+
requires sortable<iterator_t<_Range>, _Comp, _Proj>
61+
_LIBCPP_HIDE_FROM_ABI constexpr
62+
borrowed_iterator_t<_Range> operator()(_Range&& __r, iterator_t<_Range> __nth, _Comp __comp = {},
63+
_Proj __proj = {}) const {
64+
return __nth_element_fn_impl(ranges::begin(__r), std::move(__nth), ranges::end(__r), __comp, __proj);
65+
}
66+
};
67+
68+
} // namespace __nth_element
69+
70+
inline namespace __cpo {
71+
inline constexpr auto nth_element = __nth_element::__fn{};
72+
} // namespace __cpo
73+
} // namespace ranges
74+
75+
_LIBCPP_END_NAMESPACE_STD
76+
77+
#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
78+
79+
#endif // _LIBCPP___ALGORITHM_RANGES_NTH_ELEMENT_H

libcxx/include/algorithm

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,17 @@ namespace ranges {
379379
constexpr borrowed_iterator_t<R>
380380
ranges::is_sorted_until(R&& r, Comp comp = {}, Proj proj = {}); // since C++20
381381
382+
template<random_access_iterator I, sentinel_for<I> S, class Comp = ranges::less,
383+
class Proj = identity>
384+
requires sortable<I, Comp, Proj>
385+
constexpr I
386+
ranges::nth_element(I first, I nth, S last, Comp comp = {}, Proj proj = {}); // since C++20
387+
388+
template<random_access_range R, class Comp = ranges::less, class Proj = identity>
389+
requires sortable<iterator_t<R>, Comp, Proj>
390+
constexpr borrowed_iterator_t<R>
391+
ranges::nth_element(R&& r, iterator_t<R> nth, Comp comp = {}, Proj proj = {}); // since C++20
392+
382393
template<forward_iterator I, sentinel_for<I> S, class T, class Proj = identity,
383394
indirect_strict_weak_order<const T*, projected<I, Proj>> Comp = ranges::less>
384395
constexpr I upper_bound(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); // since C++20
@@ -1313,6 +1324,7 @@ template <class BidirectionalIterator, class Compare>
13131324
#include <__algorithm/ranges_move.h>
13141325
#include <__algorithm/ranges_move_backward.h>
13151326
#include <__algorithm/ranges_none_of.h>
1327+
#include <__algorithm/ranges_nth_element.h>
13161328
#include <__algorithm/ranges_remove.h>
13171329
#include <__algorithm/ranges_remove_if.h>
13181330
#include <__algorithm/ranges_replace.h>

libcxx/include/module.modulemap.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ module std [system] {
342342
module ranges_move { private header "__algorithm/ranges_move.h" }
343343
module ranges_move_backward { private header "__algorithm/ranges_move_backward.h" }
344344
module ranges_none_of { private header "__algorithm/ranges_none_of.h" }
345+
module ranges_nth_element { private header "__algorithm/ranges_nth_element.h" }
345346
module ranges_remove { private header "__algorithm/ranges_remove.h" }
346347
module ranges_remove_if { private header "__algorithm/ranges_remove_if.h" }
347348
module ranges_replace { private header "__algorithm/ranges_replace.h" }

libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,8 @@ constexpr bool all_the_algorithms()
169169
//(void)std::ranges::next_permutation(a, Less(&copies)); assert(copies == 0);
170170
(void)std::ranges::none_of(first, last, UnaryTrue(&copies)); assert(copies == 0);
171171
(void)std::ranges::none_of(a, UnaryTrue(&copies)); assert(copies == 0);
172-
//(void)std::ranges::nth_element(first, mid, last, Less(&copies)); assert(copies == 0);
173-
//(void)std::ranges::nth_element(a, mid, Less(&copies)); assert(copies == 0);
172+
(void)std::ranges::nth_element(first, mid, last, Less(&copies)); assert(copies == 0);
173+
(void)std::ranges::nth_element(a, mid, Less(&copies)); assert(copies == 0);
174174
//(void)std::ranges::partial_sort(first, mid, last, Less(&copies)); assert(copies == 0);
175175
//(void)std::ranges::partial_sort(a, mid, Less(&copies)); assert(copies == 0);
176176
//(void)std::ranges::partial_sort_copy(first, last, first2, mid2, Less(&copies)); assert(copies == 0);

libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,8 @@ constexpr bool all_the_algorithms()
152152
//(void)std::ranges::next_permutation(a, Less(), Proj(&copies)); assert(copies == 0);
153153
(void)std::ranges::none_of(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0);
154154
(void)std::ranges::none_of(a, UnaryTrue(), Proj(&copies)); assert(copies == 0);
155-
//(void)std::ranges::nth_element(first, mid, last, Less(), Proj(&copies)); assert(copies == 0);
156-
//(void)std::ranges::nth_element(a, mid, Less(), Proj(&copies)); assert(copies == 0);
155+
(void)std::ranges::nth_element(first, mid, last, Less(), Proj(&copies)); assert(copies == 0);
156+
(void)std::ranges::nth_element(a, mid, Less(), Proj(&copies)); assert(copies == 0);
157157
//(void)std::ranges::partial_sort(first, mid, last, Less(), Proj(&copies)); assert(copies == 0);
158158
//(void)std::ranges::partial_sort(a, mid, Less(), Proj(&copies)); assert(copies == 0);
159159
//(void)std::ranges::partial_sort_copy(first, last, first2, mid2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);

libcxx/test/libcxx/private_headers.verify.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ END-SCRIPT
140140
#include <__algorithm/ranges_move.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_move.h'}}
141141
#include <__algorithm/ranges_move_backward.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_move_backward.h'}}
142142
#include <__algorithm/ranges_none_of.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_none_of.h'}}
143+
#include <__algorithm/ranges_nth_element.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_nth_element.h'}}
143144
#include <__algorithm/ranges_remove.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_remove.h'}}
144145
#include <__algorithm/ranges_remove_if.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_remove_if.h'}}
145146
#include <__algorithm/ranges_replace.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_replace.h'}}

0 commit comments

Comments
 (0)