2 //===----------------------------------------------------------------------===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___BIT_REFERENCE
11 #define _LIBCPP___BIT_REFERENCE
13 #include <__algorithm/copy_n.h>
14 #include <__algorithm/fill_n.h>
15 #include <__algorithm/min.h>
16 #include <__bit/countr.h>
17 #include <__bit/invert_if.h>
18 #include <__bit/popcount.h>
19 #include <__compare/ordering.h>
21 #include <__fwd/bit_reference.h>
22 #include <__iterator/iterator_traits.h>
23 #include <__memory/construct_at.h>
24 #include <__memory/pointer_traits.h>
25 #include <__type_traits/conditional.h>
26 #include <__utility/swap.h>
29 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
30 # pragma GCC system_header
34 #include <__undef_macros>
36 _LIBCPP_BEGIN_NAMESPACE_STD
39 class __bit_const_reference;
42 struct __has_storage_type {
43 static const bool value = false;
46 template <class _Cp, bool = __has_storage_type<_Cp>::value>
47 class __bit_reference {
48 using __storage_type = typename _Cp::__storage_type;
49 using __storage_pointer = typename _Cp::__storage_pointer;
51 __storage_pointer __seg_;
52 __storage_type __mask_;
54 friend typename _Cp::__self;
56 friend class __bit_const_reference<_Cp>;
57 friend class __bit_iterator<_Cp, false>;
60 using __container = typename _Cp::__self;
62 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_reference(const __bit_reference&) = default;
64 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 operator bool() const _NOEXCEPT {
65 return static_cast<bool>(*__seg_ & __mask_);
67 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool operator~() const _NOEXCEPT {
68 return !static_cast<bool>(*this);
71 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_reference& operator=(bool __x) _NOEXCEPT {
79 #if _LIBCPP_STD_VER >= 23
80 _LIBCPP_HIDE_FROM_ABI constexpr const __bit_reference& operator=(bool __x) const noexcept {
89 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_reference& operator=(const __bit_reference& __x) _NOEXCEPT {
90 return operator=(static_cast<bool>(__x));
93 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void flip() _NOEXCEPT { *__seg_ ^= __mask_; }
94 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false> operator&() const _NOEXCEPT {
95 return __bit_iterator<_Cp, false>(__seg_, static_cast<unsigned>(std::__libcpp_ctz(__mask_)));
100 _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bit_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT
106 class __bit_reference<_Cp, false> {};
109 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
110 swap(__bit_reference<_Cp> __x, __bit_reference<_Cp> __y) _NOEXCEPT {
116 template <class _Cp, class _Dp>
117 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
118 swap(__bit_reference<_Cp> __x, __bit_reference<_Dp> __y) _NOEXCEPT {
125 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(__bit_reference<_Cp> __x, bool& __y) _NOEXCEPT {
132 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(bool& __x, __bit_reference<_Cp> __y) _NOEXCEPT {
139 class __bit_const_reference {
140 using __storage_type = typename _Cp::__storage_type;
141 using __storage_pointer = typename _Cp::__const_storage_pointer;
143 __storage_pointer __seg_;
144 __storage_type __mask_;
146 friend typename _Cp::__self;
147 friend class __bit_iterator<_Cp, true>;
150 using __container = typename _Cp::__self;
152 _LIBCPP_HIDE_FROM_ABI __bit_const_reference(const __bit_const_reference&) = default;
153 __bit_const_reference& operator=(const __bit_const_reference&) = delete;
155 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_const_reference(const __bit_reference<_Cp>& __x) _NOEXCEPT
156 : __seg_(__x.__seg_),
157 __mask_(__x.__mask_) {}
159 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR operator bool() const _NOEXCEPT {
160 return static_cast<bool>(*__seg_ & __mask_);
163 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, true> operator&() const _NOEXCEPT {
164 return __bit_iterator<_Cp, true>(__seg_, static_cast<unsigned>(std::__libcpp_ctz(__mask_)));
168 _LIBCPP_HIDE_FROM_ABI
169 _LIBCPP_CONSTEXPR explicit __bit_const_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT
176 template <class _Cp, bool _IsConst>
177 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_aligned(
178 __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
179 using _In = __bit_iterator<_Cp, _IsConst>;
180 using difference_type = typename _In::difference_type;
181 using __storage_type = typename _In::__storage_type;
183 const int __bits_per_word = _In::__bits_per_word;
184 difference_type __n = __last - __first;
187 if (__first.__ctz_ != 0) {
188 unsigned __clz = __bits_per_word - __first.__ctz_;
189 difference_type __dn = std::min(static_cast<difference_type>(__clz), __n);
191 __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn));
192 __storage_type __b = *__first.__seg_ & __m;
193 *__result.__seg_ &= ~__m;
194 *__result.__seg_ |= __b;
195 __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
196 __result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
198 // __first.__ctz_ = 0;
200 // __first.__ctz_ == 0;
202 __storage_type __nw = __n / __bits_per_word;
203 std::copy_n(std::__to_address(__first.__seg_), __nw, std::__to_address(__result.__seg_));
204 __n -= __nw * __bits_per_word;
205 __result.__seg_ += __nw;
208 __first.__seg_ += __nw;
209 __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
210 __storage_type __b = *__first.__seg_ & __m;
211 *__result.__seg_ &= ~__m;
212 *__result.__seg_ |= __b;
213 __result.__ctz_ = static_cast<unsigned>(__n);
219 template <class _Cp, bool _IsConst>
220 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_unaligned(
221 __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
222 using _In = __bit_iterator<_Cp, _IsConst>;
223 using difference_type = typename _In::difference_type;
224 using __storage_type = typename _In::__storage_type;
226 const int __bits_per_word = _In::__bits_per_word;
227 difference_type __n = __last - __first;
230 if (__first.__ctz_ != 0) {
231 unsigned __clz_f = __bits_per_word - __first.__ctz_;
232 difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n);
234 __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
235 __storage_type __b = *__first.__seg_ & __m;
236 unsigned __clz_r = __bits_per_word - __result.__ctz_;
237 __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
238 __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn));
239 *__result.__seg_ &= ~__m;
240 if (__result.__ctz_ > __first.__ctz_)
241 *__result.__seg_ |= __b << (__result.__ctz_ - __first.__ctz_);
243 *__result.__seg_ |= __b >> (__first.__ctz_ - __result.__ctz_);
244 __result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word;
245 __result.__ctz_ = static_cast<unsigned>((__ddn + __result.__ctz_) % __bits_per_word);
248 __m = ~__storage_type(0) >> (__bits_per_word - __dn);
249 *__result.__seg_ &= ~__m;
250 *__result.__seg_ |= __b >> (__first.__ctz_ + __ddn);
251 __result.__ctz_ = static_cast<unsigned>(__dn);
254 // __first.__ctz_ = 0;
256 // __first.__ctz_ == 0;
258 unsigned __clz_r = __bits_per_word - __result.__ctz_;
259 __storage_type __m = ~__storage_type(0) << __result.__ctz_;
260 for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) {
261 __storage_type __b = *__first.__seg_;
262 *__result.__seg_ &= ~__m;
263 *__result.__seg_ |= __b << __result.__ctz_;
265 *__result.__seg_ &= __m;
266 *__result.__seg_ |= __b >> __clz_r;
270 __m = ~__storage_type(0) >> (__bits_per_word - __n);
271 __storage_type __b = *__first.__seg_ & __m;
272 __storage_type __dn = std::min(__n, static_cast<difference_type>(__clz_r));
273 __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn));
274 *__result.__seg_ &= ~__m;
275 *__result.__seg_ |= __b << __result.__ctz_;
276 __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
277 __result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
280 __m = ~__storage_type(0) >> (__bits_per_word - __n);
281 *__result.__seg_ &= ~__m;
282 *__result.__seg_ |= __b >> __dn;
283 __result.__ctz_ = static_cast<unsigned>(__n);
290 template <class _Cp, bool _IsConst>
291 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false>
292 copy(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
293 if (__first.__ctz_ == __result.__ctz_)
294 return std::__copy_aligned(__first, __last, __result);
295 return std::__copy_unaligned(__first, __last, __result);
300 template <class _Cp, bool _IsConst>
301 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_backward_aligned(
302 __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
303 using _In = __bit_iterator<_Cp, _IsConst>;
304 using difference_type = typename _In::difference_type;
305 using __storage_type = typename _In::__storage_type;
307 const int __bits_per_word = _In::__bits_per_word;
308 difference_type __n = __last - __first;
311 if (__last.__ctz_ != 0) {
312 difference_type __dn = std::min(static_cast<difference_type>(__last.__ctz_), __n);
314 unsigned __clz = __bits_per_word - __last.__ctz_;
315 __storage_type __m = (~__storage_type(0) << (__last.__ctz_ - __dn)) & (~__storage_type(0) >> __clz);
316 __storage_type __b = *__last.__seg_ & __m;
317 *__result.__seg_ &= ~__m;
318 *__result.__seg_ |= __b;
319 __result.__ctz_ = static_cast<unsigned>(((-__dn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word);
322 // __last.__ctz_ == 0 || __n == 0
323 // __result.__ctz_ == 0 || __n == 0
325 __storage_type __nw = __n / __bits_per_word;
326 __result.__seg_ -= __nw;
327 __last.__seg_ -= __nw;
328 std::copy_n(std::__to_address(__last.__seg_), __nw, std::__to_address(__result.__seg_));
329 __n -= __nw * __bits_per_word;
332 __storage_type __m = ~__storage_type(0) << (__bits_per_word - __n);
333 __storage_type __b = *--__last.__seg_ & __m;
334 *--__result.__seg_ &= ~__m;
335 *__result.__seg_ |= __b;
336 __result.__ctz_ = static_cast<unsigned>(-__n & (__bits_per_word - 1));
342 template <class _Cp, bool _IsConst>
343 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_backward_unaligned(
344 __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
345 using _In = __bit_iterator<_Cp, _IsConst>;
346 using difference_type = typename _In::difference_type;
347 using __storage_type = typename _In::__storage_type;
349 const int __bits_per_word = _In::__bits_per_word;
350 difference_type __n = __last - __first;
353 if (__last.__ctz_ != 0) {
354 difference_type __dn = std::min(static_cast<difference_type>(__last.__ctz_), __n);
356 unsigned __clz_l = __bits_per_word - __last.__ctz_;
357 __storage_type __m = (~__storage_type(0) << (__last.__ctz_ - __dn)) & (~__storage_type(0) >> __clz_l);
358 __storage_type __b = *__last.__seg_ & __m;
359 unsigned __clz_r = __bits_per_word - __result.__ctz_;
360 __storage_type __ddn = std::min(__dn, static_cast<difference_type>(__result.__ctz_));
362 __m = (~__storage_type(0) << (__result.__ctz_ - __ddn)) & (~__storage_type(0) >> __clz_r);
363 *__result.__seg_ &= ~__m;
364 if (__result.__ctz_ > __last.__ctz_)
365 *__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_);
367 *__result.__seg_ |= __b >> (__last.__ctz_ - __result.__ctz_);
368 __result.__ctz_ = static_cast<unsigned>(((-__ddn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word);
372 // __result.__ctz_ == 0
374 __result.__ctz_ = static_cast<unsigned>(-__dn & (__bits_per_word - 1));
375 __m = ~__storage_type(0) << __result.__ctz_;
376 *__result.__seg_ &= ~__m;
377 __last.__ctz_ -= __dn + __ddn;
378 *__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_);
382 // __last.__ctz_ == 0 || __n == 0
383 // __result.__ctz_ != 0 || __n == 0
385 unsigned __clz_r = __bits_per_word - __result.__ctz_;
386 __storage_type __m = ~__storage_type(0) >> __clz_r;
387 for (; __n >= __bits_per_word; __n -= __bits_per_word) {
388 __storage_type __b = *--__last.__seg_;
389 *__result.__seg_ &= ~__m;
390 *__result.__seg_ |= __b >> __clz_r;
391 *--__result.__seg_ &= __m;
392 *__result.__seg_ |= __b << __result.__ctz_;
396 __m = ~__storage_type(0) << (__bits_per_word - __n);
397 __storage_type __b = *--__last.__seg_ & __m;
398 __clz_r = __bits_per_word - __result.__ctz_;
399 __storage_type __dn = std::min(__n, static_cast<difference_type>(__result.__ctz_));
400 __m = (~__storage_type(0) << (__result.__ctz_ - __dn)) & (~__storage_type(0) >> __clz_r);
401 *__result.__seg_ &= ~__m;
402 *__result.__seg_ |= __b >> (__bits_per_word - __result.__ctz_);
403 __result.__ctz_ = static_cast<unsigned>(((-__dn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word);
406 // __result.__ctz_ == 0
408 __result.__ctz_ = static_cast<unsigned>(-__n & (__bits_per_word - 1));
409 __m = ~__storage_type(0) << __result.__ctz_;
410 *__result.__seg_ &= ~__m;
411 *__result.__seg_ |= __b << (__result.__ctz_ - (__bits_per_word - __n - __dn));
418 template <class _Cp, bool _IsConst>
419 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false> copy_backward(
420 __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
421 if (__last.__ctz_ == __result.__ctz_)
422 return std::__copy_backward_aligned(__first, __last, __result);
423 return std::__copy_backward_unaligned(__first, __last, __result);
428 template <class _Cp, bool _IsConst>
429 inline _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false>
430 move(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
431 return std::copy(__first, __last, __result);
436 template <class _Cp, bool _IsConst>
437 inline _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> move_backward(
438 __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
439 return std::copy_backward(__first, __last, __result);
444 template <class _Cl, class _Cr>
445 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cr, false> __swap_ranges_aligned(
446 __bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, __bit_iterator<_Cr, false> __result) {
447 using _I1 = __bit_iterator<_Cl, false>;
448 using difference_type = typename _I1::difference_type;
449 using __storage_type = typename _I1::__storage_type;
451 const int __bits_per_word = _I1::__bits_per_word;
452 difference_type __n = __last - __first;
455 if (__first.__ctz_ != 0) {
456 unsigned __clz = __bits_per_word - __first.__ctz_;
457 difference_type __dn = std::min(static_cast<difference_type>(__clz), __n);
459 __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn));
460 __storage_type __b1 = *__first.__seg_ & __m;
461 *__first.__seg_ &= ~__m;
462 __storage_type __b2 = *__result.__seg_ & __m;
463 *__result.__seg_ &= ~__m;
464 *__result.__seg_ |= __b1;
465 *__first.__seg_ |= __b2;
466 __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
467 __result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
469 // __first.__ctz_ = 0;
471 // __first.__ctz_ == 0;
473 for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_, ++__result.__seg_)
474 swap(*__first.__seg_, *__result.__seg_);
477 __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
478 __storage_type __b1 = *__first.__seg_ & __m;
479 *__first.__seg_ &= ~__m;
480 __storage_type __b2 = *__result.__seg_ & __m;
481 *__result.__seg_ &= ~__m;
482 *__result.__seg_ |= __b1;
483 *__first.__seg_ |= __b2;
484 __result.__ctz_ = static_cast<unsigned>(__n);
490 template <class _Cl, class _Cr>
491 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cr, false> __swap_ranges_unaligned(
492 __bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, __bit_iterator<_Cr, false> __result) {
493 using _I1 = __bit_iterator<_Cl, false>;
494 using difference_type = typename _I1::difference_type;
495 using __storage_type = typename _I1::__storage_type;
497 const int __bits_per_word = _I1::__bits_per_word;
498 difference_type __n = __last - __first;
501 if (__first.__ctz_ != 0) {
502 unsigned __clz_f = __bits_per_word - __first.__ctz_;
503 difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n);
505 __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
506 __storage_type __b1 = *__first.__seg_ & __m;
507 *__first.__seg_ &= ~__m;
508 unsigned __clz_r = __bits_per_word - __result.__ctz_;
509 __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
510 __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn));
511 __storage_type __b2 = *__result.__seg_ & __m;
512 *__result.__seg_ &= ~__m;
513 if (__result.__ctz_ > __first.__ctz_) {
514 unsigned __s = __result.__ctz_ - __first.__ctz_;
515 *__result.__seg_ |= __b1 << __s;
516 *__first.__seg_ |= __b2 >> __s;
518 unsigned __s = __first.__ctz_ - __result.__ctz_;
519 *__result.__seg_ |= __b1 >> __s;
520 *__first.__seg_ |= __b2 << __s;
522 __result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word;
523 __result.__ctz_ = static_cast<unsigned>((__ddn + __result.__ctz_) % __bits_per_word);
526 __m = ~__storage_type(0) >> (__bits_per_word - __dn);
527 __b2 = *__result.__seg_ & __m;
528 *__result.__seg_ &= ~__m;
529 unsigned __s = __first.__ctz_ + __ddn;
530 *__result.__seg_ |= __b1 >> __s;
531 *__first.__seg_ |= __b2 << __s;
532 __result.__ctz_ = static_cast<unsigned>(__dn);
535 // __first.__ctz_ = 0;
537 // __first.__ctz_ == 0;
539 __storage_type __m = ~__storage_type(0) << __result.__ctz_;
540 unsigned __clz_r = __bits_per_word - __result.__ctz_;
541 for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) {
542 __storage_type __b1 = *__first.__seg_;
543 __storage_type __b2 = *__result.__seg_ & __m;
544 *__result.__seg_ &= ~__m;
545 *__result.__seg_ |= __b1 << __result.__ctz_;
546 *__first.__seg_ = __b2 >> __result.__ctz_;
548 __b2 = *__result.__seg_ & ~__m;
549 *__result.__seg_ &= __m;
550 *__result.__seg_ |= __b1 >> __clz_r;
551 *__first.__seg_ |= __b2 << __clz_r;
555 __m = ~__storage_type(0) >> (__bits_per_word - __n);
556 __storage_type __b1 = *__first.__seg_ & __m;
557 *__first.__seg_ &= ~__m;
558 __storage_type __dn = std::min<__storage_type>(__n, __clz_r);
559 __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn));
560 __storage_type __b2 = *__result.__seg_ & __m;
561 *__result.__seg_ &= ~__m;
562 *__result.__seg_ |= __b1 << __result.__ctz_;
563 *__first.__seg_ |= __b2 >> __result.__ctz_;
564 __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
565 __result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
568 __m = ~__storage_type(0) >> (__bits_per_word - __n);
569 __b2 = *__result.__seg_ & __m;
570 *__result.__seg_ &= ~__m;
571 *__result.__seg_ |= __b1 >> __dn;
572 *__first.__seg_ |= __b2 << __dn;
573 __result.__ctz_ = static_cast<unsigned>(__n);
580 template <class _Cl, class _Cr>
581 inline _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cr, false> swap_ranges(
582 __bit_iterator<_Cl, false> __first1, __bit_iterator<_Cl, false> __last1, __bit_iterator<_Cr, false> __first2) {
583 if (__first1.__ctz_ == __first2.__ctz_)
584 return std::__swap_ranges_aligned(__first1, __last1, __first2);
585 return std::__swap_ranges_unaligned(__first1, __last1, __first2);
592 using difference_type = typename _Cp::difference_type;
593 using __storage_type = typename _Cp::__storage_type;
594 using __storage_pointer = typename _Cp::__storage_pointer;
595 using iterator = typename _Cp::iterator;
597 static const unsigned __bits_per_word = _Cp::__bits_per_word;
598 static const unsigned _Np = 4;
600 difference_type __size_;
601 __storage_type __word_[_Np];
603 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static difference_type capacity() {
604 return static_cast<difference_type>(_Np * __bits_per_word);
606 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bit_array(difference_type __s) : __size_(__s) {
607 if (__libcpp_is_constant_evaluated()) {
608 for (size_t __i = 0; __i != __bit_array<_Cp>::_Np; ++__i)
609 std::__construct_at(__word_ + __i, 0);
612 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator begin() {
613 return iterator(pointer_traits<__storage_pointer>::pointer_to(__word_[0]), 0);
615 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator end() {
616 return iterator(pointer_traits<__storage_pointer>::pointer_to(__word_[0]) + __size_ / __bits_per_word,
617 static_cast<unsigned>(__size_ % __bits_per_word));
622 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false>
623 rotate(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __middle, __bit_iterator<_Cp, false> __last) {
624 using _I1 = __bit_iterator<_Cp, false>;
625 using difference_type = typename _I1::difference_type;
627 difference_type __d1 = __middle - __first;
628 difference_type __d2 = __last - __middle;
629 _I1 __r = __first + __d2;
630 while (__d1 != 0 && __d2 != 0) {
632 if (__d1 <= __bit_array<_Cp>::capacity()) {
633 __bit_array<_Cp> __b(__d1);
634 std::copy(__first, __middle, __b.begin());
635 std::copy(__b.begin(), __b.end(), std::copy(__middle, __last, __first));
638 __bit_iterator<_Cp, false> __mp = std::swap_ranges(__first, __middle, __middle);
644 if (__d2 <= __bit_array<_Cp>::capacity()) {
645 __bit_array<_Cp> __b(__d2);
646 std::copy(__middle, __last, __b.begin());
647 std::copy_backward(__b.begin(), __b.end(), std::copy_backward(__first, __middle, __last));
650 __bit_iterator<_Cp, false> __mp = __first + __d2;
651 std::swap_ranges(__first, __mp, __middle);
662 template <class _Cp, bool _IC1, bool _IC2>
663 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __equal_unaligned(
664 __bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) {
665 using _It = __bit_iterator<_Cp, _IC1>;
666 using difference_type = typename _It::difference_type;
667 using __storage_type = typename _It::__storage_type;
669 const int __bits_per_word = _It::__bits_per_word;
670 difference_type __n = __last1 - __first1;
673 if (__first1.__ctz_ != 0) {
674 unsigned __clz_f = __bits_per_word - __first1.__ctz_;
675 difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n);
677 __storage_type __m = (~__storage_type(0) << __first1.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
678 __storage_type __b = *__first1.__seg_ & __m;
679 unsigned __clz_r = __bits_per_word - __first2.__ctz_;
680 __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
681 __m = (~__storage_type(0) << __first2.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn));
682 if (__first2.__ctz_ > __first1.__ctz_) {
683 if ((*__first2.__seg_ & __m) != (__b << (__first2.__ctz_ - __first1.__ctz_)))
686 if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ - __first2.__ctz_)))
689 __first2.__seg_ += (__ddn + __first2.__ctz_) / __bits_per_word;
690 __first2.__ctz_ = static_cast<unsigned>((__ddn + __first2.__ctz_) % __bits_per_word);
693 __m = ~__storage_type(0) >> (__bits_per_word - __dn);
694 if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ + __ddn)))
696 __first2.__ctz_ = static_cast<unsigned>(__dn);
699 // __first1.__ctz_ = 0;
701 // __first1.__ctz_ == 0;
703 unsigned __clz_r = __bits_per_word - __first2.__ctz_;
704 __storage_type __m = ~__storage_type(0) << __first2.__ctz_;
705 for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_) {
706 __storage_type __b = *__first1.__seg_;
707 if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_))
710 if ((*__first2.__seg_ & ~__m) != (__b >> __clz_r))
715 __m = ~__storage_type(0) >> (__bits_per_word - __n);
716 __storage_type __b = *__first1.__seg_ & __m;
717 __storage_type __dn = std::min(__n, static_cast<difference_type>(__clz_r));
718 __m = (~__storage_type(0) << __first2.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn));
719 if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_))
721 __first2.__seg_ += (__dn + __first2.__ctz_) / __bits_per_word;
722 __first2.__ctz_ = static_cast<unsigned>((__dn + __first2.__ctz_) % __bits_per_word);
725 __m = ~__storage_type(0) >> (__bits_per_word - __n);
726 if ((*__first2.__seg_ & __m) != (__b >> __dn))
734 template <class _Cp, bool _IC1, bool _IC2>
735 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __equal_aligned(
736 __bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) {
737 using _It = __bit_iterator<_Cp, _IC1>;
738 using difference_type = typename _It::difference_type;
739 using __storage_type = typename _It::__storage_type;
741 const int __bits_per_word = _It::__bits_per_word;
742 difference_type __n = __last1 - __first1;
745 if (__first1.__ctz_ != 0) {
746 unsigned __clz = __bits_per_word - __first1.__ctz_;
747 difference_type __dn = std::min(static_cast<difference_type>(__clz), __n);
749 __storage_type __m = (~__storage_type(0) << __first1.__ctz_) & (~__storage_type(0) >> (__clz - __dn));
750 if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m))
754 // __first1.__ctz_ = 0;
755 // __first2.__ctz_ = 0;
757 // __first1.__ctz_ == 0;
758 // __first2.__ctz_ == 0;
760 for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_, ++__first2.__seg_)
761 if (*__first2.__seg_ != *__first1.__seg_)
765 __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
766 if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m))
773 template <class _Cp, bool _IC1, bool _IC2>
774 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
775 equal(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) {
776 if (__first1.__ctz_ == __first2.__ctz_)
777 return std::__equal_aligned(__first1, __last1, __first2);
778 return std::__equal_unaligned(__first1, __last1, __first2);
781 template <class _Cp, bool _IsConst, typename _Cp::__storage_type>
782 class __bit_iterator {
784 using difference_type = typename _Cp::difference_type;
785 using value_type = bool;
786 using pointer = __bit_iterator;
787 #ifndef _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL
788 using reference = __conditional_t<_IsConst, __bit_const_reference<_Cp>, __bit_reference<_Cp> >;
790 using reference = __conditional_t<_IsConst, bool, __bit_reference<_Cp> >;
792 using iterator_category = random_access_iterator_tag;
795 using __storage_type = typename _Cp::__storage_type;
796 using __storage_pointer =
797 __conditional_t<_IsConst, typename _Cp::__const_storage_pointer, typename _Cp::__storage_pointer>;
799 static const unsigned __bits_per_word = _Cp::__bits_per_word;
801 __storage_pointer __seg_;
805 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator() _NOEXCEPT
806 #if _LIBCPP_STD_VER >= 14
813 // When _IsConst=false, this is the copy constructor.
814 // It is non-trivial. Making it trivial would break ABI.
815 // When _IsConst=true, this is a converting constructor;
816 // the copy and move constructors are implicitly generated
818 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator(const __bit_iterator<_Cp, false>& __it) _NOEXCEPT
819 : __seg_(__it.__seg_),
820 __ctz_(__it.__ctz_) {}
822 // When _IsConst=false, we have a user-provided copy constructor,
823 // so we must also provide a copy assignment operator because
824 // the implicit generation of a defaulted one is deprecated.
825 // When _IsConst=true, the assignment operators are
826 // implicitly generated and trivial.
827 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator&
828 operator=(const _If<_IsConst, struct __private_nat, __bit_iterator>& __it) {
829 __seg_ = __it.__seg_;
830 __ctz_ = __it.__ctz_;
834 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator*() const _NOEXCEPT {
835 return __conditional_t<_IsConst, __bit_const_reference<_Cp>, __bit_reference<_Cp> >(
836 __seg_, __storage_type(1) << __ctz_);
839 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator& operator++() {
840 if (__ctz_ != __bits_per_word - 1)
849 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator operator++(int) {
850 __bit_iterator __tmp = *this;
855 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator& operator--() {
859 __ctz_ = __bits_per_word - 1;
865 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator operator--(int) {
866 __bit_iterator __tmp = *this;
871 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator& operator+=(difference_type __n) {
873 __seg_ += (__n + __ctz_) / __bits_per_word;
875 __seg_ += static_cast<difference_type>(__n - __bits_per_word + __ctz_ + 1) /
876 static_cast<difference_type>(__bits_per_word);
877 __n &= (__bits_per_word - 1);
878 __ctz_ = static_cast<unsigned>((__n + __ctz_) % __bits_per_word);
882 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator& operator-=(difference_type __n) {
883 return *this += -__n;
886 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator operator+(difference_type __n) const {
887 __bit_iterator __t(*this);
892 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator operator-(difference_type __n) const {
893 __bit_iterator __t(*this);
898 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator
899 operator+(difference_type __n, const __bit_iterator& __it) {
903 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend difference_type
904 operator-(const __bit_iterator& __x, const __bit_iterator& __y) {
905 return (__x.__seg_ - __y.__seg_) * __bits_per_word + __x.__ctz_ - __y.__ctz_;
908 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator[](difference_type __n) const {
909 return *(*this + __n);
912 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
913 operator==(const __bit_iterator& __x, const __bit_iterator& __y) {
914 return __x.__seg_ == __y.__seg_ && __x.__ctz_ == __y.__ctz_;
917 #if _LIBCPP_STD_VER <= 17
918 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
919 operator!=(const __bit_iterator& __x, const __bit_iterator& __y) {
920 return !(__x == __y);
923 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
924 operator<(const __bit_iterator& __x, const __bit_iterator& __y) {
925 return __x.__seg_ < __y.__seg_ || (__x.__seg_ == __y.__seg_ && __x.__ctz_ < __y.__ctz_);
928 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
929 operator>(const __bit_iterator& __x, const __bit_iterator& __y) {
933 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
934 operator<=(const __bit_iterator& __x, const __bit_iterator& __y) {
938 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
939 operator>=(const __bit_iterator& __x, const __bit_iterator& __y) {
942 #else // _LIBCPP_STD_VER <= 17
943 _LIBCPP_HIDE_FROM_ABI constexpr friend strong_ordering
944 operator<=>(const __bit_iterator& __x, const __bit_iterator& __y) {
945 if (__x.__seg_ < __y.__seg_)
946 return strong_ordering::less;
948 if (__x.__seg_ == __y.__seg_)
949 return __x.__ctz_ <=> __y.__ctz_;
951 return strong_ordering::greater;
953 #endif // _LIBCPP_STD_VER <= 17
956 _LIBCPP_HIDE_FROM_ABI
957 _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bit_iterator(__storage_pointer __s, unsigned __ctz) _NOEXCEPT
961 friend typename _Cp::__self;
963 friend class __bit_reference<_Cp>;
964 friend class __bit_const_reference<_Cp>;
965 friend class __bit_iterator<_Cp, true>;
967 friend struct __bit_array;
969 template <bool _FillVal, class _Dp>
970 _LIBCPP_CONSTEXPR_SINCE_CXX20 friend void
971 __fill_n_bool(__bit_iterator<_Dp, false> __first, typename _Dp::size_type __n);
973 template <class _Dp, bool _IC>
974 _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_aligned(
975 __bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
976 template <class _Dp, bool _IC>
977 _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_unaligned(
978 __bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
979 template <class _Dp, bool _IC>
980 _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false>
981 copy(__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
982 template <class _Dp, bool _IC>
983 _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_backward_aligned(
984 __bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
985 template <class _Dp, bool _IC>
986 _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_backward_unaligned(
987 __bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
988 template <class _Dp, bool _IC>
989 _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false>
990 copy_backward(__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
991 template <class _Cl, class _Cr>
992 friend __bit_iterator<_Cr, false>
993 __swap_ranges_aligned(__bit_iterator<_Cl, false>, __bit_iterator<_Cl, false>, __bit_iterator<_Cr, false>);
994 template <class _Cl, class _Cr>
995 friend __bit_iterator<_Cr, false>
996 __swap_ranges_unaligned(__bit_iterator<_Cl, false>, __bit_iterator<_Cl, false>, __bit_iterator<_Cr, false>);
997 template <class _Cl, class _Cr>
998 friend __bit_iterator<_Cr, false>
999 swap_ranges(__bit_iterator<_Cl, false>, __bit_iterator<_Cl, false>, __bit_iterator<_Cr, false>);
1000 template <class _Dp>
1001 _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false>
1002 rotate(__bit_iterator<_Dp, false>, __bit_iterator<_Dp, false>, __bit_iterator<_Dp, false>);
1003 template <class _Dp, bool _IC1, bool _IC2>
1004 _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
1005 __equal_aligned(__bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC2>);
1006 template <class _Dp, bool _IC1, bool _IC2>
1007 _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
1008 __equal_unaligned(__bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC2>);
1009 template <class _Dp, bool _IC1, bool _IC2>
1010 _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
1011 equal(__bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC2>);
1012 template <bool _ToFind, class _Dp, bool _IC>
1013 _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, _IC>
1014 __find_bool(__bit_iterator<_Dp, _IC>, typename _Dp::size_type);
1015 template <bool _ToCount, class _Dp, bool _IC>
1016 friend typename __bit_iterator<_Dp, _IC>::difference_type _LIBCPP_HIDE_FROM_ABI
1017 _LIBCPP_CONSTEXPR_SINCE_CXX20 __count_bool(__bit_iterator<_Dp, _IC>, typename _Dp::size_type);
1020 _LIBCPP_END_NAMESPACE_STD
1024 #endif // _LIBCPP___BIT_REFERENCE