1e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===// 2e78f53d1SNikolas Klauser // 3e78f53d1SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e78f53d1SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information. 5e78f53d1SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e78f53d1SNikolas Klauser // 7e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===// 8e78f53d1SNikolas Klauser 9*ce777190SNikolas Klauser #ifndef _LIBCPP___CXX03___ALGORITHM_INPLACE_MERGE_H 10*ce777190SNikolas Klauser #define _LIBCPP___CXX03___ALGORITHM_INPLACE_MERGE_H 11e78f53d1SNikolas Klauser 1273fbae83SNikolas Klauser #include <__cxx03/__algorithm/comp.h> 1373fbae83SNikolas Klauser #include <__cxx03/__algorithm/comp_ref_type.h> 1473fbae83SNikolas Klauser #include <__cxx03/__algorithm/iterator_operations.h> 1573fbae83SNikolas Klauser #include <__cxx03/__algorithm/lower_bound.h> 1673fbae83SNikolas Klauser #include <__cxx03/__algorithm/min.h> 1773fbae83SNikolas Klauser #include <__cxx03/__algorithm/move.h> 1873fbae83SNikolas Klauser #include <__cxx03/__algorithm/rotate.h> 1973fbae83SNikolas Klauser #include <__cxx03/__algorithm/upper_bound.h> 2073fbae83SNikolas Klauser #include <__cxx03/__config> 2173fbae83SNikolas Klauser #include <__cxx03/__functional/identity.h> 2273fbae83SNikolas Klauser #include <__cxx03/__iterator/advance.h> 2373fbae83SNikolas Klauser #include <__cxx03/__iterator/distance.h> 2473fbae83SNikolas Klauser #include <__cxx03/__iterator/iterator_traits.h> 2573fbae83SNikolas Klauser #include <__cxx03/__iterator/reverse_iterator.h> 2673fbae83SNikolas Klauser #include <__cxx03/__memory/destruct_n.h> 2773fbae83SNikolas Klauser #include <__cxx03/__memory/temporary_buffer.h> 2873fbae83SNikolas Klauser #include <__cxx03/__memory/unique_ptr.h> 2973fbae83SNikolas Klauser #include <__cxx03/__utility/pair.h> 3073fbae83SNikolas Klauser #include <__cxx03/new> 31e78f53d1SNikolas Klauser 32e78f53d1SNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 33e78f53d1SNikolas Klauser # pragma GCC system_header 34e78f53d1SNikolas Klauser #endif 35e78f53d1SNikolas Klauser 36e78f53d1SNikolas Klauser _LIBCPP_PUSH_MACROS 3773fbae83SNikolas Klauser #include <__cxx03/__undef_macros> 38e78f53d1SNikolas Klauser 39e78f53d1SNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_STD 40e78f53d1SNikolas Klauser 41e78f53d1SNikolas Klauser template <class _Predicate> 42e78f53d1SNikolas Klauser class __invert // invert the sense of a comparison 43e78f53d1SNikolas Klauser { 44e78f53d1SNikolas Klauser private: 45e78f53d1SNikolas Klauser _Predicate __p_; 46e78f53d1SNikolas Klauser 47e78f53d1SNikolas Klauser public: 48e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI __invert() {} 49e78f53d1SNikolas Klauser 50e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI explicit __invert(_Predicate __p) : __p_(__p) {} 51e78f53d1SNikolas Klauser 52e78f53d1SNikolas Klauser template <class _T1> 53e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI bool operator()(const _T1& __x) { 54e78f53d1SNikolas Klauser return !__p_(__x); 55e78f53d1SNikolas Klauser } 56e78f53d1SNikolas Klauser 57e78f53d1SNikolas Klauser template <class _T1, class _T2> 58e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI bool operator()(const _T1& __x, const _T2& __y) { 59e78f53d1SNikolas Klauser return __p_(__y, __x); 60e78f53d1SNikolas Klauser } 61e78f53d1SNikolas Klauser }; 62e78f53d1SNikolas Klauser 63e78f53d1SNikolas Klauser template <class _AlgPolicy, 64e78f53d1SNikolas Klauser class _Compare, 65e78f53d1SNikolas Klauser class _InputIterator1, 66e78f53d1SNikolas Klauser class _Sent1, 67e78f53d1SNikolas Klauser class _InputIterator2, 68e78f53d1SNikolas Klauser class _Sent2, 69e78f53d1SNikolas Klauser class _OutputIterator> 70e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void __half_inplace_merge( 71e78f53d1SNikolas Klauser _InputIterator1 __first1, 72e78f53d1SNikolas Klauser _Sent1 __last1, 73e78f53d1SNikolas Klauser _InputIterator2 __first2, 74e78f53d1SNikolas Klauser _Sent2 __last2, 75e78f53d1SNikolas Klauser _OutputIterator __result, 76e78f53d1SNikolas Klauser _Compare&& __comp) { 77e78f53d1SNikolas Klauser for (; __first1 != __last1; ++__result) { 78e78f53d1SNikolas Klauser if (__first2 == __last2) { 79e78f53d1SNikolas Klauser std::__move<_AlgPolicy>(__first1, __last1, __result); 80e78f53d1SNikolas Klauser return; 81e78f53d1SNikolas Klauser } 82e78f53d1SNikolas Klauser 83e78f53d1SNikolas Klauser if (__comp(*__first2, *__first1)) { 84e78f53d1SNikolas Klauser *__result = _IterOps<_AlgPolicy>::__iter_move(__first2); 85e78f53d1SNikolas Klauser ++__first2; 86e78f53d1SNikolas Klauser } else { 87e78f53d1SNikolas Klauser *__result = _IterOps<_AlgPolicy>::__iter_move(__first1); 88e78f53d1SNikolas Klauser ++__first1; 89e78f53d1SNikolas Klauser } 90e78f53d1SNikolas Klauser } 91e78f53d1SNikolas Klauser // __first2 through __last2 are already in the right spot. 92e78f53d1SNikolas Klauser } 93e78f53d1SNikolas Klauser 94e78f53d1SNikolas Klauser template <class _AlgPolicy, class _Compare, class _BidirectionalIterator> 95e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void __buffered_inplace_merge( 96e78f53d1SNikolas Klauser _BidirectionalIterator __first, 97e78f53d1SNikolas Klauser _BidirectionalIterator __middle, 98e78f53d1SNikolas Klauser _BidirectionalIterator __last, 99e78f53d1SNikolas Klauser _Compare&& __comp, 100e78f53d1SNikolas Klauser typename iterator_traits<_BidirectionalIterator>::difference_type __len1, 101e78f53d1SNikolas Klauser typename iterator_traits<_BidirectionalIterator>::difference_type __len2, 102e78f53d1SNikolas Klauser typename iterator_traits<_BidirectionalIterator>::value_type* __buff) { 103e78f53d1SNikolas Klauser typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; 104e78f53d1SNikolas Klauser __destruct_n __d(0); 105e78f53d1SNikolas Klauser unique_ptr<value_type, __destruct_n&> __h2(__buff, __d); 106e78f53d1SNikolas Klauser if (__len1 <= __len2) { 107e78f53d1SNikolas Klauser value_type* __p = __buff; 108e78f53d1SNikolas Klauser for (_BidirectionalIterator __i = __first; __i != __middle; 109e78f53d1SNikolas Klauser __d.template __incr<value_type>(), (void)++__i, (void)++__p) 110e78f53d1SNikolas Klauser ::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i)); 111e78f53d1SNikolas Klauser std::__half_inplace_merge<_AlgPolicy>(__buff, __p, __middle, __last, __first, __comp); 112e78f53d1SNikolas Klauser } else { 113e78f53d1SNikolas Klauser value_type* __p = __buff; 114e78f53d1SNikolas Klauser for (_BidirectionalIterator __i = __middle; __i != __last; 115e78f53d1SNikolas Klauser __d.template __incr<value_type>(), (void)++__i, (void)++__p) 116e78f53d1SNikolas Klauser ::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i)); 117e78f53d1SNikolas Klauser typedef reverse_iterator<_BidirectionalIterator> _RBi; 118e78f53d1SNikolas Klauser typedef reverse_iterator<value_type*> _Rv; 119e78f53d1SNikolas Klauser typedef __invert<_Compare> _Inverted; 120e78f53d1SNikolas Klauser std::__half_inplace_merge<_AlgPolicy>( 121e78f53d1SNikolas Klauser _Rv(__p), _Rv(__buff), _RBi(__middle), _RBi(__first), _RBi(__last), _Inverted(__comp)); 122e78f53d1SNikolas Klauser } 123e78f53d1SNikolas Klauser } 124e78f53d1SNikolas Klauser 125e78f53d1SNikolas Klauser template <class _AlgPolicy, class _Compare, class _BidirectionalIterator> 126e78f53d1SNikolas Klauser void __inplace_merge( 127e78f53d1SNikolas Klauser _BidirectionalIterator __first, 128e78f53d1SNikolas Klauser _BidirectionalIterator __middle, 129e78f53d1SNikolas Klauser _BidirectionalIterator __last, 130e78f53d1SNikolas Klauser _Compare&& __comp, 131e78f53d1SNikolas Klauser typename iterator_traits<_BidirectionalIterator>::difference_type __len1, 132e78f53d1SNikolas Klauser typename iterator_traits<_BidirectionalIterator>::difference_type __len2, 133e78f53d1SNikolas Klauser typename iterator_traits<_BidirectionalIterator>::value_type* __buff, 134e78f53d1SNikolas Klauser ptrdiff_t __buff_size) { 135e78f53d1SNikolas Klauser using _Ops = _IterOps<_AlgPolicy>; 136e78f53d1SNikolas Klauser 137e78f53d1SNikolas Klauser typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; 138e78f53d1SNikolas Klauser while (true) { 139e78f53d1SNikolas Klauser // if __middle == __last, we're done 140e78f53d1SNikolas Klauser if (__len2 == 0) 141e78f53d1SNikolas Klauser return; 142e78f53d1SNikolas Klauser if (__len1 <= __buff_size || __len2 <= __buff_size) 143e78f53d1SNikolas Klauser return std::__buffered_inplace_merge<_AlgPolicy>(__first, __middle, __last, __comp, __len1, __len2, __buff); 144e78f53d1SNikolas Klauser // shrink [__first, __middle) as much as possible (with no moves), returning if it shrinks to 0 145e78f53d1SNikolas Klauser for (; true; ++__first, (void)--__len1) { 146e78f53d1SNikolas Klauser if (__len1 == 0) 147e78f53d1SNikolas Klauser return; 148e78f53d1SNikolas Klauser if (__comp(*__middle, *__first)) 149e78f53d1SNikolas Klauser break; 150e78f53d1SNikolas Klauser } 151e78f53d1SNikolas Klauser // __first < __middle < __last 152e78f53d1SNikolas Klauser // *__first > *__middle 153e78f53d1SNikolas Klauser // partition [__first, __m1) [__m1, __middle) [__middle, __m2) [__m2, __last) such that 154e78f53d1SNikolas Klauser // all elements in: 155e78f53d1SNikolas Klauser // [__first, __m1) <= [__middle, __m2) 156e78f53d1SNikolas Klauser // [__middle, __m2) < [__m1, __middle) 157e78f53d1SNikolas Klauser // [__m1, __middle) <= [__m2, __last) 158e78f53d1SNikolas Klauser // and __m1 or __m2 is in the middle of its range 159e78f53d1SNikolas Klauser _BidirectionalIterator __m1; // "median" of [__first, __middle) 160e78f53d1SNikolas Klauser _BidirectionalIterator __m2; // "median" of [__middle, __last) 161e78f53d1SNikolas Klauser difference_type __len11; // distance(__first, __m1) 162e78f53d1SNikolas Klauser difference_type __len21; // distance(__middle, __m2) 163e78f53d1SNikolas Klauser // binary search smaller range 164e78f53d1SNikolas Klauser if (__len1 < __len2) { // __len >= 1, __len2 >= 2 165e78f53d1SNikolas Klauser __len21 = __len2 / 2; 166e78f53d1SNikolas Klauser __m2 = __middle; 167e78f53d1SNikolas Klauser _Ops::advance(__m2, __len21); 168e78f53d1SNikolas Klauser __m1 = std::__upper_bound<_AlgPolicy>(__first, __middle, *__m2, __comp, std::__identity()); 169e78f53d1SNikolas Klauser __len11 = _Ops::distance(__first, __m1); 170e78f53d1SNikolas Klauser } else { 171e78f53d1SNikolas Klauser if (__len1 == 1) { // __len1 >= __len2 && __len2 > 0, therefore __len2 == 1 172e78f53d1SNikolas Klauser // It is known *__first > *__middle 173e78f53d1SNikolas Klauser _Ops::iter_swap(__first, __middle); 174e78f53d1SNikolas Klauser return; 175e78f53d1SNikolas Klauser } 176e78f53d1SNikolas Klauser // __len1 >= 2, __len2 >= 1 177e78f53d1SNikolas Klauser __len11 = __len1 / 2; 178e78f53d1SNikolas Klauser __m1 = __first; 179e78f53d1SNikolas Klauser _Ops::advance(__m1, __len11); 180e78f53d1SNikolas Klauser __m2 = std::lower_bound(__middle, __last, *__m1, __comp); 181e78f53d1SNikolas Klauser __len21 = _Ops::distance(__middle, __m2); 182e78f53d1SNikolas Klauser } 183e78f53d1SNikolas Klauser difference_type __len12 = __len1 - __len11; // distance(__m1, __middle) 184e78f53d1SNikolas Klauser difference_type __len22 = __len2 - __len21; // distance(__m2, __last) 185e78f53d1SNikolas Klauser // [__first, __m1) [__m1, __middle) [__middle, __m2) [__m2, __last) 186e78f53d1SNikolas Klauser // swap middle two partitions 187e78f53d1SNikolas Klauser __middle = std::__rotate<_AlgPolicy>(__m1, __middle, __m2).first; 188e78f53d1SNikolas Klauser // __len12 and __len21 now have swapped meanings 189e78f53d1SNikolas Klauser // merge smaller range with recursive call and larger with tail recursion elimination 190e78f53d1SNikolas Klauser if (__len11 + __len21 < __len12 + __len22) { 191e78f53d1SNikolas Klauser std::__inplace_merge<_AlgPolicy>(__first, __m1, __middle, __comp, __len11, __len21, __buff, __buff_size); 192e78f53d1SNikolas Klauser __first = __middle; 193e78f53d1SNikolas Klauser __middle = __m2; 194e78f53d1SNikolas Klauser __len1 = __len12; 195e78f53d1SNikolas Klauser __len2 = __len22; 196e78f53d1SNikolas Klauser } else { 197e78f53d1SNikolas Klauser std::__inplace_merge<_AlgPolicy>(__middle, __m2, __last, __comp, __len12, __len22, __buff, __buff_size); 198e78f53d1SNikolas Klauser __last = __middle; 199e78f53d1SNikolas Klauser __middle = __m1; 200e78f53d1SNikolas Klauser __len1 = __len11; 201e78f53d1SNikolas Klauser __len2 = __len21; 202e78f53d1SNikolas Klauser } 203e78f53d1SNikolas Klauser } 204e78f53d1SNikolas Klauser } 205e78f53d1SNikolas Klauser 206e78f53d1SNikolas Klauser template <class _AlgPolicy, class _BidirectionalIterator, class _Compare> 207e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void __inplace_merge( 208e78f53d1SNikolas Klauser _BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare&& __comp) { 209e78f53d1SNikolas Klauser typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; 210e78f53d1SNikolas Klauser typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; 211e78f53d1SNikolas Klauser difference_type __len1 = _IterOps<_AlgPolicy>::distance(__first, __middle); 212e78f53d1SNikolas Klauser difference_type __len2 = _IterOps<_AlgPolicy>::distance(__middle, __last); 213e78f53d1SNikolas Klauser difference_type __buf_size = std::min(__len1, __len2); 214e78f53d1SNikolas Klauser // TODO: Remove the use of std::get_temporary_buffer 215e78f53d1SNikolas Klauser _LIBCPP_SUPPRESS_DEPRECATED_PUSH 216e78f53d1SNikolas Klauser pair<value_type*, ptrdiff_t> __buf = std::get_temporary_buffer<value_type>(__buf_size); 217e78f53d1SNikolas Klauser _LIBCPP_SUPPRESS_DEPRECATED_POP 218e78f53d1SNikolas Klauser unique_ptr<value_type, __return_temporary_buffer> __h(__buf.first); 219e78f53d1SNikolas Klauser return std::__inplace_merge<_AlgPolicy>( 220e78f53d1SNikolas Klauser std::move(__first), std::move(__middle), std::move(__last), __comp, __len1, __len2, __buf.first, __buf.second); 221e78f53d1SNikolas Klauser } 222e78f53d1SNikolas Klauser 223e78f53d1SNikolas Klauser template <class _BidirectionalIterator, class _Compare> 224e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI void inplace_merge( 225e78f53d1SNikolas Klauser _BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare __comp) { 226e78f53d1SNikolas Klauser std::__inplace_merge<_ClassicAlgPolicy>( 227e78f53d1SNikolas Klauser std::move(__first), std::move(__middle), std::move(__last), static_cast<__comp_ref_type<_Compare> >(__comp)); 228e78f53d1SNikolas Klauser } 229e78f53d1SNikolas Klauser 230e78f53d1SNikolas Klauser template <class _BidirectionalIterator> 231e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI void 232e78f53d1SNikolas Klauser inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last) { 233e78f53d1SNikolas Klauser std::inplace_merge(std::move(__first), std::move(__middle), std::move(__last), __less<>()); 234e78f53d1SNikolas Klauser } 235e78f53d1SNikolas Klauser 236e78f53d1SNikolas Klauser _LIBCPP_END_NAMESPACE_STD 237e78f53d1SNikolas Klauser 238e78f53d1SNikolas Klauser _LIBCPP_POP_MACROS 239e78f53d1SNikolas Klauser 240*ce777190SNikolas Klauser #endif // _LIBCPP___CXX03___ALGORITHM_INPLACE_MERGE_H 241