1313#include < __algorithm/for_each_segment.h>
1414#include < __algorithm/min.h>
1515#include < __config>
16+ #include < __fwd/bit_reference.h>
1617#include < __iterator/iterator_traits.h>
1718#include < __iterator/segmented_iterator.h>
1819#include < __type_traits/common_type.h>
@@ -29,9 +30,129 @@ _LIBCPP_PUSH_MACROS
2930
3031_LIBCPP_BEGIN_NAMESPACE_STD
3132
33+ template <class _InputIterator , class _OutputIterator >
34+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
35+ copy (_InputIterator __first, _InputIterator __last, _OutputIterator __result);
36+
3237template <class _InIter , class _Sent , class _OutIter >
3338inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> __copy (_InIter, _Sent, _OutIter);
3439
40+ template <class _Cp , bool _IsConst>
41+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false > __copy_aligned (
42+ __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false > __result) {
43+ using _In = __bit_iterator<_Cp, _IsConst>;
44+ using difference_type = typename _In::difference_type;
45+ using __storage_type = typename _In::__storage_type;
46+
47+ const int __bits_per_word = _In::__bits_per_word;
48+ difference_type __n = __last - __first;
49+ if (__n > 0 ) {
50+ // do first word
51+ if (__first.__ctz_ != 0 ) {
52+ unsigned __clz = __bits_per_word - __first.__ctz_ ;
53+ difference_type __dn = std::min (static_cast <difference_type>(__clz), __n);
54+ __n -= __dn;
55+ __storage_type __m = (~__storage_type (0 ) << __first.__ctz_ ) & (~__storage_type (0 ) >> (__clz - __dn));
56+ __storage_type __b = *__first.__seg_ & __m;
57+ *__result.__seg_ &= ~__m;
58+ *__result.__seg_ |= __b;
59+ __result.__seg_ += (__dn + __result.__ctz_ ) / __bits_per_word;
60+ __result.__ctz_ = static_cast <unsigned >((__dn + __result.__ctz_ ) % __bits_per_word);
61+ ++__first.__seg_ ;
62+ // __first.__ctz_ = 0;
63+ }
64+ // __first.__ctz_ == 0;
65+ // do middle words
66+ __storage_type __nw = __n / __bits_per_word;
67+ std::copy (std::__to_address (__first.__seg_ ),
68+ std::__to_address (__first.__seg_ + __nw),
69+ std::__to_address (__result.__seg_ ));
70+ __n -= __nw * __bits_per_word;
71+ __result.__seg_ += __nw;
72+ // do last word
73+ if (__n > 0 ) {
74+ __first.__seg_ += __nw;
75+ __storage_type __m = ~__storage_type (0 ) >> (__bits_per_word - __n);
76+ __storage_type __b = *__first.__seg_ & __m;
77+ *__result.__seg_ &= ~__m;
78+ *__result.__seg_ |= __b;
79+ __result.__ctz_ = static_cast <unsigned >(__n);
80+ }
81+ }
82+ return __result;
83+ }
84+
85+ template <class _Cp , bool _IsConst>
86+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false > __copy_unaligned (
87+ __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false > __result) {
88+ using _In = __bit_iterator<_Cp, _IsConst>;
89+ using difference_type = typename _In::difference_type;
90+ using __storage_type = typename _In::__storage_type;
91+
92+ const int __bits_per_word = _In::__bits_per_word;
93+ difference_type __n = __last - __first;
94+ if (__n > 0 ) {
95+ // do first word
96+ if (__first.__ctz_ != 0 ) {
97+ unsigned __clz_f = __bits_per_word - __first.__ctz_ ;
98+ difference_type __dn = std::min (static_cast <difference_type>(__clz_f), __n);
99+ __n -= __dn;
100+ __storage_type __m = (~__storage_type (0 ) << __first.__ctz_ ) & (~__storage_type (0 ) >> (__clz_f - __dn));
101+ __storage_type __b = *__first.__seg_ & __m;
102+ unsigned __clz_r = __bits_per_word - __result.__ctz_ ;
103+ __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
104+ __m = (~__storage_type (0 ) << __result.__ctz_ ) & (~__storage_type (0 ) >> (__clz_r - __ddn));
105+ *__result.__seg_ &= ~__m;
106+ if (__result.__ctz_ > __first.__ctz_ )
107+ *__result.__seg_ |= __b << (__result.__ctz_ - __first.__ctz_ );
108+ else
109+ *__result.__seg_ |= __b >> (__first.__ctz_ - __result.__ctz_ );
110+ __result.__seg_ += (__ddn + __result.__ctz_ ) / __bits_per_word;
111+ __result.__ctz_ = static_cast <unsigned >((__ddn + __result.__ctz_ ) % __bits_per_word);
112+ __dn -= __ddn;
113+ if (__dn > 0 ) {
114+ __m = ~__storage_type (0 ) >> (__bits_per_word - __dn);
115+ *__result.__seg_ &= ~__m;
116+ *__result.__seg_ |= __b >> (__first.__ctz_ + __ddn);
117+ __result.__ctz_ = static_cast <unsigned >(__dn);
118+ }
119+ ++__first.__seg_ ;
120+ // __first.__ctz_ = 0;
121+ }
122+ // __first.__ctz_ == 0;
123+ // do middle words
124+ unsigned __clz_r = __bits_per_word - __result.__ctz_ ;
125+ __storage_type __m = ~__storage_type (0 ) << __result.__ctz_ ;
126+ for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_ ) {
127+ __storage_type __b = *__first.__seg_ ;
128+ *__result.__seg_ &= ~__m;
129+ *__result.__seg_ |= __b << __result.__ctz_ ;
130+ ++__result.__seg_ ;
131+ *__result.__seg_ &= __m;
132+ *__result.__seg_ |= __b >> __clz_r;
133+ }
134+ // do last word
135+ if (__n > 0 ) {
136+ __m = ~__storage_type (0 ) >> (__bits_per_word - __n);
137+ __storage_type __b = *__first.__seg_ & __m;
138+ __storage_type __dn = std::min (__n, static_cast <difference_type>(__clz_r));
139+ __m = (~__storage_type (0 ) << __result.__ctz_ ) & (~__storage_type (0 ) >> (__clz_r - __dn));
140+ *__result.__seg_ &= ~__m;
141+ *__result.__seg_ |= __b << __result.__ctz_ ;
142+ __result.__seg_ += (__dn + __result.__ctz_ ) / __bits_per_word;
143+ __result.__ctz_ = static_cast <unsigned >((__dn + __result.__ctz_ ) % __bits_per_word);
144+ __n -= __dn;
145+ if (__n > 0 ) {
146+ __m = ~__storage_type (0 ) >> (__bits_per_word - __n);
147+ *__result.__seg_ &= ~__m;
148+ *__result.__seg_ |= __b >> __dn;
149+ __result.__ctz_ = static_cast <unsigned >(__n);
150+ }
151+ }
152+ }
153+ return __result;
154+ }
155+
35156struct __copy_impl {
36157 template <class _InIter , class _Sent , class _OutIter >
37158 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
@@ -95,6 +216,16 @@ struct __copy_impl {
95216 }
96217 }
97218
219+ template <class _Cp , bool _IsConst>
220+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cp, _IsConst>, __bit_iterator<_Cp, false > >
221+ operator ()(__bit_iterator<_Cp, _IsConst> __first,
222+ __bit_iterator<_Cp, _IsConst> __last,
223+ __bit_iterator<_Cp, false > __result) {
224+ if (__first.__ctz_ == __result.__ctz_ )
225+ return std::make_pair (__last, std::__copy_aligned (__first, __last, __result));
226+ return std::make_pair (__last, std::__copy_unaligned (__first, __last, __result));
227+ }
228+
98229 // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer.
99230 template <class _In , class _Out , __enable_if_t <__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int > = 0 >
100231 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
@@ -110,7 +241,7 @@ __copy(_InIter __first, _Sent __last, _OutIter __result) {
110241}
111242
112243template <class _InputIterator , class _OutputIterator >
113- inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
244+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
114245copy (_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
115246 return std::__copy (__first, __last, __result).second ;
116247}
0 commit comments