1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef _LIBCPP___ALGORITHM_COPY_BACKWARD_H
10#define _LIBCPP___ALGORITHM_COPY_BACKWARD_H
11
12#include <__algorithm/copy_move_common.h>
13#include <__algorithm/copy_n.h>
14#include <__algorithm/for_each_segment.h>
15#include <__algorithm/iterator_operations.h>
16#include <__algorithm/min.h>
17#include <__config>
18#include <__fwd/bit_reference.h>
19#include <__iterator/iterator_traits.h>
20#include <__iterator/segmented_iterator.h>
21#include <__memory/pointer_traits.h>
22#include <__type_traits/common_type.h>
23#include <__type_traits/enable_if.h>
24#include <__type_traits/is_constructible.h>
25#include <__utility/move.h>
26#include <__utility/pair.h>
27
28#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
29# pragma GCC system_header
30#endif
31
32_LIBCPP_PUSH_MACROS
33#include <__undef_macros>
34
35_LIBCPP_BEGIN_NAMESPACE_STD
36
37template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter>
38_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InIter, _OutIter>
39__copy_backward(_InIter __first, _Sent __last, _OutIter __result);
40
41template <class _Cp, bool _IsConst>
42_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_backward_aligned(
43 __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
44 using _In = __bit_iterator<_Cp, _IsConst>;
45 using difference_type = typename _In::difference_type;
46 using __storage_type = typename _In::__storage_type;
47
48 const int __bits_per_word = _In::__bits_per_word;
49 difference_type __n = __last - __first;
50 if (__n > 0) {
51 // do first word
52 if (__last.__ctz_ != 0) {
53 difference_type __dn = std::min(static_cast<difference_type>(__last.__ctz_), __n);
54 __n -= __dn;
55 unsigned __clz = __bits_per_word - __last.__ctz_;
56 __storage_type __m = std::__middle_mask<__storage_type>(__clz, __last.__ctz_ - __dn);
57 __storage_type __b = *__last.__seg_ & __m;
58 *__result.__seg_ &= ~__m;
59 *__result.__seg_ |= __b;
60 __result.__ctz_ = static_cast<unsigned>(((-__dn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word);
61 // __last.__ctz_ = 0
62 }
63 // __last.__ctz_ == 0 || __n == 0
64 // __result.__ctz_ == 0 || __n == 0
65 // do middle words
66 __storage_type __nw = __n / __bits_per_word;
67 __result.__seg_ -= __nw;
68 __last.__seg_ -= __nw;
69 std::copy_n(std::__to_address(__last.__seg_), __nw, std::__to_address(__result.__seg_));
70 __n -= __nw * __bits_per_word;
71 // do last word
72 if (__n > 0) {
73 __storage_type __m = std::__leading_mask<__storage_type>(__bits_per_word - __n);
74 __storage_type __b = *--__last.__seg_ & __m;
75 *--__result.__seg_ &= ~__m;
76 *__result.__seg_ |= __b;
77 __result.__ctz_ = static_cast<unsigned>(-__n & (__bits_per_word - 1));
78 }
79 }
80 return __result;
81}
82
83template <class _Cp, bool _IsConst>
84_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_backward_unaligned(
85 __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
86 using _In = __bit_iterator<_Cp, _IsConst>;
87 using difference_type = typename _In::difference_type;
88 using __storage_type = typename _In::__storage_type;
89
90 const int __bits_per_word = _In::__bits_per_word;
91 difference_type __n = __last - __first;
92 if (__n > 0) {
93 // do first word
94 if (__last.__ctz_ != 0) {
95 difference_type __dn = std::min(static_cast<difference_type>(__last.__ctz_), __n);
96 __n -= __dn;
97 unsigned __clz_l = __bits_per_word - __last.__ctz_;
98 __storage_type __m = std::__middle_mask<__storage_type>(__clz_l, __last.__ctz_ - __dn);
99 __storage_type __b = *__last.__seg_ & __m;
100 unsigned __clz_r = __bits_per_word - __result.__ctz_;
101 __storage_type __ddn = std::min(__dn, static_cast<difference_type>(__result.__ctz_));
102 if (__ddn > 0) {
103 __m = std::__middle_mask<__storage_type>(__clz_r, __result.__ctz_ - __ddn);
104 *__result.__seg_ &= ~__m;
105 if (__result.__ctz_ > __last.__ctz_)
106 *__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_);
107 else
108 *__result.__seg_ |= __b >> (__last.__ctz_ - __result.__ctz_);
109 __result.__ctz_ = static_cast<unsigned>(((-__ddn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word);
110 __dn -= __ddn;
111 }
112 if (__dn > 0) {
113 // __result.__ctz_ == 0
114 --__result.__seg_;
115 __result.__ctz_ = static_cast<unsigned>(-__dn & (__bits_per_word - 1));
116 __m = std::__leading_mask<__storage_type>(__result.__ctz_);
117 *__result.__seg_ &= ~__m;
118 __last.__ctz_ -= __dn + __ddn;
119 *__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_);
120 }
121 // __last.__ctz_ = 0
122 }
123 // __last.__ctz_ == 0 || __n == 0
124 // __result.__ctz_ != 0 || __n == 0
125 // do middle words
126 unsigned __clz_r = __bits_per_word - __result.__ctz_;
127 __storage_type __m = std::__trailing_mask<__storage_type>(__clz_r);
128 for (; __n >= __bits_per_word; __n -= __bits_per_word) {
129 __storage_type __b = *--__last.__seg_;
130 *__result.__seg_ &= ~__m;
131 *__result.__seg_ |= __b >> __clz_r;
132 *--__result.__seg_ &= __m;
133 *__result.__seg_ |= __b << __result.__ctz_;
134 }
135 // do last word
136 if (__n > 0) {
137 __m = std::__leading_mask<__storage_type>(__bits_per_word - __n);
138 __storage_type __b = *--__last.__seg_ & __m;
139 __clz_r = __bits_per_word - __result.__ctz_;
140 __storage_type __dn = std::min(__n, static_cast<difference_type>(__result.__ctz_));
141 __m = std::__middle_mask<__storage_type>(__clz_r, __result.__ctz_ - __dn);
142 *__result.__seg_ &= ~__m;
143 *__result.__seg_ |= __b >> (__bits_per_word - __result.__ctz_);
144 __result.__ctz_ = static_cast<unsigned>(((-__dn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word);
145 __n -= __dn;
146 if (__n > 0) {
147 // __result.__ctz_ == 0
148 --__result.__seg_;
149 __result.__ctz_ = static_cast<unsigned>(-__n & (__bits_per_word - 1));
150 __m = std::__leading_mask<__storage_type>(__result.__ctz_);
151 *__result.__seg_ &= ~__m;
152 *__result.__seg_ |= __b << (__result.__ctz_ - (__bits_per_word - __n - __dn));
153 }
154 }
155 }
156 return __result;
157}
158
159template <class _AlgPolicy>
160struct __copy_backward_impl {
161 template <class _InIter, class _Sent, class _OutIter>
162 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
163 operator()(_InIter __first, _Sent __last, _OutIter __result) const {
164 auto __last_iter = _IterOps<_AlgPolicy>::next(__first, __last);
165 auto __original_last_iter = __last_iter;
166
167 while (__first != __last_iter) {
168 *--__result = *--__last_iter;
169 }
170
171 return std::make_pair(std::move(__original_last_iter), std::move(__result));
172 }
173
174 template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator_v<_InIter>, int> = 0>
175 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
176 operator()(_InIter __first, _InIter __last, _OutIter __result) const {
177 using __local_iterator = typename __segmented_iterator_traits<_InIter>::__local_iterator;
178 std::__for_each_segment_backward(__first, __last, [&__result](__local_iterator __lfirst, __local_iterator __llast) {
179 __result = std::__copy_backward<_AlgPolicy>(std::move(__lfirst), std::move(__llast), std::move(__result)).second;
180 });
181 return std::make_pair(__last, std::move(__result));
182 }
183
184 template <class _InIter,
185 class _OutIter,
186 __enable_if_t<__has_random_access_iterator_category<_InIter>::value &&
187 !__is_segmented_iterator_v<_InIter> && __is_segmented_iterator_v<_OutIter>,
188 int> = 0>
189 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
190 operator()(_InIter __first, _InIter __last, _OutIter __result) const {
191 using _Traits = __segmented_iterator_traits<_OutIter>;
192 auto __orig_last = __last;
193 auto __segment_iterator = _Traits::__segment(__result);
194
195 // When the range contains no elements, __result might not be a valid iterator
196 if (__first == __last)
197 return std::make_pair(__first, __result);
198
199 auto __local_last = _Traits::__local(__result);
200 while (true) {
201 using _DiffT =
202 typename common_type<__iterator_difference_type<_InIter>, __iterator_difference_type<_OutIter> >::type;
203
204 auto __local_first = _Traits::__begin(__segment_iterator);
205 auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first);
206 auto __iter = std::__copy_backward<_AlgPolicy>(__last - __size, __last, __local_last).second;
207 __last -= __size;
208
209 if (__first == __last)
210 return std::make_pair(std::move(__orig_last), _Traits::__compose(__segment_iterator, std::move(__iter)));
211 --__segment_iterator;
212 __local_last = _Traits::__end(__segment_iterator);
213 }
214 }
215
216 template <class _Cp, bool _IsConst>
217 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cp, _IsConst>, __bit_iterator<_Cp, false> >
218 operator()(__bit_iterator<_Cp, _IsConst> __first,
219 __bit_iterator<_Cp, _IsConst> __last,
220 __bit_iterator<_Cp, false> __result) {
221 if (__last.__ctz_ == __result.__ctz_)
222 return std::make_pair(__last, std::__copy_backward_aligned(__first, __last, __result));
223 return std::make_pair(__last, std::__copy_backward_unaligned(__first, __last, __result));
224 }
225
226 // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer.
227 template <class _In, class _Out, __enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0>
228 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
229 operator()(_In* __first, _In* __last, _Out* __result) const {
230 return std::__copy_backward_trivial_impl(__first, __last, __result);
231 }
232};
233
234template <class _AlgPolicy, class _BidirectionalIterator1, class _Sentinel, class _BidirectionalIterator2>
235_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator1, _BidirectionalIterator2>
236__copy_backward(_BidirectionalIterator1 __first, _Sentinel __last, _BidirectionalIterator2 __result) {
237 return std::__copy_move_unwrap_iters<__copy_backward_impl<_AlgPolicy> >(
238 std::move(__first), std::move(__last), std::move(__result));
239}
240
241template <class _BidirectionalIterator1, class _BidirectionalIterator2>
242inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _BidirectionalIterator2
243copy_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, _BidirectionalIterator2 __result) {
244 static_assert(std::is_copy_constructible<_BidirectionalIterator1>::value &&
245 std::is_copy_constructible<_BidirectionalIterator1>::value,
246 "Iterators must be copy constructible.");
247
248 return std::__copy_backward<_ClassicAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)).second;
249}
250
251_LIBCPP_END_NAMESPACE_STD
252
253_LIBCPP_POP_MACROS
254
255#endif // _LIBCPP___ALGORITHM_COPY_BACKWARD_H
256