This implements a new algorithm for `rotate` with random access iterators, which uses `swap_ranges`. This reduces cache misses and allows for vectorization. Apple M4: ``` Benchmark old new Difference % Difference --------------------------------------------------- -------------- -------------- ------------ -------------- rng::rotate(deque<int>)_(1_element_backward)/1024 46.17 45.13 -1.04 -2.26% rng::rotate(deque<int>)_(1_element_backward)/32 4.90 4.92 0.02 0.45% rng::rotate(deque<int>)_(1_element_backward)/50 6.12 6.02 -0.10 -1.56% rng::rotate(deque<int>)_(1_element_backward)/8192 329.97 330.49 0.52 0.16% rng::rotate(deque<int>)_(1_element_forward)/1024 42.20 42.99 0.79 1.87% rng::rotate(deque<int>)_(1_element_forward)/32 4.99 5.26 0.27 5.37% rng::rotate(deque<int>)_(1_element_forward)/50 6.33 6.48 0.14 2.28% rng::rotate(deque<int>)_(1_element_forward)/8192 317.40 318.68 1.28 0.40% rng::rotate(deque<int>)_(by_1/2)/1024 185.42 184.23 -1.18 -0.64% rng::rotate(deque<int>)_(by_1/2)/32 8.72 8.99 0.27 3.14% rng::rotate(deque<int>)_(by_1/2)/50 12.03 11.60 -0.43 -3.59% rng::rotate(deque<int>)_(by_1/2)/8192 1549.94 1549.30 -0.64 -0.04% rng::rotate(deque<int>)_(by_1/3)/1024 1886.50 409.41 -1477.09 -78.30% rng::rotate(deque<int>)_(by_1/3)/32 46.51 21.68 -24.84 -53.40% rng::rotate(deque<int>)_(by_1/3)/50 77.70 29.85 -47.85 -61.58% rng::rotate(deque<int>)_(by_1/3)/8192 22814.91 3171.92 -19642.99 -86.10% rng::rotate(deque<int>)_(by_1/4)/1024 811.39 283.28 -528.11 -65.09% rng::rotate(deque<int>)_(by_1/4)/32 30.30 14.44 -15.86 -52.35% rng::rotate(deque<int>)_(by_1/4)/50 76.23 29.29 -46.94 -61.58% rng::rotate(deque<int>)_(by_1/4)/8192 7154.50 2357.48 -4797.02 -67.05% rng::rotate(list<int>)_(1_element_backward)/1024 1483.46 742.31 -741.15 -49.96% rng::rotate(list<int>)_(1_element_backward)/32 16.17 16.37 0.20 1.24% rng::rotate(list<int>)_(1_element_backward)/50 29.31 29.20 -0.10 -0.34% rng::rotate(list<int>)_(1_element_backward)/8192 8896.07 8949.56 53.49 0.60% rng::rotate(list<int>)_(1_element_forward)/1024 1481.36 742.24 -739.12 -49.89% rng::rotate(list<int>)_(1_element_forward)/32 15.72 16.22 0.50 3.19% rng::rotate(list<int>)_(1_element_forward)/50 28.91 28.87 -0.03 -0.12% rng::rotate(list<int>)_(1_element_forward)/8192 9595.63 9846.80 251.16 2.62% rng::rotate(list<int>)_(by_1/2)/1024 833.67 408.22 -425.46 -51.03% rng::rotate(list<int>)_(by_1/2)/32 8.88 8.76 -0.11 -1.25% rng::rotate(list<int>)_(by_1/2)/50 15.67 15.73 0.06 0.40% rng::rotate(list<int>)_(by_1/2)/8192 6392.01 6597.30 205.30 3.21% rng::rotate(list<int>)_(by_1/3)/1024 1360.66 872.00 -488.66 -35.91% rng::rotate(list<int>)_(by_1/3)/32 19.72 19.37 -0.35 -1.80% rng::rotate(list<int>)_(by_1/3)/50 33.15 33.12 -0.04 -0.12% rng::rotate(list<int>)_(by_1/3)/8192 10807.14 11216.71 409.58 3.79% rng::rotate(list<int>)_(by_1/4)/1024 624.92 625.80 0.88 0.14% rng::rotate(list<int>)_(by_1/4)/32 15.28 15.37 0.09 0.60% rng::rotate(list<int>)_(by_1/4)/50 32.27 32.78 0.52 1.60% rng::rotate(list<int>)_(by_1/4)/8192 11266.66 9594.79 -1671.87 -14.84% rng::rotate(vector<bool>)_(1_element_backward)/1024 32.10 31.94 -0.16 -0.51% rng::rotate(vector<bool>)_(1_element_backward)/32 18.48 18.07 -0.41 -2.21% rng::rotate(vector<bool>)_(1_element_backward)/50 18.49 18.19 -0.30 -1.64% rng::rotate(vector<bool>)_(1_element_backward)/8192 113.76 112.91 -0.85 -0.75% rng::rotate(vector<bool>)_(1_element_forward)/1024 30.87 30.72 -0.15 -0.48% rng::rotate(vector<bool>)_(1_element_forward)/32 18.16 17.98 -0.18 -1.01% rng::rotate(vector<bool>)_(1_element_forward)/50 17.98 17.98 0.01 0.03% rng::rotate(vector<bool>)_(1_element_forward)/8192 111.84 111.50 -0.34 -0.31% rng::rotate(vector<bool>)_(by_1/2)/1024 9.27 9.34 0.07 0.75% rng::rotate(vector<bool>)_(by_1/2)/32 18.32 17.90 -0.42 -2.29% rng::rotate(vector<bool>)_(by_1/2)/50 18.14 17.69 -0.45 -2.49% rng::rotate(vector<bool>)_(by_1/2)/8192 16.23 16.80 0.57 3.49% rng::rotate(vector<bool>)_(by_1/3)/1024 58.89 58.74 -0.15 -0.25% rng::rotate(vector<bool>)_(by_1/3)/32 18.16 17.74 -0.41 -2.28% rng::rotate(vector<bool>)_(by_1/3)/50 18.15 17.72 -0.43 -2.38% rng::rotate(vector<bool>)_(by_1/3)/8192 164.52 166.17 1.65 1.00% rng::rotate(vector<bool>)_(by_1/4)/1024 13.44 14.20 0.76 5.65% rng::rotate(vector<bool>)_(by_1/4)/32 18.38 17.86 -0.52 -2.84% rng::rotate(vector<bool>)_(by_1/4)/50 18.26 17.75 -0.51 -2.79% rng::rotate(vector<bool>)_(by_1/4)/8192 34.49 34.59 0.11 0.31% rng::rotate(vector<int>)_(1_element_backward)/1024 37.22 37.55 0.33 0.88% rng::rotate(vector<int>)_(1_element_backward)/32 3.02 3.01 -0.00 -0.10% rng::rotate(vector<int>)_(1_element_backward)/50 5.31 5.33 0.02 0.31% rng::rotate(vector<int>)_(1_element_backward)/8192 302.96 295.02 -7.94 -2.62% rng::rotate(vector<int>)_(1_element_forward)/1024 36.78 36.97 0.19 0.51% rng::rotate(vector<int>)_(1_element_forward)/32 3.08 3.19 0.11 3.56% rng::rotate(vector<int>)_(1_element_forward)/50 5.33 5.33 -0.00 -0.05% rng::rotate(vector<int>)_(1_element_forward)/8192 288.25 285.28 -2.97 -1.03% rng::rotate(vector<int>)_(by_1/2)/1024 32.49 32.13 -0.36 -1.10% rng::rotate(vector<int>)_(by_1/2)/32 3.80 2.63 -1.17 -30.82% rng::rotate(vector<int>)_(by_1/2)/50 5.29 3.69 -1.59 -30.13% rng::rotate(vector<int>)_(by_1/2)/8192 256.13 252.05 -4.07 -1.59% rng::rotate(vector<int>)_(by_1/3)/1024 1389.57 135.85 -1253.72 -90.22% rng::rotate(vector<int>)_(by_1/3)/32 21.73 11.99 -9.73 -44.80% rng::rotate(vector<int>)_(by_1/3)/50 40.23 11.88 -28.35 -70.48% rng::rotate(vector<int>)_(by_1/3)/8192 11040.23 946.51 -10093.72 -91.43% rng::rotate(vector<int>)_(by_1/4)/1024 335.13 49.05 -286.08 -85.36% rng::rotate(vector<int>)_(by_1/4)/32 12.32 6.06 -6.26 -50.83% rng::rotate(vector<int>)_(by_1/4)/50 40.54 12.54 -28.00 -69.07% rng::rotate(vector<int>)_(by_1/4)/8192 2648.84 391.91 -2256.93 -85.20% std::rotate(deque<int>)_(1_element_backward)/1024 45.81 45.88 0.08 0.16% std::rotate(deque<int>)_(1_element_backward)/32 4.81 4.85 0.04 0.76% std::rotate(deque<int>)_(1_element_backward)/50 6.11 6.10 -0.01 -0.13% std::rotate(deque<int>)_(1_element_backward)/8192 329.99 330.63 0.64 0.19% std::rotate(deque<int>)_(1_element_forward)/1024 42.45 42.21 -0.24 -0.57% std::rotate(deque<int>)_(1_element_forward)/32 5.03 5.14 0.11 2.23% std::rotate(deque<int>)_(1_element_forward)/50 5.96 6.04 0.09 1.43% std::rotate(deque<int>)_(1_element_forward)/8192 316.09 317.73 1.64 0.52% std::rotate(deque<int>)_(by_1/2)/1024 185.34 185.41 0.07 0.04% std::rotate(deque<int>)_(by_1/2)/32 8.08 8.57 0.49 6.01% std::rotate(deque<int>)_(by_1/2)/50 11.13 11.61 0.48 4.35% std::rotate(deque<int>)_(by_1/2)/8192 1549.74 1527.97 -21.77 -1.40% std::rotate(deque<int>)_(by_1/3)/1024 1837.15 410.26 -1426.89 -77.67% std::rotate(deque<int>)_(by_1/3)/32 46.73 22.85 -23.88 -51.11% std::rotate(deque<int>)_(by_1/3)/50 78.05 29.61 -48.43 -62.06% std::rotate(deque<int>)_(by_1/3)/8192 22784.08 3174.02 -19610.06 -86.07% std::rotate(deque<int>)_(by_1/4)/1024 874.13 282.91 -591.22 -67.64% std::rotate(deque<int>)_(by_1/4)/32 31.14 14.31 -16.83 -54.05% std::rotate(deque<int>)_(by_1/4)/50 77.39 28.67 -48.72 -62.96% std::rotate(deque<int>)_(by_1/4)/8192 7207.73 2344.73 -4863.00 -67.47% std::rotate(list<int>)_(1_element_backward)/1024 1490.45 745.80 -744.65 -49.96% std::rotate(list<int>)_(1_element_backward)/32 16.15 16.43 0.28 1.71% std::rotate(list<int>)_(1_element_backward)/50 29.28 29.29 0.01 0.02% std::rotate(list<int>)_(1_element_backward)/8192 9305.23 10372.35 1067.13 11.47% std::rotate(list<int>)_(1_element_forward)/1024 1479.13 743.71 -735.42 -49.72% std::rotate(list<int>)_(1_element_forward)/32 15.86 16.21 0.35 2.20% std::rotate(list<int>)_(1_element_forward)/50 28.91 28.90 -0.01 -0.04% std::rotate(list<int>)_(1_element_forward)/8192 9796.34 8826.58 -969.76 -9.90% std::rotate(list<int>)_(by_1/2)/1024 851.06 411.44 -439.61 -51.66% std::rotate(list<int>)_(by_1/2)/32 8.90 8.80 -0.10 -1.10% std::rotate(list<int>)_(by_1/2)/50 15.69 15.69 0.00 0.02% std::rotate(list<int>)_(by_1/2)/8192 6479.34 6599.58 120.24 1.86% std::rotate(list<int>)_(by_1/3)/1024 865.82 877.81 11.99 1.38% std::rotate(list<int>)_(by_1/3)/32 19.52 19.44 -0.09 -0.44% std::rotate(list<int>)_(by_1/3)/50 33.67 33.14 -0.53 -1.59% std::rotate(list<int>)_(by_1/3)/8192 10513.57 10355.02 -158.55 -1.51% std::rotate(list<int>)_(by_1/4)/1024 639.35 655.30 15.95 2.49% std::rotate(list<int>)_(by_1/4)/32 15.22 15.45 0.24 1.55% std::rotate(list<int>)_(by_1/4)/50 32.51 32.93 0.42 1.29% std::rotate(list<int>)_(by_1/4)/8192 9883.06 9284.28 -598.79 -6.06% std::rotate(vector<bool>)_(1_element_backward)/1024 30.77 30.95 0.18 0.58% std::rotate(vector<bool>)_(1_element_backward)/32 17.73 17.57 -0.16 -0.89% std::rotate(vector<bool>)_(1_element_backward)/50 17.74 17.58 -0.16 -0.91% std::rotate(vector<bool>)_(1_element_backward)/8192 111.37 111.04 -0.33 -0.29% std::rotate(vector<bool>)_(1_element_forward)/1024 30.16 29.92 -0.24 -0.81% std::rotate(vector<bool>)_(1_element_forward)/32 17.22 17.38 0.16 0.94% std::rotate(vector<bool>)_(1_element_forward)/50 17.22 17.36 0.14 0.83% std::rotate(vector<bool>)_(1_element_forward)/8192 111.28 111.19 -0.09 -0.08% std::rotate(vector<bool>)_(by_1/2)/1024 9.20 9.65 0.46 4.96% std::rotate(vector<bool>)_(by_1/2)/32 17.23 17.12 -0.11 -0.62% std::rotate(vector<bool>)_(by_1/2)/50 17.18 17.04 -0.14 -0.82% std::rotate(vector<bool>)_(by_1/2)/8192 15.93 16.92 0.99 6.22% std::rotate(vector<bool>)_(by_1/3)/1024 57.99 58.05 0.06 0.10% std::rotate(vector<bool>)_(by_1/3)/32 17.14 17.06 -0.08 -0.47% std::rotate(vector<bool>)_(by_1/3)/50 17.09 16.95 -0.15 -0.87% std::rotate(vector<bool>)_(by_1/3)/8192 164.14 165.70 1.56 0.95% std::rotate(vector<bool>)_(by_1/4)/1024 14.00 14.21 0.21 1.49% std::rotate(vector<bool>)_(by_1/4)/32 17.20 17.20 -0.00 -0.00% std::rotate(vector<bool>)_(by_1/4)/50 17.09 17.10 0.01 0.08% std::rotate(vector<bool>)_(by_1/4)/8192 33.90 34.16 0.26 0.76% std::rotate(vector<int>)_(1_element_backward)/1024 37.04 37.54 0.50 1.35% std::rotate(vector<int>)_(1_element_backward)/32 3.01 3.01 0.00 0.04% std::rotate(vector<int>)_(1_element_backward)/50 5.30 4.96 -0.34 -6.44% std::rotate(vector<int>)_(1_element_backward)/8192 302.63 286.92 -15.71 -5.19% std::rotate(vector<int>)_(1_element_forward)/1024 36.83 36.88 0.05 0.15% std::rotate(vector<int>)_(1_element_forward)/32 3.08 3.06 -0.02 -0.56% std::rotate(vector<int>)_(1_element_forward)/50 5.34 5.07 -0.26 -4.95% std::rotate(vector<int>)_(1_element_forward)/8192 283.85 284.99 1.14 0.40% std::rotate(vector<int>)_(by_1/2)/1024 32.12 32.19 0.06 0.20% std::rotate(vector<int>)_(by_1/2)/32 3.83 2.22 -1.61 -42.16% std::rotate(vector<int>)_(by_1/2)/50 4.28 4.38 0.09 2.19% std::rotate(vector<int>)_(by_1/2)/8192 256.28 252.63 -3.65 -1.42% std::rotate(vector<int>)_(by_1/3)/1024 1386.79 142.76 -1244.03 -89.71% std::rotate(vector<int>)_(by_1/3)/32 21.76 11.54 -10.22 -46.98% std::rotate(vector<int>)_(by_1/3)/50 40.30 11.79 -28.51 -70.74% std::rotate(vector<int>)_(by_1/3)/8192 11017.09 949.95 -10067.14 -91.38% std::rotate(vector<int>)_(by_1/4)/1024 335.51 48.69 -286.83 -85.49% std::rotate(vector<int>)_(by_1/4)/32 12.31 6.09 -6.22 -50.51% std::rotate(vector<int>)_(by_1/4)/50 40.82 13.03 -27.79 -68.07% std::rotate(vector<int>)_(by_1/4)/8192 2647.90 392.58 -2255.32 -85.17% Geomean 76.74 56.58 -20.16 -26.27% ``` Fixes #54949
227 lines
8.6 KiB
C++
227 lines
8.6 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef _LIBCPP___ALGORITHM_ROTATE_H
|
|
#define _LIBCPP___ALGORITHM_ROTATE_H
|
|
|
|
#include <__algorithm/copy.h>
|
|
#include <__algorithm/copy_backward.h>
|
|
#include <__algorithm/iterator_operations.h>
|
|
#include <__algorithm/min.h>
|
|
#include <__algorithm/move.h>
|
|
#include <__algorithm/move_backward.h>
|
|
#include <__algorithm/swap_ranges.h>
|
|
#include <__config>
|
|
#include <__fwd/bit_reference.h>
|
|
#include <__iterator/iterator_traits.h>
|
|
#include <__type_traits/is_trivially_assignable.h>
|
|
#include <__utility/move.h>
|
|
#include <__utility/pair.h>
|
|
|
|
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
|
# pragma GCC system_header
|
|
#endif
|
|
|
|
_LIBCPP_PUSH_MACROS
|
|
#include <__undef_macros>
|
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
template <class _AlgPolicy, class _ForwardIterator>
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator
|
|
__rotate_left(_ForwardIterator __first, _ForwardIterator __last) {
|
|
typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
|
|
using _Ops = _IterOps<_AlgPolicy>;
|
|
|
|
value_type __tmp = _Ops::__iter_move(__first);
|
|
_ForwardIterator __lm1 = std::__move<_AlgPolicy>(_Ops::next(__first), __last, __first).second;
|
|
*__lm1 = std::move(__tmp);
|
|
return __lm1;
|
|
}
|
|
|
|
template <class _AlgPolicy, class _BidirectionalIterator>
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _BidirectionalIterator
|
|
__rotate_right(_BidirectionalIterator __first, _BidirectionalIterator __last) {
|
|
typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
|
|
using _Ops = _IterOps<_AlgPolicy>;
|
|
|
|
_BidirectionalIterator __lm1 = _Ops::prev(__last);
|
|
value_type __tmp = _Ops::__iter_move(__lm1);
|
|
_BidirectionalIterator __fp1 = std::__move_backward<_AlgPolicy>(__first, __lm1, std::move(__last)).second;
|
|
*__first = std::move(__tmp);
|
|
return __fp1;
|
|
}
|
|
|
|
template <class _AlgPolicy, class _ForwardIterator>
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _ForwardIterator
|
|
__rotate_forward(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) {
|
|
_ForwardIterator __i = __middle;
|
|
while (true) {
|
|
_IterOps<_AlgPolicy>::iter_swap(__first, __i);
|
|
++__first;
|
|
if (++__i == __last)
|
|
break;
|
|
if (__first == __middle)
|
|
__middle = __i;
|
|
}
|
|
_ForwardIterator __r = __first;
|
|
if (__first != __middle) {
|
|
__i = __middle;
|
|
while (true) {
|
|
_IterOps<_AlgPolicy>::iter_swap(__first, __i);
|
|
++__first;
|
|
if (++__i == __last) {
|
|
if (__first == __middle)
|
|
break;
|
|
__i = __middle;
|
|
} else if (__first == __middle)
|
|
__middle = __i;
|
|
}
|
|
}
|
|
return __r;
|
|
}
|
|
|
|
template <class _AlgPolicy, class _Iter, class _Sent>
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _Iter
|
|
__rotate_random_access(_Iter __first, _Iter __middle, _Sent __sent) {
|
|
auto __left = _IterOps<_AlgPolicy>::distance(__first, __middle);
|
|
auto __right = _IterOps<_AlgPolicy>::distance(__middle, __sent);
|
|
auto __last = __first + __right;
|
|
|
|
auto __min_len = std::min(__left, __right);
|
|
|
|
while (__min_len > 0) {
|
|
if (__left <= __right) {
|
|
do {
|
|
std::__swap_ranges<_AlgPolicy>(__first, __first + __left, __first + __left);
|
|
__first += __left;
|
|
__right -= __left;
|
|
} while (__left <= __right);
|
|
__min_len = __right;
|
|
} else {
|
|
do {
|
|
std::__swap_ranges<_AlgPolicy>(__first + (__left - __right), __first + __left, __first + __left);
|
|
__left -= __right;
|
|
} while (__left > __right);
|
|
__min_len = __left;
|
|
}
|
|
}
|
|
return __last;
|
|
}
|
|
|
|
template <class _AlgPolicy, class _ForwardIterator>
|
|
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator
|
|
__rotate_impl(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, std::forward_iterator_tag) {
|
|
typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
|
|
if (is_trivially_move_assignable<value_type>::value) {
|
|
if (_IterOps<_AlgPolicy>::next(__first) == __middle)
|
|
return std::__rotate_left<_AlgPolicy>(__first, __last);
|
|
}
|
|
return std::__rotate_forward<_AlgPolicy>(__first, __middle, __last);
|
|
}
|
|
|
|
template <class _AlgPolicy, class _BidirectionalIterator>
|
|
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _BidirectionalIterator __rotate_impl(
|
|
_BidirectionalIterator __first,
|
|
_BidirectionalIterator __middle,
|
|
_BidirectionalIterator __last,
|
|
bidirectional_iterator_tag) {
|
|
typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
|
|
if (is_trivially_move_assignable<value_type>::value) {
|
|
if (_IterOps<_AlgPolicy>::next(__first) == __middle)
|
|
return std::__rotate_left<_AlgPolicy>(__first, __last);
|
|
if (_IterOps<_AlgPolicy>::next(__middle) == __last)
|
|
return std::__rotate_right<_AlgPolicy>(__first, __last);
|
|
}
|
|
return std::__rotate_forward<_AlgPolicy>(__first, __middle, __last);
|
|
}
|
|
|
|
template <class _AlgPolicy, class _RandomAccessIterator>
|
|
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _RandomAccessIterator __rotate_impl(
|
|
_RandomAccessIterator __first,
|
|
_RandomAccessIterator __middle,
|
|
_RandomAccessIterator __last,
|
|
random_access_iterator_tag) {
|
|
typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
|
|
if (is_trivially_move_assignable<value_type>::value) {
|
|
if (_IterOps<_AlgPolicy>::next(__first) == __middle)
|
|
return std::__rotate_left<_AlgPolicy>(__first, __last);
|
|
if (_IterOps<_AlgPolicy>::next(__middle) == __last)
|
|
return std::__rotate_right<_AlgPolicy>(__first, __last);
|
|
return std::__rotate_random_access<_AlgPolicy>(__first, __middle, __last);
|
|
}
|
|
return std::__rotate_forward<_AlgPolicy>(__first, __middle, __last);
|
|
}
|
|
|
|
template <class _AlgPolicy, class _Iterator, class _Sentinel>
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iterator, _Iterator>
|
|
__rotate(_Iterator __first, _Iterator __middle, _Sentinel __last) {
|
|
using _Ret = pair<_Iterator, _Iterator>;
|
|
_Iterator __last_iter = _IterOps<_AlgPolicy>::next(__middle, __last);
|
|
|
|
if (__first == __middle)
|
|
return _Ret(__last_iter, __last_iter);
|
|
if (__middle == __last)
|
|
return _Ret(std::move(__first), std::move(__last_iter));
|
|
|
|
using _IterCategory = typename _IterOps<_AlgPolicy>::template __iterator_category<_Iterator>;
|
|
auto __result = std::__rotate_impl<_AlgPolicy>(std::move(__first), std::move(__middle), __last_iter, _IterCategory());
|
|
|
|
return _Ret(std::move(__result), std::move(__last_iter));
|
|
}
|
|
|
|
template <class, class _Cp>
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cp, false>, __bit_iterator<_Cp, false> >
|
|
__rotate(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __middle, __bit_iterator<_Cp, false> __last) {
|
|
using _I1 = __bit_iterator<_Cp, false>;
|
|
using difference_type = typename _I1::difference_type;
|
|
difference_type __d1 = __middle - __first;
|
|
difference_type __d2 = __last - __middle;
|
|
_I1 __r = __first + __d2;
|
|
while (__d1 != 0 && __d2 != 0) {
|
|
if (__d1 <= __d2) {
|
|
if (__d1 <= __bit_array<_Cp>::capacity()) {
|
|
__bit_array<_Cp> __b(__d1);
|
|
std::copy(__first, __middle, __b.begin());
|
|
std::copy(__b.begin(), __b.end(), std::copy(__middle, __last, __first));
|
|
break;
|
|
} else {
|
|
__bit_iterator<_Cp, false> __mp = std::swap_ranges(__first, __middle, __middle);
|
|
__first = __middle;
|
|
__middle = __mp;
|
|
__d2 -= __d1;
|
|
}
|
|
} else {
|
|
if (__d2 <= __bit_array<_Cp>::capacity()) {
|
|
__bit_array<_Cp> __b(__d2);
|
|
std::copy(__middle, __last, __b.begin());
|
|
std::copy_backward(__b.begin(), __b.end(), std::copy_backward(__first, __middle, __last));
|
|
break;
|
|
} else {
|
|
__bit_iterator<_Cp, false> __mp = __first + __d2;
|
|
std::swap_ranges(__first, __mp, __middle);
|
|
__first = __mp;
|
|
__d1 -= __d2;
|
|
}
|
|
}
|
|
}
|
|
return std::make_pair(__r, __last);
|
|
}
|
|
|
|
template <class _ForwardIterator>
|
|
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
|
|
rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) {
|
|
return std::__rotate<_ClassicAlgPolicy>(std::move(__first), std::move(__middle), std::move(__last)).first;
|
|
}
|
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
_LIBCPP_POP_MACROS
|
|
|
|
#endif // _LIBCPP___ALGORITHM_ROTATE_H
|