xref: /freebsd/contrib/llvm-project/libcxx/include/__algorithm/equal_range.h (revision ca457394fccfc7d712cd9cc6a66e574767a0a32b)
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_EQUAL_RANGE_H
10  #define _LIBCPP___ALGORITHM_EQUAL_RANGE_H
11  
12  #include <__config>
13  #include <__algorithm/comp.h>
14  #include <__algorithm/comp_ref_type.h>
15  #include <__algorithm/half_positive.h>
16  #include <__algorithm/lower_bound.h>
17  #include <__algorithm/upper_bound.h>
18  #include <iterator>
19  
20  #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
21  #pragma GCC system_header
22  #endif
23  
24  _LIBCPP_PUSH_MACROS
25  #include <__undef_macros>
26  
27  _LIBCPP_BEGIN_NAMESPACE_STD
28  
29  template <class _Compare, class _ForwardIterator, class _Tp>
30  _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_ForwardIterator, _ForwardIterator>
31  __equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp)
32  {
33      typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type;
34      difference_type __len = _VSTD::distance(__first, __last);
35      while (__len != 0)
36      {
37          difference_type __l2 = _VSTD::__half_positive(__len);
38          _ForwardIterator __m = __first;
39          _VSTD::advance(__m, __l2);
40          if (__comp(*__m, __value_))
41          {
42              __first = ++__m;
43              __len -= __l2 + 1;
44          }
45          else if (__comp(__value_, *__m))
46          {
47              __last = __m;
48              __len = __l2;
49          }
50          else
51          {
52              _ForwardIterator __mp1 = __m;
53              return pair<_ForwardIterator, _ForwardIterator>
54                     (
55                        _VSTD::__lower_bound<_Compare>(__first, __m, __value_, __comp),
56                        _VSTD::__upper_bound<_Compare>(++__mp1, __last, __value_, __comp)
57                     );
58          }
59      }
60      return pair<_ForwardIterator, _ForwardIterator>(__first, __first);
61  }
62  
63  template <class _ForwardIterator, class _Tp, class _Compare>
64  _LIBCPP_NODISCARD_EXT inline
65  _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
66  pair<_ForwardIterator, _ForwardIterator>
67  equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp)
68  {
69      typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
70      return _VSTD::__equal_range<_Comp_ref>(__first, __last, __value_, __comp);
71  }
72  
73  template <class _ForwardIterator, class _Tp>
74  _LIBCPP_NODISCARD_EXT inline
75  _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
76  pair<_ForwardIterator, _ForwardIterator>
77  equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_)
78  {
79      return _VSTD::equal_range(__first, __last, __value_,
80                               __less<typename iterator_traits<_ForwardIterator>::value_type, _Tp>());
81  }
82  
83  _LIBCPP_END_NAMESPACE_STD
84  
85  _LIBCPP_POP_MACROS
86  
87  #endif // _LIBCPP___ALGORITHM_EQUAL_RANGE_H
88