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>
19+ #include < __memory/pointer_traits.h>
1820#include < __type_traits/common_type.h>
1921#include < __type_traits/enable_if.h>
2022#include < __utility/move.h>
@@ -29,9 +31,129 @@ _LIBCPP_PUSH_MACROS
2931
3032_LIBCPP_BEGIN_NAMESPACE_STD
3133
34+ template <class _InputIterator , class _OutputIterator >
35+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
36+ copy (_InputIterator __first, _InputIterator __last, _OutputIterator __result);
37+
3238template <class _InIter , class _Sent , class _OutIter >
3339inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> __copy (_InIter, _Sent, _OutIter);
3440
41+ template <class _Cp , bool _IsConst>
42+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false > __copy_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 (__first.__ctz_ != 0 ) {
53+ unsigned __clz = __bits_per_word - __first.__ctz_ ;
54+ difference_type __dn = std::min (static_cast <difference_type>(__clz), __n);
55+ __n -= __dn;
56+ __storage_type __m = (~__storage_type (0 ) << __first.__ctz_ ) & (~__storage_type (0 ) >> (__clz - __dn));
57+ __storage_type __b = *__first.__seg_ & __m;
58+ *__result.__seg_ &= ~__m;
59+ *__result.__seg_ |= __b;
60+ __result.__seg_ += (__dn + __result.__ctz_ ) / __bits_per_word;
61+ __result.__ctz_ = static_cast <unsigned >((__dn + __result.__ctz_ ) % __bits_per_word);
62+ ++__first.__seg_ ;
63+ // __first.__ctz_ = 0;
64+ }
65+ // __first.__ctz_ == 0;
66+ // do middle words
67+ __storage_type __nw = __n / __bits_per_word;
68+ std::copy (std::__to_address (__first.__seg_ ),
69+ std::__to_address (__first.__seg_ + __nw),
70+ std::__to_address (__result.__seg_ ));
71+ __n -= __nw * __bits_per_word;
72+ __result.__seg_ += __nw;
73+ // do last word
74+ if (__n > 0 ) {
75+ __first.__seg_ += __nw;
76+ __storage_type __m = ~__storage_type (0 ) >> (__bits_per_word - __n);
77+ __storage_type __b = *__first.__seg_ & __m;
78+ *__result.__seg_ &= ~__m;
79+ *__result.__seg_ |= __b;
80+ __result.__ctz_ = static_cast <unsigned >(__n);
81+ }
82+ }
83+ return __result;
84+ }
85+
86+ template <class _Cp , bool _IsConst>
87+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false > __copy_unaligned (
88+ __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false > __result) {
89+ using _In = __bit_iterator<_Cp, _IsConst>;
90+ using difference_type = typename _In::difference_type;
91+ using __storage_type = typename _In::__storage_type;
92+
93+ const int __bits_per_word = _In::__bits_per_word;
94+ difference_type __n = __last - __first;
95+ if (__n > 0 ) {
96+ // do first word
97+ if (__first.__ctz_ != 0 ) {
98+ unsigned __clz_f = __bits_per_word - __first.__ctz_ ;
99+ difference_type __dn = std::min (static_cast <difference_type>(__clz_f), __n);
100+ __n -= __dn;
101+ __storage_type __m = (~__storage_type (0 ) << __first.__ctz_ ) & (~__storage_type (0 ) >> (__clz_f - __dn));
102+ __storage_type __b = *__first.__seg_ & __m;
103+ unsigned __clz_r = __bits_per_word - __result.__ctz_ ;
104+ __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
105+ __m = (~__storage_type (0 ) << __result.__ctz_ ) & (~__storage_type (0 ) >> (__clz_r - __ddn));
106+ *__result.__seg_ &= ~__m;
107+ if (__result.__ctz_ > __first.__ctz_ )
108+ *__result.__seg_ |= __b << (__result.__ctz_ - __first.__ctz_ );
109+ else
110+ *__result.__seg_ |= __b >> (__first.__ctz_ - __result.__ctz_ );
111+ __result.__seg_ += (__ddn + __result.__ctz_ ) / __bits_per_word;
112+ __result.__ctz_ = static_cast <unsigned >((__ddn + __result.__ctz_ ) % __bits_per_word);
113+ __dn -= __ddn;
114+ if (__dn > 0 ) {
115+ __m = ~__storage_type (0 ) >> (__bits_per_word - __dn);
116+ *__result.__seg_ &= ~__m;
117+ *__result.__seg_ |= __b >> (__first.__ctz_ + __ddn);
118+ __result.__ctz_ = static_cast <unsigned >(__dn);
119+ }
120+ ++__first.__seg_ ;
121+ // __first.__ctz_ = 0;
122+ }
123+ // __first.__ctz_ == 0;
124+ // do middle words
125+ unsigned __clz_r = __bits_per_word - __result.__ctz_ ;
126+ __storage_type __m = ~__storage_type (0 ) << __result.__ctz_ ;
127+ for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_ ) {
128+ __storage_type __b = *__first.__seg_ ;
129+ *__result.__seg_ &= ~__m;
130+ *__result.__seg_ |= __b << __result.__ctz_ ;
131+ ++__result.__seg_ ;
132+ *__result.__seg_ &= __m;
133+ *__result.__seg_ |= __b >> __clz_r;
134+ }
135+ // do last word
136+ if (__n > 0 ) {
137+ __m = ~__storage_type (0 ) >> (__bits_per_word - __n);
138+ __storage_type __b = *__first.__seg_ & __m;
139+ __storage_type __dn = std::min (__n, static_cast <difference_type>(__clz_r));
140+ __m = (~__storage_type (0 ) << __result.__ctz_ ) & (~__storage_type (0 ) >> (__clz_r - __dn));
141+ *__result.__seg_ &= ~__m;
142+ *__result.__seg_ |= __b << __result.__ctz_ ;
143+ __result.__seg_ += (__dn + __result.__ctz_ ) / __bits_per_word;
144+ __result.__ctz_ = static_cast <unsigned >((__dn + __result.__ctz_ ) % __bits_per_word);
145+ __n -= __dn;
146+ if (__n > 0 ) {
147+ __m = ~__storage_type (0 ) >> (__bits_per_word - __n);
148+ *__result.__seg_ &= ~__m;
149+ *__result.__seg_ |= __b >> __dn;
150+ __result.__ctz_ = static_cast <unsigned >(__n);
151+ }
152+ }
153+ }
154+ return __result;
155+ }
156+
35157struct __copy_impl {
36158 template <class _InIter , class _Sent , class _OutIter >
37159 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
@@ -95,6 +217,16 @@ struct __copy_impl {
95217 }
96218 }
97219
220+ template <class _Cp , bool _IsConst>
221+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cp, _IsConst>, __bit_iterator<_Cp, false > >
222+ operator ()(__bit_iterator<_Cp, _IsConst> __first,
223+ __bit_iterator<_Cp, _IsConst> __last,
224+ __bit_iterator<_Cp, false > __result) const {
225+ if (__first.__ctz_ == __result.__ctz_ )
226+ return std::make_pair (__last, std::__copy_aligned (__first, __last, __result));
227+ return std::make_pair (__last, std::__copy_unaligned (__first, __last, __result));
228+ }
229+
98230 // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer.
99231 template <class _In , class _Out , __enable_if_t <__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int > = 0 >
100232 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
@@ -110,7 +242,7 @@ __copy(_InIter __first, _Sent __last, _OutIter __result) {
110242}
111243
112244template <class _InputIterator , class _OutputIterator >
113- inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
245+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
114246copy (_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
115247 return std::__copy (__first, __last, __result).second ;
116248}
0 commit comments