1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef _LIBCPP___ALGORITHM_INPLACE_MERGE_H
10 #define _LIBCPP___ALGORITHM_INPLACE_MERGE_H
12 #include <__algorithm/comp.h>
13 #include <__algorithm/comp_ref_type.h>
14 #include <__algorithm/iterator_operations.h>
15 #include <__algorithm/lower_bound.h>
16 #include <__algorithm/min.h>
17 #include <__algorithm/move.h>
18 #include <__algorithm/rotate.h>
19 #include <__algorithm/upper_bound.h>
21 #include <__cstddef/ptrdiff_t.h>
22 #include <__functional/identity.h>
23 #include <__iterator/advance.h>
24 #include <__iterator/distance.h>
25 #include <__iterator/iterator_traits.h>
26 #include <__iterator/reverse_iterator.h>
27 #include <__memory/destruct_n.h>
28 #include <__memory/unique_ptr.h>
29 #include <__memory/unique_temporary_buffer.h>
30 #include <__utility/move.h>
31 #include <__utility/pair.h>
34 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
35 # pragma GCC system_header
39 #include <__undef_macros>
41 _LIBCPP_BEGIN_NAMESPACE_STD
43 template <class _Predicate
>
44 class __invert
// invert the sense of a comparison
50 _LIBCPP_HIDE_FROM_ABI
__invert() {}
52 _LIBCPP_HIDE_FROM_ABI
explicit __invert(_Predicate __p
) : __p_(__p
) {}
55 _LIBCPP_HIDE_FROM_ABI
bool operator()(const _T1
& __x
) {
59 template <class _T1
, class _T2
>
60 _LIBCPP_HIDE_FROM_ABI
bool operator()(const _T1
& __x
, const _T2
& __y
) {
61 return __p_(__y
, __x
);
65 template <class _AlgPolicy
,
67 class _InputIterator1
,
69 class _InputIterator2
,
71 class _OutputIterator
>
72 _LIBCPP_HIDE_FROM_ABI
void __half_inplace_merge(
73 _InputIterator1 __first1
,
75 _InputIterator2 __first2
,
77 _OutputIterator __result
,
79 for (; __first1
!= __last1
; ++__result
) {
80 if (__first2
== __last2
) {
81 std::__move
<_AlgPolicy
>(__first1
, __last1
, __result
);
85 if (__comp(*__first2
, *__first1
)) {
86 *__result
= _IterOps
<_AlgPolicy
>::__iter_move(__first2
);
89 *__result
= _IterOps
<_AlgPolicy
>::__iter_move(__first1
);
93 // __first2 through __last2 are already in the right spot.
96 template <class _AlgPolicy
, class _Compare
, class _BidirectionalIterator
>
97 _LIBCPP_HIDE_FROM_ABI
void __buffered_inplace_merge(
98 _BidirectionalIterator __first
,
99 _BidirectionalIterator __middle
,
100 _BidirectionalIterator __last
,
102 typename iterator_traits
<_BidirectionalIterator
>::difference_type __len1
,
103 typename iterator_traits
<_BidirectionalIterator
>::difference_type __len2
,
104 typename iterator_traits
<_BidirectionalIterator
>::value_type
* __buff
) {
105 typedef typename iterator_traits
<_BidirectionalIterator
>::value_type value_type
;
107 unique_ptr
<value_type
, __destruct_n
&> __h2(__buff
, __d
);
108 if (__len1
<= __len2
) {
109 value_type
* __p
= __buff
;
110 for (_BidirectionalIterator __i
= __first
; __i
!= __middle
;
111 __d
.template __incr
<value_type
>(), (void)++__i
, (void)++__p
)
112 ::new ((void*)__p
) value_type(_IterOps
<_AlgPolicy
>::__iter_move(__i
));
113 std::__half_inplace_merge
<_AlgPolicy
>(__buff
, __p
, __middle
, __last
, __first
, __comp
);
115 value_type
* __p
= __buff
;
116 for (_BidirectionalIterator __i
= __middle
; __i
!= __last
;
117 __d
.template __incr
<value_type
>(), (void)++__i
, (void)++__p
)
118 ::new ((void*)__p
) value_type(_IterOps
<_AlgPolicy
>::__iter_move(__i
));
119 typedef reverse_iterator
<_BidirectionalIterator
> _RBi
;
120 typedef reverse_iterator
<value_type
*> _Rv
;
121 typedef __invert
<_Compare
> _Inverted
;
122 std::__half_inplace_merge
<_AlgPolicy
>(
123 _Rv(__p
), _Rv(__buff
), _RBi(__middle
), _RBi(__first
), _RBi(__last
), _Inverted(__comp
));
127 template <class _AlgPolicy
, class _Compare
, class _BidirectionalIterator
>
128 void __inplace_merge(
129 _BidirectionalIterator __first
,
130 _BidirectionalIterator __middle
,
131 _BidirectionalIterator __last
,
133 typename iterator_traits
<_BidirectionalIterator
>::difference_type __len1
,
134 typename iterator_traits
<_BidirectionalIterator
>::difference_type __len2
,
135 typename iterator_traits
<_BidirectionalIterator
>::value_type
* __buff
,
136 ptrdiff_t __buff_size
) {
137 using _Ops
= _IterOps
<_AlgPolicy
>;
139 typedef typename iterator_traits
<_BidirectionalIterator
>::difference_type difference_type
;
141 // if __middle == __last, we're done
144 if (__len1
<= __buff_size
|| __len2
<= __buff_size
)
145 return std::__buffered_inplace_merge
<_AlgPolicy
>(__first
, __middle
, __last
, __comp
, __len1
, __len2
, __buff
);
146 // shrink [__first, __middle) as much as possible (with no moves), returning if it shrinks to 0
147 for (; true; ++__first
, (void)--__len1
) {
150 if (__comp(*__middle
, *__first
))
153 // __first < __middle < __last
154 // *__first > *__middle
155 // partition [__first, __m1) [__m1, __middle) [__middle, __m2) [__m2, __last) such that
157 // [__first, __m1) <= [__middle, __m2)
158 // [__middle, __m2) < [__m1, __middle)
159 // [__m1, __middle) <= [__m2, __last)
160 // and __m1 or __m2 is in the middle of its range
161 _BidirectionalIterator __m1
; // "median" of [__first, __middle)
162 _BidirectionalIterator __m2
; // "median" of [__middle, __last)
163 difference_type __len11
; // distance(__first, __m1)
164 difference_type __len21
; // distance(__middle, __m2)
165 // binary search smaller range
166 if (__len1
< __len2
) { // __len >= 1, __len2 >= 2
167 __len21
= __len2
/ 2;
169 _Ops::advance(__m2
, __len21
);
170 __m1
= std::__upper_bound
<_AlgPolicy
>(__first
, __middle
, *__m2
, __comp
, std::__identity());
171 __len11
= _Ops::distance(__first
, __m1
);
173 if (__len1
== 1) { // __len1 >= __len2 && __len2 > 0, therefore __len2 == 1
174 // It is known *__first > *__middle
175 _Ops::iter_swap(__first
, __middle
);
178 // __len1 >= 2, __len2 >= 1
179 __len11
= __len1
/ 2;
181 _Ops::advance(__m1
, __len11
);
182 __m2
= std::lower_bound(__middle
, __last
, *__m1
, __comp
);
183 __len21
= _Ops::distance(__middle
, __m2
);
185 difference_type __len12
= __len1
- __len11
; // distance(__m1, __middle)
186 difference_type __len22
= __len2
- __len21
; // distance(__m2, __last)
187 // [__first, __m1) [__m1, __middle) [__middle, __m2) [__m2, __last)
188 // swap middle two partitions
189 __middle
= std::__rotate
<_AlgPolicy
>(__m1
, __middle
, __m2
).first
;
190 // __len12 and __len21 now have swapped meanings
191 // merge smaller range with recursive call and larger with tail recursion elimination
192 if (__len11
+ __len21
< __len12
+ __len22
) {
193 std::__inplace_merge
<_AlgPolicy
>(__first
, __m1
, __middle
, __comp
, __len11
, __len21
, __buff
, __buff_size
);
199 std::__inplace_merge
<_AlgPolicy
>(__middle
, __m2
, __last
, __comp
, __len12
, __len22
, __buff
, __buff_size
);
208 template <class _AlgPolicy
, class _BidirectionalIterator
, class _Compare
>
209 _LIBCPP_HIDE_FROM_ABI
void __inplace_merge(
210 _BidirectionalIterator __first
, _BidirectionalIterator __middle
, _BidirectionalIterator __last
, _Compare
&& __comp
) {
211 typedef typename iterator_traits
<_BidirectionalIterator
>::value_type value_type
;
212 typedef typename iterator_traits
<_BidirectionalIterator
>::difference_type difference_type
;
213 difference_type __len1
= _IterOps
<_AlgPolicy
>::distance(__first
, __middle
);
214 difference_type __len2
= _IterOps
<_AlgPolicy
>::distance(__middle
, __last
);
215 difference_type __buf_size
= std::min(__len1
, __len2
);
216 __unique_temporary_buffer
<value_type
> __unique_buf
= std::__allocate_unique_temporary_buffer
<value_type
>(__buf_size
);
217 return std::__inplace_merge
<_AlgPolicy
>(
225 __unique_buf
.get_deleter().__count_
);
228 template <class _BidirectionalIterator
, class _Compare
>
229 inline _LIBCPP_HIDE_FROM_ABI
void inplace_merge(
230 _BidirectionalIterator __first
, _BidirectionalIterator __middle
, _BidirectionalIterator __last
, _Compare __comp
) {
231 std::__inplace_merge
<_ClassicAlgPolicy
>(
232 std::move(__first
), std::move(__middle
), std::move(__last
), static_cast<__comp_ref_type
<_Compare
> >(__comp
));
235 template <class _BidirectionalIterator
>
236 inline _LIBCPP_HIDE_FROM_ABI
void
237 inplace_merge(_BidirectionalIterator __first
, _BidirectionalIterator __middle
, _BidirectionalIterator __last
) {
238 std::inplace_merge(std::move(__first
), std::move(__middle
), std::move(__last
), __less
<>());
241 _LIBCPP_END_NAMESPACE_STD
245 #endif // _LIBCPP___ALGORITHM_INPLACE_MERGE_H