1*134723edSLouis Dionne //===----------------------------------------------------------------------===// 2*134723edSLouis Dionne // 3*134723edSLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*134723edSLouis Dionne // See https://llvm.org/LICENSE.txt for license information. 5*134723edSLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*134723edSLouis Dionne // 7*134723edSLouis Dionne //===----------------------------------------------------------------------===// 8*134723edSLouis Dionne 9*134723edSLouis Dionne #ifndef _LIBCPP___ALGORITHM_SHIFT_RIGHT_H 10*134723edSLouis Dionne #define _LIBCPP___ALGORITHM_SHIFT_RIGHT_H 11*134723edSLouis Dionne 12*134723edSLouis Dionne #include <__config> 13*134723edSLouis Dionne #include <__algorithm/move.h> 14*134723edSLouis Dionne #include <__algorithm/move_backward.h> 15*134723edSLouis Dionne #include <__iterator/iterator_traits.h> 16*134723edSLouis Dionne #include <type_traits> // swap 17*134723edSLouis Dionne 18*134723edSLouis Dionne #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 19*134723edSLouis Dionne #pragma GCC system_header 20*134723edSLouis Dionne #endif 21*134723edSLouis Dionne 22*134723edSLouis Dionne _LIBCPP_PUSH_MACROS 23*134723edSLouis Dionne #include <__undef_macros> 24*134723edSLouis Dionne 25*134723edSLouis Dionne _LIBCPP_BEGIN_NAMESPACE_STD 26*134723edSLouis Dionne 27*134723edSLouis Dionne #if _LIBCPP_STD_VER > 17 28*134723edSLouis Dionne 29*134723edSLouis Dionne template <class _ForwardIterator> 30*134723edSLouis Dionne inline _LIBCPP_INLINE_VISIBILITY constexpr 31*134723edSLouis Dionne _ForwardIterator 32*134723edSLouis Dionne shift_right(_ForwardIterator __first, _ForwardIterator __last, 33*134723edSLouis Dionne typename iterator_traits<_ForwardIterator>::difference_type __n) 34*134723edSLouis Dionne { 35*134723edSLouis Dionne if (__n == 0) { 36*134723edSLouis Dionne return __first; 37*134723edSLouis Dionne } 38*134723edSLouis Dionne 39*134723edSLouis Dionne if constexpr (__is_cpp17_random_access_iterator<_ForwardIterator>::value) { 40*134723edSLouis Dionne decltype(__n) __d = __last - __first; 41*134723edSLouis Dionne if (__n >= __d) { 42*134723edSLouis Dionne return __last; 43*134723edSLouis Dionne } 44*134723edSLouis Dionne _ForwardIterator __m = __first + (__d - __n); 45*134723edSLouis Dionne return _VSTD::move_backward(__first, __m, __last); 46*134723edSLouis Dionne } else if constexpr (__is_cpp17_bidirectional_iterator<_ForwardIterator>::value) { 47*134723edSLouis Dionne _ForwardIterator __m = __last; 48*134723edSLouis Dionne for (; __n > 0; --__n) { 49*134723edSLouis Dionne if (__m == __first) { 50*134723edSLouis Dionne return __last; 51*134723edSLouis Dionne } 52*134723edSLouis Dionne --__m; 53*134723edSLouis Dionne } 54*134723edSLouis Dionne return _VSTD::move_backward(__first, __m, __last); 55*134723edSLouis Dionne } else { 56*134723edSLouis Dionne _ForwardIterator __ret = __first; 57*134723edSLouis Dionne for (; __n > 0; --__n) { 58*134723edSLouis Dionne if (__ret == __last) { 59*134723edSLouis Dionne return __last; 60*134723edSLouis Dionne } 61*134723edSLouis Dionne ++__ret; 62*134723edSLouis Dionne } 63*134723edSLouis Dionne 64*134723edSLouis Dionne // We have an __n-element scratch space from __first to __ret. 65*134723edSLouis Dionne // Slide an __n-element window [__trail, __lead) from left to right. 66*134723edSLouis Dionne // We're essentially doing swap_ranges(__first, __ret, __trail, __lead) 67*134723edSLouis Dionne // over and over; but once __lead reaches __last we needn't bother 68*134723edSLouis Dionne // to save the values of elements [__trail, __last). 69*134723edSLouis Dionne 70*134723edSLouis Dionne auto __trail = __first; 71*134723edSLouis Dionne auto __lead = __ret; 72*134723edSLouis Dionne while (__trail != __ret) { 73*134723edSLouis Dionne if (__lead == __last) { 74*134723edSLouis Dionne _VSTD::move(__first, __trail, __ret); 75*134723edSLouis Dionne return __ret; 76*134723edSLouis Dionne } 77*134723edSLouis Dionne ++__trail; 78*134723edSLouis Dionne ++__lead; 79*134723edSLouis Dionne } 80*134723edSLouis Dionne 81*134723edSLouis Dionne _ForwardIterator __mid = __first; 82*134723edSLouis Dionne while (true) { 83*134723edSLouis Dionne if (__lead == __last) { 84*134723edSLouis Dionne __trail = _VSTD::move(__mid, __ret, __trail); 85*134723edSLouis Dionne _VSTD::move(__first, __mid, __trail); 86*134723edSLouis Dionne return __ret; 87*134723edSLouis Dionne } 88*134723edSLouis Dionne swap(*__mid, *__trail); 89*134723edSLouis Dionne ++__mid; 90*134723edSLouis Dionne ++__trail; 91*134723edSLouis Dionne ++__lead; 92*134723edSLouis Dionne if (__mid == __ret) { 93*134723edSLouis Dionne __mid = __first; 94*134723edSLouis Dionne } 95*134723edSLouis Dionne } 96*134723edSLouis Dionne } 97*134723edSLouis Dionne } 98*134723edSLouis Dionne 99*134723edSLouis Dionne #endif // _LIBCPP_STD_VER > 17 100*134723edSLouis Dionne 101*134723edSLouis Dionne _LIBCPP_END_NAMESPACE_STD 102*134723edSLouis Dionne 103*134723edSLouis Dionne _LIBCPP_POP_MACROS 104*134723edSLouis Dionne 105*134723edSLouis Dionne #endif // _LIBCPP___ALGORITHM_SHIFT_RIGHT_H 106