Skip to content

Commit f83d833

Browse files
committed
[libc++][ranges] Implement ranges::min
Reviewed By: var-const, Mordante, #libc Spies: jwakely, ldionne, libcxx-commits, mgorny Differential Revision: https://reviews.llvm.org/D119589
1 parent dd8b0fe commit f83d833

File tree

10 files changed

+402
-25
lines changed

10 files changed

+402
-25
lines changed

libcxx/docs/Status/RangesAlgorithms.csv

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ Search,lower_bound,Christopher Di Bella,`D105795 <https://llvm.org/D105795>`_,Un
1515
Search,upper_bound,Christopher Di Bella,`D105795 <https://llvm.org/D105795>`_,Under review
1616
Search,equal_range,Christopher Di Bella,n/a,Not started
1717
Search,binary_search,Christopher Di Bella,n/a,Not started
18-
Search,min,Not assigned,n/a,Not started
18+
Search,min,Nikolas Klauser,`D119589 <https://llvm.org/D119589>`_,✅
1919
Search,max,Not assigned,n/a,Not started
2020
Search,minmax,Not assigned,n/a,Not started
21-
Search,min_element,Nikolas Klauser,n/a,✅
22-
Search,max_element,Not assigned,n/a,Not started
21+
Search,min_element,Nikolas Klauser,`D117025 <https://llvm.org/D117025>`_,✅
22+
Search,max_element,Nikolas Klauser,`D117523 <https://llvm.org/D117523>`_,✅
2323
Search,minmax_element,Not assigned,n/a,Not started
2424
Search,count,Not assigned,n/a,Not started
2525
Search,count_if,Not assigned,n/a,Not started

libcxx/include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ set(files
7070
__algorithm/ranges_find_if.h
7171
__algorithm/ranges_find_if_not.h
7272
__algorithm/ranges_max_element.h
73+
__algorithm/ranges_min.h
7374
__algorithm/ranges_min_element.h
7475
__algorithm/ranges_mismatch.h
7576
__algorithm/ranges_swap_ranges.h
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
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_MIN_H
10+
#define _LIBCPP___ALGORITHM_RANGES_MIN_H
11+
12+
#include <__algorithm/ranges_min_element.h>
13+
#include <__assert>
14+
#include <__concepts/copyable.h>
15+
#include <__config>
16+
#include <__functional/identity.h>
17+
#include <__functional/invoke.h>
18+
#include <__functional/ranges_operations.h>
19+
#include <__iterator/concepts.h>
20+
#include <__iterator/projected.h>
21+
#include <__ranges/access.h>
22+
#include <__ranges/concepts.h>
23+
#include <initializer_list>
24+
25+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
26+
# pragma GCC system_header
27+
#endif
28+
29+
#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
30+
31+
_LIBCPP_PUSH_MACROS
32+
#include <__undef_macros>
33+
34+
_LIBCPP_BEGIN_NAMESPACE_STD
35+
36+
namespace ranges {
37+
namespace __min {
38+
struct __fn {
39+
template <class _Tp, class _Proj = identity,
40+
indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less>
41+
_LIBCPP_HIDE_FROM_ABI constexpr
42+
const _Tp& operator()(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) const {
43+
return std::invoke(__comp, std::invoke(__proj, __b), std::invoke(__proj, __a)) ? __b : __a;
44+
}
45+
46+
template <copyable _Tp, class _Proj = identity,
47+
indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less>
48+
_LIBCPP_HIDE_FROM_ABI constexpr
49+
_Tp operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const {
50+
_LIBCPP_ASSERT(__il.begin() != __il.end(), "initializer_list must contain at least one element");
51+
return *ranges::__min_element_impl(__il.begin(), __il.end(), __comp, __proj);
52+
}
53+
54+
template <input_range _Rp, class _Proj = identity,
55+
indirect_strict_weak_order<projected<iterator_t<_Rp>, _Proj>> _Comp = ranges::less>
56+
requires indirectly_copyable_storable<iterator_t<_Rp>, range_value_t<_Rp>*>
57+
_LIBCPP_HIDE_FROM_ABI constexpr
58+
range_value_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const {
59+
auto __first = ranges::begin(__r);
60+
auto __last = ranges::end(__r);
61+
62+
_LIBCPP_ASSERT(__first != __last, "range must contain at least one element");
63+
64+
if constexpr (forward_range<_Rp>) {
65+
return *ranges::__min_element_impl(__first, __last, __comp, __proj);
66+
} else {
67+
range_value_t<_Rp> __result = *__first;
68+
while (++__first != __last) {
69+
if (std::invoke(__comp, std::invoke(__proj, *__first), std::invoke(__proj, __result)))
70+
__result = *__first;
71+
}
72+
return __result;
73+
}
74+
}
75+
};
76+
} // namespace __min
77+
78+
inline namespace __cpo {
79+
inline constexpr auto min = __min::__fn{};
80+
} // namespace __cpo
81+
} // namespace ranges
82+
83+
_LIBCPP_END_NAMESPACE_STD
84+
85+
_LIBCPP_POP_MACROS
86+
87+
#endif // _LIBCPP_STD_VER > 17 && && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
88+
89+
#endif // _LIBCPP___ALGORITHM_RANGES_MIN_H

libcxx/include/__algorithm/ranges_min_element.h

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,33 +29,34 @@
2929
_LIBCPP_BEGIN_NAMESPACE_STD
3030

3131
namespace ranges {
32-
namespace __min_element {
33-
struct __fn {
34-
template <class _Ip, class _Sp, class _Proj, class _Comp>
35-
_LIBCPP_HIDE_FROM_ABI static constexpr
36-
_Ip __go(_Ip __first, _Sp __last, _Comp& __comp, _Proj& __proj) {
37-
if (__first == __last)
38-
return __first;
3932

40-
_Ip __i = __first;
41-
while (++__i != __last)
42-
if (std::invoke(__comp, std::invoke(__proj, *__i), std::invoke(__proj, *__first)))
43-
__first = __i;
33+
template <class _Ip, class _Sp, class _Proj, class _Comp>
34+
_LIBCPP_HIDE_FROM_ABI static constexpr
35+
_Ip __min_element_impl(_Ip __first, _Sp __last, _Comp& __comp, _Proj& __proj) {
36+
if (__first == __last)
4437
return __first;
45-
}
4638

39+
_Ip __i = __first;
40+
while (++__i != __last)
41+
if (std::invoke(__comp, std::invoke(__proj, *__i), std::invoke(__proj, *__first)))
42+
__first = __i;
43+
return __first;
44+
}
45+
46+
namespace __min_element {
47+
struct __fn {
4748
template <forward_iterator _Ip, sentinel_for<_Ip> _Sp, class _Proj = identity,
4849
indirect_strict_weak_order<projected<_Ip, _Proj>> _Comp = ranges::less>
4950
_LIBCPP_HIDE_FROM_ABI constexpr
5051
_Ip operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const {
51-
return __go(__first, __last, __comp, __proj);
52+
return ranges::__min_element_impl(__first, __last, __comp, __proj);
5253
}
5354

5455
template <forward_range _Rp, class _Proj = identity,
5556
indirect_strict_weak_order<projected<iterator_t<_Rp>, _Proj>> _Comp = ranges::less>
5657
_LIBCPP_HIDE_FROM_ABI constexpr
5758
borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const {
58-
return __go(ranges::begin(__r), ranges::end(__r), __comp, __proj);
59+
return ranges::__min_element_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj);
5960
}
6061
};
6162
} // namespace __min_element

libcxx/include/__ranges/take_view.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#ifndef _LIBCPP___RANGES_TAKE_VIEW_H
1010
#define _LIBCPP___RANGES_TAKE_VIEW_H
1111

12-
#include <__algorithm/min.h>
12+
#include <__algorithm/ranges_min.h>
1313
#include <__config>
1414
#include <__iterator/concepts.h>
1515
#include <__iterator/counted_iterator.h>
@@ -118,15 +118,13 @@ namespace ranges {
118118
_LIBCPP_HIDE_FROM_ABI
119119
constexpr auto size() requires sized_range<_View> {
120120
auto __n = ranges::size(__base_);
121-
// TODO: use ranges::min here.
122-
return std::min(__n, static_cast<decltype(__n)>(__count_));
121+
return ranges::min(__n, static_cast<decltype(__n)>(__count_));
123122
}
124123

125124
_LIBCPP_HIDE_FROM_ABI
126125
constexpr auto size() const requires sized_range<const _View> {
127126
auto __n = ranges::size(__base_);
128-
// TODO: use ranges::min here.
129-
return std::min(__n, static_cast<decltype(__n)>(__count_));
127+
return ranges::min(__n, static_cast<decltype(__n)>(__count_));
130128
}
131129
};
132130

libcxx/include/algorithm

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ namespace ranges {
5757
constexpr mismatch_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>>
5858
mismatch(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) // since C++20
5959
60-
template<input_iterator I, sentinel_for<I> S, class T, class Proj = identity>
6160
requires indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*>
6261
constexpr I find(I first, S last, const T& value, Proj proj = {}); // since C++20
6362
@@ -83,9 +82,22 @@ namespace ranges {
8382
indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred>
8483
constexpr borrowed_iterator_t<R>
8584
find_if_not(R&& r, Pred pred, Proj proj = {}); // since C++20
85+
86+
template<class T, class Proj = identity,
87+
indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less>
88+
constexpr const T& min(const T& a, const T& b, Comp comp = {}, Proj proj = {}); // since C++20
89+
90+
template<copyable T, class Proj = identity,
91+
indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less>
92+
constexpr T min(initializer_list<T> r, Comp comp = {}, Proj proj = {}); // since C++20
93+
94+
template<input_range R, class Proj = identity,
95+
indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less>
96+
requires indirectly_copyable_storable<iterator_t<R>, range_value_t<R>*>
97+
constexpr range_value_t<R>
98+
min(R&& r, Comp comp = {}, Proj proj = {}); // since C++20
8699
}
87100
88-
template <class InputIterator, class Predicate>
89101
constexpr bool // constexpr in C++20
90102
all_of(InputIterator first, InputIterator last, Predicate pred);
91103
@@ -804,6 +816,7 @@ template <class BidirectionalIterator, class Compare>
804816
#include <__algorithm/ranges_find_if.h>
805817
#include <__algorithm/ranges_find_if_not.h>
806818
#include <__algorithm/ranges_max_element.h>
819+
#include <__algorithm/ranges_min.h>
807820
#include <__algorithm/ranges_min_element.h>
808821
#include <__algorithm/ranges_mismatch.h>
809822
#include <__algorithm/ranges_swap_ranges.h>

libcxx/include/module.modulemap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ module std [system] {
298298
module ranges_find_if { private header "__algorithm/ranges_find_if.h" }
299299
module ranges_find_if_not { private header "__algorithm/ranges_find_if_not.h" }
300300
module ranges_max_element { private header "__algorithm/ranges_max_element.h" }
301+
module ranges_min { private header "__algorithm/ranges_min.h" }
301302
module ranges_min_element { private header "__algorithm/ranges_min_element.h" }
302303
module ranges_mismatch { private header "__algorithm/ranges_mismatch.h" }
303304
module ranges_swap_ranges { private header "__algorithm/ranges_swap_ranges.h" }
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
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+
// REQUIRES: modules-build
10+
11+
// WARNING: This test was generated by 'generate_private_header_tests.py'
12+
// and should not be edited manually.
13+
14+
// expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_min.h'}}
15+
#include <__algorithm/ranges_min.h>

0 commit comments

Comments
 (0)