diff --git a/libcxx/benchmarks/algorithms/common.h b/libcxx/benchmarks/algorithms/common.h --- a/libcxx/benchmarks/algorithms/common.h +++ b/libcxx/benchmarks/algorithms/common.h @@ -17,14 +17,19 @@ #include "../CartesianBenchmarks.h" #include "../GenerateInput.h" -enum class ValueType { Uint32, Uint64, Pair, Tuple, String, Float }; -struct AllValueTypes : EnumValuesAsTuple { +enum class ValueType { Uint32, Uint64, Pair, Tuple, String, Float, ExpensiveToMove }; +struct AllValueTypes : EnumValuesAsTuple { static constexpr const char* Names[] = {"uint32", "uint64", "pair", "tuple", - "string", "float"}; + "string", "float", "ExpensiveToMove"}; +}; + +struct ExpensiveToMove { + int a[256]; + std::strong_ordering operator<=>(const ExpensiveToMove&) const = default; }; using Types = std::tuple< uint32_t, uint64_t, std::pair, std::tuple, - std::string, float >; + std::string, float, ExpensiveToMove >; template using Value = std::tuple_element_t<(int)V::value, Types>; @@ -146,6 +151,20 @@ } } +void fillValues(std::vector& V, size_t N, Order O) { + if (O == Order::SingleElement) { + V.resize(N, ExpensiveToMove{}); + } else { + while (V.size() != N) { + ExpensiveToMove e; + for (size_t i = 0; i != 256; ++i) { + e.a[i] = V.size() + i; + } + V.push_back(e); + } + } +} + template void sortValues(T& V, Order O) { switch (O) { diff --git a/libcxx/include/__algorithm/ranges_rotate.h b/libcxx/include/__algorithm/ranges_rotate.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__algorithm/ranges_rotate.h @@ -0,0 +1,14 @@ +//===----------------------------------------------------------------------===// +// +// 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_RANGES_ROTATE_H +#define _LIBCPP___ALGORITHM_RANGES_ROTATE_H + + + +#endif // _LIBCPP___ALGORITHM_RANGES_ROTATE_H diff --git a/libcxx/include/__algorithm/rotate.h b/libcxx/include/__algorithm/rotate.h --- a/libcxx/include/__algorithm/rotate.h +++ b/libcxx/include/__algorithm/rotate.h @@ -10,6 +10,7 @@ #define _LIBCPP___ALGORITHM_ROTATE_H #include <__algorithm/iterator_operations.h> +#include <__algorithm/min.h> #include <__algorithm/move.h> #include <__algorithm/move_backward.h> #include <__algorithm/swap_ranges.h> @@ -27,186 +28,133 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template -_LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator -__rotate_left(_ForwardIterator __first, _ForwardIterator __last) -{ - typedef typename iterator_traits<_ForwardIterator>::value_type value_type; - value_type __tmp = _IterOps<_AlgPolicy>::__iter_move(__first); - // TODO(ranges): pass `_AlgPolicy` to `move`. - _ForwardIterator __lm1 = _VSTD::move(_VSTD::next(__first), __last, __first); - *__lm1 = _VSTD::move(__tmp); - return __lm1; +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _Iter __rotate_left(_Iter __first, _Sent __last) { + auto __tmp = std::move(*__first); + auto __lm1 = std::__move(std::next(__first), __last, __first); + *__lm1 = std::move(__tmp); + return __lm1; } -template -_LIBCPP_CONSTEXPR_AFTER_CXX11 _BidirectionalIterator -__rotate_right(_BidirectionalIterator __first, _BidirectionalIterator __last) -{ - typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; - // TODO(ranges): pass `_AlgPolicy` to `prev`. - _BidirectionalIterator __lm1 = _VSTD::prev(__last); - value_type __tmp = _IterOps<_AlgPolicy>::__iter_move(__lm1); - // TODO(ranges): pass `_AlgPolicy` to `move_backward`. - _BidirectionalIterator __fp1 = _VSTD::move_backward(__first, __lm1, __last); - *__first = _VSTD::move(__tmp); - return __fp1; +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _Iter __rotate_right(_Iter __first, _Sent __last) { + auto __lm1 = std::prev(__last); + auto __tmp = std::move(*__lm1); + auto __fp1 = std::__move_backward(__first, __lm1, __last); + *__first = std::move(__tmp); + return __fp1; } -template -_LIBCPP_CONSTEXPR_AFTER_CXX14 _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; +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 _Iter +__rotate_forward(_Iter __first, _Iter __middle, _Sent __last) { + auto __i = __middle; + while (true) { + swap(*__first, *__i); + ++__first; + if (++__i == __last) + break; + if (__first == __middle) + __middle = __i; + } + auto __r = __first; + if (__first != __middle) { + __i = __middle; + while (true) { + swap(*__first, *__i); + ++__first; + if (++__i == __last) { if (__first == __middle) - __middle = __i; - } - _ForwardIterator __r = __first; - if (__first != __middle) - { + break; __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; - } + } else if (__first == __middle) + __middle = __i; } - return __r; -} - -template -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_AFTER_CXX14 _Integral -__algo_gcd(_Integral __x, _Integral __y) -{ - do - { - _Integral __t = __x % __y; - __x = __y; - __y = __t; - } while (__y); - return __x; + } + return __r; } -template -_LIBCPP_CONSTEXPR_AFTER_CXX14 _RandomAccessIterator -__rotate_gcd(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last) -{ - typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; - typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; - - const difference_type __m1 = __middle - __first; - const difference_type __m2 = __last - __middle; - if (__m1 == __m2) - { - // TODO(ranges): pass `_AlgPolicy` to `swap_ranges`. - _VSTD::swap_ranges(__first, __middle, __middle); - return __middle; +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 _Iter __rotate_random(_Iter __first, _Iter __middle, _Sent __last) { + auto __left = std::distance(__first, __middle); + auto __right = std::distance(__middle, __last); + auto __end = __first + __right; + + if (__left == 0 || __first == __last) + return __first; + + if (__left == __right) { + std::swap_ranges(__first, __middle, __middle); + return __middle; + } + + auto __min_len = std::min(__left, __right); + + while (__min_len > 0) { + if (__left <= __right) { + do { + std::swap_ranges(__first, __first + __left, __first + __left); + __first += __left; + __right -= __left; + } while (__left <= __right); + __min_len = __right; + } else { + do { + std::swap_ranges(__first + (__left - __right), __first + __left, __first + __left); + __left -= __right; + } while (__left > __right); + __min_len = __left; } - const difference_type __g = _VSTD::__algo_gcd(__m1, __m2); - for (_RandomAccessIterator __p = __first + __g; __p != __first;) - { - value_type __t(_IterOps<_AlgPolicy>::__iter_move(--__p)); - _RandomAccessIterator __p1 = __p; - _RandomAccessIterator __p2 = __p1 + __m1; - do - { - *__p1 = _IterOps<_AlgPolicy>::__iter_move(__p2); - __p1 = __p2; - const difference_type __d = __last - __p2; - if (__m1 < __d) - __p2 += __m1; - else - __p2 = __first + (__m1 - __d); - } while (__p2 != __p); - *__p1 = _VSTD::move(__t); - } - return __first + __m2; + } + return __end; } -template -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator -__rotate_impl(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, - _VSTD::forward_iterator_tag) -{ - typedef typename iterator_traits<_ForwardIterator>::value_type value_type; - if (is_trivially_move_assignable::value) - { - if (_IterOps<_AlgPolicy>::next(__first) == __middle) - return std::__rotate_left<_AlgPolicy>(__first, __last); - } - return std::__rotate_forward<_AlgPolicy>(__first, __middle, __last); +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _Iter +__rotate(_Iter __first, _Iter __middle, _Sent __last, std::forward_iterator_tag) { + using value_type = typename iterator_traits<_Iter>::value_type; + if (is_nothrow_move_assignable::value || !is_nothrow_swappable::value) { + if (std::next(__first) == __middle) + return std::__rotate_left(__first, __last); + } + return std::__rotate_forward(__first, __middle, __last); } -template -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_AFTER_CXX11 _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) - { - 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 +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _Iter +__rotate(_Iter __first, _Iter __middle, _Sent __last, bidirectional_iterator_tag) { + using value_type = typename iterator_traits<_Iter>::value_type; + if (is_nothrow_move_assignable::value || !is_nothrow_swappable::value) { + if (std::next(__first) == __middle) + return std::__rotate_left(__first, __last); + if (std::next(__middle) == __last) + return std::__rotate_right(__first, __last); + } + return std::__rotate_forward(__first, __middle, __last); } -template -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_AFTER_CXX11 _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) - { - 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_gcd<_AlgPolicy>(__first, __middle, __last); - } - return std::__rotate_forward<_AlgPolicy>(__first, __middle, __last); +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _Iter +__rotate(_Iter __first, _Iter __middle, _Iter __last, random_access_iterator_tag) { + using value_type = typename iterator_traits<_Iter>::value_type; + if (is_nothrow_move_assignable::value || !is_nothrow_swappable::value) { + if (std::next(__first) == __middle) + return std::__rotate_left(__first, __last); + if (std::next(__middle) == __last) + return std::__rotate_right(__first, __last); + return std::__rotate_random(__first, __middle, __last); + } + return std::__rotate_forward(__first, __middle, __last); } -template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 -_RandomAccessIterator __rotate(_RandomAccessIterator __first, _RandomAccessIterator __middle, - _RandomAccessIterator __last, _IterCategory __iter_category) { +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator +rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) { if (__first == __middle) - return __last; + return __last; if (__middle == __last) - return __first; - - return std::__rotate_impl<_AlgPolicy>(std::move(__first), std::move(__middle), std::move(__last), __iter_category); -} - -template -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator -rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) -{ - return std::__rotate<_ClassicAlgPolicy>(__first, __middle, __last, - typename iterator_traits<_ForwardIterator>::iterator_category()); + return __first; + return std::__rotate(__first, __middle, __last, typename iterator_traits<_ForwardIterator>::iterator_category()); } _LIBCPP_END_NAMESPACE_STD