1111
1212#include < __algorithm/comp.h>
1313#include < __algorithm/comp_ref_type.h>
14- #include < __algorithm/find.h>
1514#include < __algorithm/iterator_operations.h>
1615#include < __config>
1716#include < __functional/identity.h>
@@ -29,13 +28,54 @@ _LIBCPP_PUSH_MACROS
2928
3029_LIBCPP_BEGIN_NAMESPACE_STD
3130
31+ template <class _Iter , class _Sent , class = void >
32+ struct __ConstTimeDistance : false_type {};
33+
34+ #if _LIBCPP_STD_VER >= 20
35+
36+ template <class _Iter , class _Sent >
37+ struct __ConstTimeDistance < _Iter, _Sent, __enable_if_t < sized_sentinel_for<_Sent, _Iter> >> : true_type {};
38+
39+ #else
40+
41+ template <class _Iter >
42+ struct __ConstTimeDistance <
43+ _Iter,
44+ _Iter,
45+ __enable_if_t < is_same<typename iterator_traits<_Iter>::iterator_category, random_access_iterator_tag>::value> >
46+ : true_type {};
47+
48+ #endif // _LIBCPP_STD_VER >= 20
49+
3250template <class _Comp , class _Iter , class _Sent , class _Proj >
33- inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter
34- __min_element (_Iter __first, _Sent __last, _Comp __comp, _Proj& __proj) {
51+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter __min_element (
52+ _Iter __first,
53+ _Sent __last,
54+ _Comp __comp,
55+ _Proj& __proj,
56+ /* _ConstTimeDistance*/ false_type) {
3557 if (__first == __last)
3658 return __first;
3759
38- const size_t __n = static_cast <size_t >(std::distance (__first, __last));
60+ _Iter __i = __first;
61+ while (++__i != __last)
62+ if (std::__invoke (__comp, std::__invoke (__proj, *__i), std::__invoke (__proj, *__first)))
63+ __first = __i;
64+ return __first;
65+ }
66+
67+ template <class _Comp , class _Iter , class _Sent , class _Proj >
68+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter __min_element (
69+ _Iter __first,
70+ _Sent __last,
71+ _Comp __comp,
72+ _Proj& __proj,
73+ /* ConstTimeDistance*/ true_type) {
74+ if (__first == __last)
75+ return __first;
76+
77+ typedef typename std::iterator_traits<_Iter>::difference_type diff_type;
78+ diff_type __n = std::distance (__first, __last);
3979
4080 if (__n <= 64 ) {
4181 _Iter __i = __first;
@@ -45,19 +85,19 @@ __min_element(_Iter __first, _Sent __last, _Comp __comp, _Proj& __proj) {
4585 return __first;
4686 }
4787
48- size_t __block_size = 256 ;
88+ diff_type __block_size = 256 ;
4989
50- size_t __n_blocked = __n - (__n % __block_size);
90+ diff_type __n_blocked = __n - (__n % __block_size);
5191 _Iter __block_start = __first, __block_end = __first;
5292
5393 typedef typename std::iterator_traits<_Iter>::value_type value_type;
5494 value_type __min_val = std::__invoke (__proj, *__first);
5595
5696 _Iter __curr = __first;
57- for (size_t __i = 0 ; __i < __n_blocked; __i += __block_size) {
97+ for (diff_type __i = 0 ; __i < __n_blocked; __i += __block_size) {
5898 _Iter __start = __curr;
5999 value_type __block_min = __min_val;
60- for (size_t j = 0 ; j < __block_size; j ++) {
100+ for (diff_type __j = 0 ; __j < __block_size; __j ++) {
61101 if (std::__invoke (__comp, std::__invoke (__proj, *__curr), __block_min)) {
62102 __block_min = *__curr;
63103 }
@@ -84,7 +124,17 @@ __min_element(_Iter __first, _Sent __last, _Comp __comp, _Proj& __proj) {
84124 __block_end = __last;
85125 }
86126
87- return std::__find (__block_start, __block_end, __min_val, __proj);
127+ for (; __block_start != __block_end; ++__block_start)
128+ if (std::__invoke (__proj, *__block_start) == __min_val)
129+ break ;
130+ return __block_start;
131+ }
132+
133+ template <class _Comp , class _Iter , class _Sent , class _Proj >
134+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter
135+ __min_element (_Iter __first, _Sent __last, _Comp __comp, _Proj& __proj) {
136+ return std::__min_element<_Comp>(
137+ std::move (__first), std::move (__last), __comp, __proj, __ConstTimeDistance<_Iter, _Sent>());
88138}
89139
90140template <class _Comp , class _Iter , class _Sent >
0 commit comments