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_ROTATE_H 10*ce777190SNikolas Klauser #define _LIBCPP___CXX03___ALGORITHM_ROTATE_H 11e78f53d1SNikolas Klauser 1273fbae83SNikolas Klauser #include <__cxx03/__algorithm/iterator_operations.h> 1373fbae83SNikolas Klauser #include <__cxx03/__algorithm/move.h> 1473fbae83SNikolas Klauser #include <__cxx03/__algorithm/move_backward.h> 1573fbae83SNikolas Klauser #include <__cxx03/__algorithm/swap_ranges.h> 1673fbae83SNikolas Klauser #include <__cxx03/__config> 1773fbae83SNikolas Klauser #include <__cxx03/__iterator/iterator_traits.h> 1873fbae83SNikolas Klauser #include <__cxx03/__type_traits/is_trivially_assignable.h> 1973fbae83SNikolas Klauser #include <__cxx03/__utility/move.h> 2073fbae83SNikolas Klauser #include <__cxx03/__utility/pair.h> 21e78f53d1SNikolas Klauser 22e78f53d1SNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 23e78f53d1SNikolas Klauser # pragma GCC system_header 24e78f53d1SNikolas Klauser #endif 25e78f53d1SNikolas Klauser 26e78f53d1SNikolas Klauser _LIBCPP_PUSH_MACROS 2773fbae83SNikolas Klauser #include <__cxx03/__undef_macros> 28e78f53d1SNikolas Klauser 29e78f53d1SNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_STD 30e78f53d1SNikolas Klauser 31e78f53d1SNikolas Klauser template <class _AlgPolicy, class _ForwardIterator> 32e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator 33e78f53d1SNikolas Klauser __rotate_left(_ForwardIterator __first, _ForwardIterator __last) { 34e78f53d1SNikolas Klauser typedef typename iterator_traits<_ForwardIterator>::value_type value_type; 35e78f53d1SNikolas Klauser using _Ops = _IterOps<_AlgPolicy>; 36e78f53d1SNikolas Klauser 37e78f53d1SNikolas Klauser value_type __tmp = _Ops::__iter_move(__first); 38e78f53d1SNikolas Klauser _ForwardIterator __lm1 = std::__move<_AlgPolicy>(_Ops::next(__first), __last, __first).second; 39e78f53d1SNikolas Klauser *__lm1 = std::move(__tmp); 40e78f53d1SNikolas Klauser return __lm1; 41e78f53d1SNikolas Klauser } 42e78f53d1SNikolas Klauser 43e78f53d1SNikolas Klauser template <class _AlgPolicy, class _BidirectionalIterator> 44e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _BidirectionalIterator 45e78f53d1SNikolas Klauser __rotate_right(_BidirectionalIterator __first, _BidirectionalIterator __last) { 46e78f53d1SNikolas Klauser typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; 47e78f53d1SNikolas Klauser using _Ops = _IterOps<_AlgPolicy>; 48e78f53d1SNikolas Klauser 49e78f53d1SNikolas Klauser _BidirectionalIterator __lm1 = _Ops::prev(__last); 50e78f53d1SNikolas Klauser value_type __tmp = _Ops::__iter_move(__lm1); 51e78f53d1SNikolas Klauser _BidirectionalIterator __fp1 = std::__move_backward<_AlgPolicy>(__first, __lm1, std::move(__last)).second; 52e78f53d1SNikolas Klauser *__first = std::move(__tmp); 53e78f53d1SNikolas Klauser return __fp1; 54e78f53d1SNikolas Klauser } 55e78f53d1SNikolas Klauser 56e78f53d1SNikolas Klauser template <class _AlgPolicy, class _ForwardIterator> 57e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _ForwardIterator 58e78f53d1SNikolas Klauser __rotate_forward(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) { 59e78f53d1SNikolas Klauser _ForwardIterator __i = __middle; 60e78f53d1SNikolas Klauser while (true) { 61e78f53d1SNikolas Klauser _IterOps<_AlgPolicy>::iter_swap(__first, __i); 62e78f53d1SNikolas Klauser ++__first; 63e78f53d1SNikolas Klauser if (++__i == __last) 64e78f53d1SNikolas Klauser break; 65e78f53d1SNikolas Klauser if (__first == __middle) 66e78f53d1SNikolas Klauser __middle = __i; 67e78f53d1SNikolas Klauser } 68e78f53d1SNikolas Klauser _ForwardIterator __r = __first; 69e78f53d1SNikolas Klauser if (__first != __middle) { 70e78f53d1SNikolas Klauser __i = __middle; 71e78f53d1SNikolas Klauser while (true) { 72e78f53d1SNikolas Klauser _IterOps<_AlgPolicy>::iter_swap(__first, __i); 73e78f53d1SNikolas Klauser ++__first; 74e78f53d1SNikolas Klauser if (++__i == __last) { 75e78f53d1SNikolas Klauser if (__first == __middle) 76e78f53d1SNikolas Klauser break; 77e78f53d1SNikolas Klauser __i = __middle; 78e78f53d1SNikolas Klauser } else if (__first == __middle) 79e78f53d1SNikolas Klauser __middle = __i; 80e78f53d1SNikolas Klauser } 81e78f53d1SNikolas Klauser } 82e78f53d1SNikolas Klauser return __r; 83e78f53d1SNikolas Klauser } 84e78f53d1SNikolas Klauser 85e78f53d1SNikolas Klauser template <typename _Integral> 86e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _Integral __algo_gcd(_Integral __x, _Integral __y) { 87e78f53d1SNikolas Klauser do { 88e78f53d1SNikolas Klauser _Integral __t = __x % __y; 89e78f53d1SNikolas Klauser __x = __y; 90e78f53d1SNikolas Klauser __y = __t; 91e78f53d1SNikolas Klauser } while (__y); 92e78f53d1SNikolas Klauser return __x; 93e78f53d1SNikolas Klauser } 94e78f53d1SNikolas Klauser 95e78f53d1SNikolas Klauser template <class _AlgPolicy, typename _RandomAccessIterator> 96e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _RandomAccessIterator 97e78f53d1SNikolas Klauser __rotate_gcd(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last) { 98e78f53d1SNikolas Klauser typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; 99e78f53d1SNikolas Klauser typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; 100e78f53d1SNikolas Klauser using _Ops = _IterOps<_AlgPolicy>; 101e78f53d1SNikolas Klauser 102e78f53d1SNikolas Klauser const difference_type __m1 = __middle - __first; 103e78f53d1SNikolas Klauser const difference_type __m2 = _Ops::distance(__middle, __last); 104e78f53d1SNikolas Klauser if (__m1 == __m2) { 105e78f53d1SNikolas Klauser std::__swap_ranges<_AlgPolicy>(__first, __middle, __middle, __last); 106e78f53d1SNikolas Klauser return __middle; 107e78f53d1SNikolas Klauser } 108e78f53d1SNikolas Klauser const difference_type __g = std::__algo_gcd(__m1, __m2); 109e78f53d1SNikolas Klauser for (_RandomAccessIterator __p = __first + __g; __p != __first;) { 110e78f53d1SNikolas Klauser value_type __t(_Ops::__iter_move(--__p)); 111e78f53d1SNikolas Klauser _RandomAccessIterator __p1 = __p; 112e78f53d1SNikolas Klauser _RandomAccessIterator __p2 = __p1 + __m1; 113e78f53d1SNikolas Klauser do { 114e78f53d1SNikolas Klauser *__p1 = _Ops::__iter_move(__p2); 115e78f53d1SNikolas Klauser __p1 = __p2; 116e78f53d1SNikolas Klauser const difference_type __d = _Ops::distance(__p2, __last); 117e78f53d1SNikolas Klauser if (__m1 < __d) 118e78f53d1SNikolas Klauser __p2 += __m1; 119e78f53d1SNikolas Klauser else 120e78f53d1SNikolas Klauser __p2 = __first + (__m1 - __d); 121e78f53d1SNikolas Klauser } while (__p2 != __p); 122e78f53d1SNikolas Klauser *__p1 = std::move(__t); 123e78f53d1SNikolas Klauser } 124e78f53d1SNikolas Klauser return __first + __m2; 125e78f53d1SNikolas Klauser } 126e78f53d1SNikolas Klauser 127e78f53d1SNikolas Klauser template <class _AlgPolicy, class _ForwardIterator> 128e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator 129e78f53d1SNikolas Klauser __rotate_impl(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, std::forward_iterator_tag) { 130e78f53d1SNikolas Klauser typedef typename iterator_traits<_ForwardIterator>::value_type value_type; 131e78f53d1SNikolas Klauser if (is_trivially_move_assignable<value_type>::value) { 132e78f53d1SNikolas Klauser if (_IterOps<_AlgPolicy>::next(__first) == __middle) 133e78f53d1SNikolas Klauser return std::__rotate_left<_AlgPolicy>(__first, __last); 134e78f53d1SNikolas Klauser } 135e78f53d1SNikolas Klauser return std::__rotate_forward<_AlgPolicy>(__first, __middle, __last); 136e78f53d1SNikolas Klauser } 137e78f53d1SNikolas Klauser 138e78f53d1SNikolas Klauser template <class _AlgPolicy, class _BidirectionalIterator> 139e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _BidirectionalIterator __rotate_impl( 140e78f53d1SNikolas Klauser _BidirectionalIterator __first, 141e78f53d1SNikolas Klauser _BidirectionalIterator __middle, 142e78f53d1SNikolas Klauser _BidirectionalIterator __last, 143e78f53d1SNikolas Klauser bidirectional_iterator_tag) { 144e78f53d1SNikolas Klauser typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; 145e78f53d1SNikolas Klauser if (is_trivially_move_assignable<value_type>::value) { 146e78f53d1SNikolas Klauser if (_IterOps<_AlgPolicy>::next(__first) == __middle) 147e78f53d1SNikolas Klauser return std::__rotate_left<_AlgPolicy>(__first, __last); 148e78f53d1SNikolas Klauser if (_IterOps<_AlgPolicy>::next(__middle) == __last) 149e78f53d1SNikolas Klauser return std::__rotate_right<_AlgPolicy>(__first, __last); 150e78f53d1SNikolas Klauser } 151e78f53d1SNikolas Klauser return std::__rotate_forward<_AlgPolicy>(__first, __middle, __last); 152e78f53d1SNikolas Klauser } 153e78f53d1SNikolas Klauser 154e78f53d1SNikolas Klauser template <class _AlgPolicy, class _RandomAccessIterator> 155e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _RandomAccessIterator __rotate_impl( 156e78f53d1SNikolas Klauser _RandomAccessIterator __first, 157e78f53d1SNikolas Klauser _RandomAccessIterator __middle, 158e78f53d1SNikolas Klauser _RandomAccessIterator __last, 159e78f53d1SNikolas Klauser random_access_iterator_tag) { 160e78f53d1SNikolas Klauser typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; 161e78f53d1SNikolas Klauser if (is_trivially_move_assignable<value_type>::value) { 162e78f53d1SNikolas Klauser if (_IterOps<_AlgPolicy>::next(__first) == __middle) 163e78f53d1SNikolas Klauser return std::__rotate_left<_AlgPolicy>(__first, __last); 164e78f53d1SNikolas Klauser if (_IterOps<_AlgPolicy>::next(__middle) == __last) 165e78f53d1SNikolas Klauser return std::__rotate_right<_AlgPolicy>(__first, __last); 166e78f53d1SNikolas Klauser return std::__rotate_gcd<_AlgPolicy>(__first, __middle, __last); 167e78f53d1SNikolas Klauser } 168e78f53d1SNikolas Klauser return std::__rotate_forward<_AlgPolicy>(__first, __middle, __last); 169e78f53d1SNikolas Klauser } 170e78f53d1SNikolas Klauser 171e78f53d1SNikolas Klauser template <class _AlgPolicy, class _Iterator, class _Sentinel> 172e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iterator, _Iterator> 173e78f53d1SNikolas Klauser __rotate(_Iterator __first, _Iterator __middle, _Sentinel __last) { 174e78f53d1SNikolas Klauser using _Ret = pair<_Iterator, _Iterator>; 175e78f53d1SNikolas Klauser _Iterator __last_iter = _IterOps<_AlgPolicy>::next(__middle, __last); 176e78f53d1SNikolas Klauser 177e78f53d1SNikolas Klauser if (__first == __middle) 178e78f53d1SNikolas Klauser return _Ret(__last_iter, __last_iter); 179e78f53d1SNikolas Klauser if (__middle == __last) 180e78f53d1SNikolas Klauser return _Ret(std::move(__first), std::move(__last_iter)); 181e78f53d1SNikolas Klauser 182e78f53d1SNikolas Klauser using _IterCategory = typename _IterOps<_AlgPolicy>::template __iterator_category<_Iterator>; 183e78f53d1SNikolas Klauser auto __result = std::__rotate_impl<_AlgPolicy>(std::move(__first), std::move(__middle), __last_iter, _IterCategory()); 184e78f53d1SNikolas Klauser 185e78f53d1SNikolas Klauser return _Ret(std::move(__result), std::move(__last_iter)); 186e78f53d1SNikolas Klauser } 187e78f53d1SNikolas Klauser 188e78f53d1SNikolas Klauser template <class _ForwardIterator> 189e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator 190e78f53d1SNikolas Klauser rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) { 191e78f53d1SNikolas Klauser return std::__rotate<_ClassicAlgPolicy>(std::move(__first), std::move(__middle), std::move(__last)).first; 192e78f53d1SNikolas Klauser } 193e78f53d1SNikolas Klauser 194e78f53d1SNikolas Klauser _LIBCPP_END_NAMESPACE_STD 195e78f53d1SNikolas Klauser 196e78f53d1SNikolas Klauser _LIBCPP_POP_MACROS 197e78f53d1SNikolas Klauser 198*ce777190SNikolas Klauser #endif // _LIBCPP___CXX03___ALGORITHM_ROTATE_H 199