10b57cec5SDimitry Andric// -*- C++ -*- 20b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 30b57cec5SDimitry Andric// 40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 70b57cec5SDimitry Andric// 80b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 90b57cec5SDimitry Andric 100b57cec5SDimitry Andric#ifndef _LIBCPP___BIT_REFERENCE 110b57cec5SDimitry Andric#define _LIBCPP___BIT_REFERENCE 120b57cec5SDimitry Andric 1361cfbce3SDimitry Andric#include <__algorithm/copy_n.h> 1461cfbce3SDimitry Andric#include <__algorithm/fill_n.h> 1581ad6265SDimitry Andric#include <__algorithm/min.h> 16bdd1243dSDimitry Andric#include <__bit/countr.h> 175f757f3fSDimitry Andric#include <__bit/invert_if.h> 18bdd1243dSDimitry Andric#include <__bit/popcount.h> 19*36b606aeSDimitry Andric#include <__compare/ordering.h> 2004eeddc0SDimitry Andric#include <__config> 215f757f3fSDimitry Andric#include <__fwd/bit_reference.h> 2281ad6265SDimitry Andric#include <__iterator/iterator_traits.h> 2361cfbce3SDimitry Andric#include <__memory/construct_at.h> 2481ad6265SDimitry Andric#include <__memory/pointer_traits.h> 2506c3fb27SDimitry Andric#include <__type_traits/conditional.h> 2606c3fb27SDimitry Andric#include <__utility/swap.h> 2781ad6265SDimitry Andric#include <cstring> 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 300b57cec5SDimitry Andric# pragma GCC system_header 310b57cec5SDimitry Andric#endif 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric_LIBCPP_PUSH_MACROS 340b57cec5SDimitry Andric#include <__undef_macros> 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 370b57cec5SDimitry Andric 385f757f3fSDimitry Andrictemplate <class _Cp> 395f757f3fSDimitry Andricclass __bit_const_reference; 400b57cec5SDimitry Andric 410b57cec5SDimitry Andrictemplate <class _Tp> 425f757f3fSDimitry Andricstruct __has_storage_type { 430b57cec5SDimitry Andric static const bool value = false; 440b57cec5SDimitry Andric}; 450b57cec5SDimitry Andric 460b57cec5SDimitry Andrictemplate <class _Cp, bool = __has_storage_type<_Cp>::value> 475f757f3fSDimitry Andricclass __bit_reference { 485f757f3fSDimitry Andric using __storage_type = typename _Cp::__storage_type; 495f757f3fSDimitry Andric using __storage_pointer = typename _Cp::__storage_pointer; 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric __storage_pointer __seg_; 520b57cec5SDimitry Andric __storage_type __mask_; 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric friend typename _Cp::__self; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric friend class __bit_const_reference<_Cp>; 570b57cec5SDimitry Andric friend class __bit_iterator<_Cp, false>; 585f757f3fSDimitry Andric 590b57cec5SDimitry Andricpublic: 60bdd1243dSDimitry Andric using __container = typename _Cp::__self; 61bdd1243dSDimitry Andric 625f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_reference(const __bit_reference&) = default; 63480093f4SDimitry Andric 645f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 operator bool() const _NOEXCEPT { 655f757f3fSDimitry Andric return static_cast<bool>(*__seg_ & __mask_); 665f757f3fSDimitry Andric } 675f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool operator~() const _NOEXCEPT { 685f757f3fSDimitry Andric return !static_cast<bool>(*this); 695f757f3fSDimitry Andric } 700b57cec5SDimitry Andric 715f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_reference& operator=(bool __x) _NOEXCEPT { 720b57cec5SDimitry Andric if (__x) 730b57cec5SDimitry Andric *__seg_ |= __mask_; 740b57cec5SDimitry Andric else 750b57cec5SDimitry Andric *__seg_ &= ~__mask_; 760b57cec5SDimitry Andric return *this; 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 7906c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 23 8061cfbce3SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const __bit_reference& operator=(bool __x) const noexcept { 8181ad6265SDimitry Andric if (__x) 8281ad6265SDimitry Andric *__seg_ |= __mask_; 8381ad6265SDimitry Andric else 8481ad6265SDimitry Andric *__seg_ &= ~__mask_; 8581ad6265SDimitry Andric return *this; 8681ad6265SDimitry Andric } 8781ad6265SDimitry Andric#endif 8881ad6265SDimitry Andric 895f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_reference& operator=(const __bit_reference& __x) _NOEXCEPT { 905f757f3fSDimitry Andric return operator=(static_cast<bool>(__x)); 915f757f3fSDimitry Andric } 920b57cec5SDimitry Andric 935f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void flip() _NOEXCEPT { *__seg_ ^= __mask_; } 945f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false> operator&() const _NOEXCEPT { 955f757f3fSDimitry Andric return __bit_iterator<_Cp, false>(__seg_, static_cast<unsigned>(std::__libcpp_ctz(__mask_))); 965f757f3fSDimitry Andric } 975f757f3fSDimitry Andric 980b57cec5SDimitry Andricprivate: 990fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI 1000fca6ea1SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bit_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT 1015f757f3fSDimitry Andric : __seg_(__s), 1025f757f3fSDimitry Andric __mask_(__m) {} 1030b57cec5SDimitry Andric}; 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andrictemplate <class _Cp> 1065f757f3fSDimitry Andricclass __bit_reference<_Cp, false> {}; 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andrictemplate <class _Cp> 1095f757f3fSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void 1105f757f3fSDimitry Andricswap(__bit_reference<_Cp> __x, __bit_reference<_Cp> __y) _NOEXCEPT { 1110b57cec5SDimitry Andric bool __t = __x; 1120b57cec5SDimitry Andric __x = __y; 1130b57cec5SDimitry Andric __y = __t; 1140b57cec5SDimitry Andric} 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andrictemplate <class _Cp, class _Dp> 1175f757f3fSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void 1185f757f3fSDimitry Andricswap(__bit_reference<_Cp> __x, __bit_reference<_Dp> __y) _NOEXCEPT { 1190b57cec5SDimitry Andric bool __t = __x; 1200b57cec5SDimitry Andric __x = __y; 1210b57cec5SDimitry Andric __y = __t; 1220b57cec5SDimitry Andric} 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andrictemplate <class _Cp> 1255f757f3fSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(__bit_reference<_Cp> __x, bool& __y) _NOEXCEPT { 1260b57cec5SDimitry Andric bool __t = __x; 1270b57cec5SDimitry Andric __x = __y; 1280b57cec5SDimitry Andric __y = __t; 1290b57cec5SDimitry Andric} 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andrictemplate <class _Cp> 1325f757f3fSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(bool& __x, __bit_reference<_Cp> __y) _NOEXCEPT { 1330b57cec5SDimitry Andric bool __t = __x; 1340b57cec5SDimitry Andric __x = __y; 1350b57cec5SDimitry Andric __y = __t; 1360b57cec5SDimitry Andric} 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andrictemplate <class _Cp> 1395f757f3fSDimitry Andricclass __bit_const_reference { 1405f757f3fSDimitry Andric using __storage_type = typename _Cp::__storage_type; 1415f757f3fSDimitry Andric using __storage_pointer = typename _Cp::__const_storage_pointer; 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric __storage_pointer __seg_; 1440b57cec5SDimitry Andric __storage_type __mask_; 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric friend typename _Cp::__self; 1470b57cec5SDimitry Andric friend class __bit_iterator<_Cp, true>; 1485f757f3fSDimitry Andric 1490b57cec5SDimitry Andricpublic: 15006c3fb27SDimitry Andric using __container = typename _Cp::__self; 15106c3fb27SDimitry Andric 1525f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI __bit_const_reference(const __bit_const_reference&) = default; 1530fca6ea1SDimitry Andric __bit_const_reference& operator=(const __bit_const_reference&) = delete; 154480093f4SDimitry Andric 1555f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_const_reference(const __bit_reference<_Cp>& __x) _NOEXCEPT 1565f757f3fSDimitry Andric : __seg_(__x.__seg_), 1575f757f3fSDimitry Andric __mask_(__x.__mask_) {} 1580b57cec5SDimitry Andric 1595f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR operator bool() const _NOEXCEPT { 1605f757f3fSDimitry Andric return static_cast<bool>(*__seg_ & __mask_); 1615f757f3fSDimitry Andric } 1620b57cec5SDimitry Andric 1635f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, true> operator&() const _NOEXCEPT { 1645f757f3fSDimitry Andric return __bit_iterator<_Cp, true>(__seg_, static_cast<unsigned>(std::__libcpp_ctz(__mask_))); 1655f757f3fSDimitry Andric } 1665f757f3fSDimitry Andric 1670b57cec5SDimitry Andricprivate: 1680fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI 1690fca6ea1SDimitry Andric _LIBCPP_CONSTEXPR explicit __bit_const_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT 1705f757f3fSDimitry Andric : __seg_(__s), 1715f757f3fSDimitry Andric __mask_(__m) {} 1720b57cec5SDimitry Andric}; 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric// copy 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andrictemplate <class _Cp, bool _IsConst> 1775f757f3fSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_aligned( 1785f757f3fSDimitry Andric __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { 1795f757f3fSDimitry Andric using _In = __bit_iterator<_Cp, _IsConst>; 1805f757f3fSDimitry Andric using difference_type = typename _In::difference_type; 1815f757f3fSDimitry Andric using __storage_type = typename _In::__storage_type; 1825f757f3fSDimitry Andric 1830b57cec5SDimitry Andric const int __bits_per_word = _In::__bits_per_word; 1840b57cec5SDimitry Andric difference_type __n = __last - __first; 1855f757f3fSDimitry Andric if (__n > 0) { 1860b57cec5SDimitry Andric // do first word 1875f757f3fSDimitry Andric if (__first.__ctz_ != 0) { 1880b57cec5SDimitry Andric unsigned __clz = __bits_per_word - __first.__ctz_; 1895f757f3fSDimitry Andric difference_type __dn = std::min(static_cast<difference_type>(__clz), __n); 1900b57cec5SDimitry Andric __n -= __dn; 1910b57cec5SDimitry Andric __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn)); 1920b57cec5SDimitry Andric __storage_type __b = *__first.__seg_ & __m; 1930b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 1940b57cec5SDimitry Andric *__result.__seg_ |= __b; 1950b57cec5SDimitry Andric __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; 1960b57cec5SDimitry Andric __result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word); 1970b57cec5SDimitry Andric ++__first.__seg_; 1980b57cec5SDimitry Andric // __first.__ctz_ = 0; 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric // __first.__ctz_ == 0; 2010b57cec5SDimitry Andric // do middle words 2020b57cec5SDimitry Andric __storage_type __nw = __n / __bits_per_word; 20361cfbce3SDimitry Andric std::copy_n(std::__to_address(__first.__seg_), __nw, std::__to_address(__result.__seg_)); 2040b57cec5SDimitry Andric __n -= __nw * __bits_per_word; 2050b57cec5SDimitry Andric __result.__seg_ += __nw; 2060b57cec5SDimitry Andric // do last word 2075f757f3fSDimitry Andric if (__n > 0) { 2080b57cec5SDimitry Andric __first.__seg_ += __nw; 2090b57cec5SDimitry Andric __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); 2100b57cec5SDimitry Andric __storage_type __b = *__first.__seg_ & __m; 2110b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 2120b57cec5SDimitry Andric *__result.__seg_ |= __b; 2130b57cec5SDimitry Andric __result.__ctz_ = static_cast<unsigned>(__n); 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric return __result; 2170b57cec5SDimitry Andric} 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andrictemplate <class _Cp, bool _IsConst> 2205f757f3fSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_unaligned( 2215f757f3fSDimitry Andric __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { 2225f757f3fSDimitry Andric using _In = __bit_iterator<_Cp, _IsConst>; 2235f757f3fSDimitry Andric using difference_type = typename _In::difference_type; 2245f757f3fSDimitry Andric using __storage_type = typename _In::__storage_type; 2255f757f3fSDimitry Andric 22661cfbce3SDimitry Andric const int __bits_per_word = _In::__bits_per_word; 2270b57cec5SDimitry Andric difference_type __n = __last - __first; 2285f757f3fSDimitry Andric if (__n > 0) { 2290b57cec5SDimitry Andric // do first word 2305f757f3fSDimitry Andric if (__first.__ctz_ != 0) { 2310b57cec5SDimitry Andric unsigned __clz_f = __bits_per_word - __first.__ctz_; 2325f757f3fSDimitry Andric difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n); 2330b57cec5SDimitry Andric __n -= __dn; 2340b57cec5SDimitry Andric __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); 2350b57cec5SDimitry Andric __storage_type __b = *__first.__seg_ & __m; 2360b57cec5SDimitry Andric unsigned __clz_r = __bits_per_word - __result.__ctz_; 2375f757f3fSDimitry Andric __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r); 2380b57cec5SDimitry Andric __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn)); 2390b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 2400b57cec5SDimitry Andric if (__result.__ctz_ > __first.__ctz_) 2410b57cec5SDimitry Andric *__result.__seg_ |= __b << (__result.__ctz_ - __first.__ctz_); 2420b57cec5SDimitry Andric else 2430b57cec5SDimitry Andric *__result.__seg_ |= __b >> (__first.__ctz_ - __result.__ctz_); 2440b57cec5SDimitry Andric __result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word; 2450b57cec5SDimitry Andric __result.__ctz_ = static_cast<unsigned>((__ddn + __result.__ctz_) % __bits_per_word); 2460b57cec5SDimitry Andric __dn -= __ddn; 2475f757f3fSDimitry Andric if (__dn > 0) { 2480b57cec5SDimitry Andric __m = ~__storage_type(0) >> (__bits_per_word - __dn); 2490b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 2500b57cec5SDimitry Andric *__result.__seg_ |= __b >> (__first.__ctz_ + __ddn); 2510b57cec5SDimitry Andric __result.__ctz_ = static_cast<unsigned>(__dn); 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric ++__first.__seg_; 2540b57cec5SDimitry Andric // __first.__ctz_ = 0; 2550b57cec5SDimitry Andric } 2560b57cec5SDimitry Andric // __first.__ctz_ == 0; 2570b57cec5SDimitry Andric // do middle words 2580b57cec5SDimitry Andric unsigned __clz_r = __bits_per_word - __result.__ctz_; 2590b57cec5SDimitry Andric __storage_type __m = ~__storage_type(0) << __result.__ctz_; 2605f757f3fSDimitry Andric for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) { 2610b57cec5SDimitry Andric __storage_type __b = *__first.__seg_; 2620b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 2630b57cec5SDimitry Andric *__result.__seg_ |= __b << __result.__ctz_; 2640b57cec5SDimitry Andric ++__result.__seg_; 2650b57cec5SDimitry Andric *__result.__seg_ &= __m; 2660b57cec5SDimitry Andric *__result.__seg_ |= __b >> __clz_r; 2670b57cec5SDimitry Andric } 2680b57cec5SDimitry Andric // do last word 2695f757f3fSDimitry Andric if (__n > 0) { 2700b57cec5SDimitry Andric __m = ~__storage_type(0) >> (__bits_per_word - __n); 2710b57cec5SDimitry Andric __storage_type __b = *__first.__seg_ & __m; 2725f757f3fSDimitry Andric __storage_type __dn = std::min(__n, static_cast<difference_type>(__clz_r)); 2730b57cec5SDimitry Andric __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn)); 2740b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 2750b57cec5SDimitry Andric *__result.__seg_ |= __b << __result.__ctz_; 2760b57cec5SDimitry Andric __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; 2770b57cec5SDimitry Andric __result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word); 2780b57cec5SDimitry Andric __n -= __dn; 2795f757f3fSDimitry Andric if (__n > 0) { 2800b57cec5SDimitry Andric __m = ~__storage_type(0) >> (__bits_per_word - __n); 2810b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 2820b57cec5SDimitry Andric *__result.__seg_ |= __b >> __dn; 2830b57cec5SDimitry Andric __result.__ctz_ = static_cast<unsigned>(__n); 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric } 2870b57cec5SDimitry Andric return __result; 2880b57cec5SDimitry Andric} 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andrictemplate <class _Cp, bool _IsConst> 2915f757f3fSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false> 2925f757f3fSDimitry Andriccopy(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { 2930b57cec5SDimitry Andric if (__first.__ctz_ == __result.__ctz_) 2945f757f3fSDimitry Andric return std::__copy_aligned(__first, __last, __result); 2955f757f3fSDimitry Andric return std::__copy_unaligned(__first, __last, __result); 2960b57cec5SDimitry Andric} 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric// copy_backward 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andrictemplate <class _Cp, bool _IsConst> 3015f757f3fSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_backward_aligned( 3025f757f3fSDimitry Andric __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { 3035f757f3fSDimitry Andric using _In = __bit_iterator<_Cp, _IsConst>; 3045f757f3fSDimitry Andric using difference_type = typename _In::difference_type; 3055f757f3fSDimitry Andric using __storage_type = typename _In::__storage_type; 3065f757f3fSDimitry Andric 3070b57cec5SDimitry Andric const int __bits_per_word = _In::__bits_per_word; 3080b57cec5SDimitry Andric difference_type __n = __last - __first; 3095f757f3fSDimitry Andric if (__n > 0) { 3100b57cec5SDimitry Andric // do first word 3115f757f3fSDimitry Andric if (__last.__ctz_ != 0) { 3125f757f3fSDimitry Andric difference_type __dn = std::min(static_cast<difference_type>(__last.__ctz_), __n); 3130b57cec5SDimitry Andric __n -= __dn; 3140b57cec5SDimitry Andric unsigned __clz = __bits_per_word - __last.__ctz_; 3150b57cec5SDimitry Andric __storage_type __m = (~__storage_type(0) << (__last.__ctz_ - __dn)) & (~__storage_type(0) >> __clz); 3160b57cec5SDimitry Andric __storage_type __b = *__last.__seg_ & __m; 3170b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 3180b57cec5SDimitry Andric *__result.__seg_ |= __b; 3195f757f3fSDimitry Andric __result.__ctz_ = static_cast<unsigned>(((-__dn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word); 3200b57cec5SDimitry Andric // __last.__ctz_ = 0 3210b57cec5SDimitry Andric } 3220b57cec5SDimitry Andric // __last.__ctz_ == 0 || __n == 0 3230b57cec5SDimitry Andric // __result.__ctz_ == 0 || __n == 0 3240b57cec5SDimitry Andric // do middle words 3250b57cec5SDimitry Andric __storage_type __nw = __n / __bits_per_word; 3260b57cec5SDimitry Andric __result.__seg_ -= __nw; 3270b57cec5SDimitry Andric __last.__seg_ -= __nw; 32861cfbce3SDimitry Andric std::copy_n(std::__to_address(__last.__seg_), __nw, std::__to_address(__result.__seg_)); 3290b57cec5SDimitry Andric __n -= __nw * __bits_per_word; 3300b57cec5SDimitry Andric // do last word 3315f757f3fSDimitry Andric if (__n > 0) { 3320b57cec5SDimitry Andric __storage_type __m = ~__storage_type(0) << (__bits_per_word - __n); 3330b57cec5SDimitry Andric __storage_type __b = *--__last.__seg_ & __m; 3340b57cec5SDimitry Andric *--__result.__seg_ &= ~__m; 3350b57cec5SDimitry Andric *__result.__seg_ |= __b; 3360b57cec5SDimitry Andric __result.__ctz_ = static_cast<unsigned>(-__n & (__bits_per_word - 1)); 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric } 3390b57cec5SDimitry Andric return __result; 3400b57cec5SDimitry Andric} 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andrictemplate <class _Cp, bool _IsConst> 3435f757f3fSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_backward_unaligned( 3445f757f3fSDimitry Andric __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { 3455f757f3fSDimitry Andric using _In = __bit_iterator<_Cp, _IsConst>; 3465f757f3fSDimitry Andric using difference_type = typename _In::difference_type; 3475f757f3fSDimitry Andric using __storage_type = typename _In::__storage_type; 3485f757f3fSDimitry Andric 3490b57cec5SDimitry Andric const int __bits_per_word = _In::__bits_per_word; 3500b57cec5SDimitry Andric difference_type __n = __last - __first; 3515f757f3fSDimitry Andric if (__n > 0) { 3520b57cec5SDimitry Andric // do first word 3535f757f3fSDimitry Andric if (__last.__ctz_ != 0) { 3545f757f3fSDimitry Andric difference_type __dn = std::min(static_cast<difference_type>(__last.__ctz_), __n); 3550b57cec5SDimitry Andric __n -= __dn; 3560b57cec5SDimitry Andric unsigned __clz_l = __bits_per_word - __last.__ctz_; 3570b57cec5SDimitry Andric __storage_type __m = (~__storage_type(0) << (__last.__ctz_ - __dn)) & (~__storage_type(0) >> __clz_l); 3580b57cec5SDimitry Andric __storage_type __b = *__last.__seg_ & __m; 3590b57cec5SDimitry Andric unsigned __clz_r = __bits_per_word - __result.__ctz_; 3605f757f3fSDimitry Andric __storage_type __ddn = std::min(__dn, static_cast<difference_type>(__result.__ctz_)); 3615f757f3fSDimitry Andric if (__ddn > 0) { 3620b57cec5SDimitry Andric __m = (~__storage_type(0) << (__result.__ctz_ - __ddn)) & (~__storage_type(0) >> __clz_r); 3630b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 3640b57cec5SDimitry Andric if (__result.__ctz_ > __last.__ctz_) 3650b57cec5SDimitry Andric *__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_); 3660b57cec5SDimitry Andric else 3670b57cec5SDimitry Andric *__result.__seg_ |= __b >> (__last.__ctz_ - __result.__ctz_); 3685f757f3fSDimitry Andric __result.__ctz_ = static_cast<unsigned>(((-__ddn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word); 3690b57cec5SDimitry Andric __dn -= __ddn; 3700b57cec5SDimitry Andric } 3715f757f3fSDimitry Andric if (__dn > 0) { 3720b57cec5SDimitry Andric // __result.__ctz_ == 0 3730b57cec5SDimitry Andric --__result.__seg_; 3740b57cec5SDimitry Andric __result.__ctz_ = static_cast<unsigned>(-__dn & (__bits_per_word - 1)); 3750b57cec5SDimitry Andric __m = ~__storage_type(0) << __result.__ctz_; 3760b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 3770b57cec5SDimitry Andric __last.__ctz_ -= __dn + __ddn; 3780b57cec5SDimitry Andric *__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_); 3790b57cec5SDimitry Andric } 3800b57cec5SDimitry Andric // __last.__ctz_ = 0 3810b57cec5SDimitry Andric } 3820b57cec5SDimitry Andric // __last.__ctz_ == 0 || __n == 0 3830b57cec5SDimitry Andric // __result.__ctz_ != 0 || __n == 0 3840b57cec5SDimitry Andric // do middle words 3850b57cec5SDimitry Andric unsigned __clz_r = __bits_per_word - __result.__ctz_; 3860b57cec5SDimitry Andric __storage_type __m = ~__storage_type(0) >> __clz_r; 3875f757f3fSDimitry Andric for (; __n >= __bits_per_word; __n -= __bits_per_word) { 3880b57cec5SDimitry Andric __storage_type __b = *--__last.__seg_; 3890b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 3900b57cec5SDimitry Andric *__result.__seg_ |= __b >> __clz_r; 3910b57cec5SDimitry Andric *--__result.__seg_ &= __m; 3920b57cec5SDimitry Andric *__result.__seg_ |= __b << __result.__ctz_; 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric // do last word 3955f757f3fSDimitry Andric if (__n > 0) { 3960b57cec5SDimitry Andric __m = ~__storage_type(0) << (__bits_per_word - __n); 3970b57cec5SDimitry Andric __storage_type __b = *--__last.__seg_ & __m; 3980b57cec5SDimitry Andric __clz_r = __bits_per_word - __result.__ctz_; 3995f757f3fSDimitry Andric __storage_type __dn = std::min(__n, static_cast<difference_type>(__result.__ctz_)); 4000b57cec5SDimitry Andric __m = (~__storage_type(0) << (__result.__ctz_ - __dn)) & (~__storage_type(0) >> __clz_r); 4010b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 4020b57cec5SDimitry Andric *__result.__seg_ |= __b >> (__bits_per_word - __result.__ctz_); 4035f757f3fSDimitry Andric __result.__ctz_ = static_cast<unsigned>(((-__dn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word); 4040b57cec5SDimitry Andric __n -= __dn; 4055f757f3fSDimitry Andric if (__n > 0) { 4060b57cec5SDimitry Andric // __result.__ctz_ == 0 4070b57cec5SDimitry Andric --__result.__seg_; 4080b57cec5SDimitry Andric __result.__ctz_ = static_cast<unsigned>(-__n & (__bits_per_word - 1)); 4090b57cec5SDimitry Andric __m = ~__storage_type(0) << __result.__ctz_; 4100b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 4110b57cec5SDimitry Andric *__result.__seg_ |= __b << (__result.__ctz_ - (__bits_per_word - __n - __dn)); 4120b57cec5SDimitry Andric } 4130b57cec5SDimitry Andric } 4140b57cec5SDimitry Andric } 4150b57cec5SDimitry Andric return __result; 4160b57cec5SDimitry Andric} 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andrictemplate <class _Cp, bool _IsConst> 4195f757f3fSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false> copy_backward( 4205f757f3fSDimitry Andric __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { 4210b57cec5SDimitry Andric if (__last.__ctz_ == __result.__ctz_) 4225f757f3fSDimitry Andric return std::__copy_backward_aligned(__first, __last, __result); 4235f757f3fSDimitry Andric return std::__copy_backward_unaligned(__first, __last, __result); 4240b57cec5SDimitry Andric} 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric// move 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andrictemplate <class _Cp, bool _IsConst> 4295f757f3fSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> 4305f757f3fSDimitry Andricmove(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { 4315f757f3fSDimitry Andric return std::copy(__first, __last, __result); 4320b57cec5SDimitry Andric} 4330b57cec5SDimitry Andric 4340b57cec5SDimitry Andric// move_backward 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andrictemplate <class _Cp, bool _IsConst> 4375f757f3fSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> move_backward( 4385f757f3fSDimitry Andric __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { 4395f757f3fSDimitry Andric return std::copy_backward(__first, __last, __result); 4400b57cec5SDimitry Andric} 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric// swap_ranges 4430b57cec5SDimitry Andric 44406c3fb27SDimitry Andrictemplate <class _Cl, class _Cr> 4455f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cr, false> __swap_ranges_aligned( 4465f757f3fSDimitry Andric __bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, __bit_iterator<_Cr, false> __result) { 4475f757f3fSDimitry Andric using _I1 = __bit_iterator<_Cl, false>; 4485f757f3fSDimitry Andric using difference_type = typename _I1::difference_type; 4495f757f3fSDimitry Andric using __storage_type = typename _I1::__storage_type; 4505f757f3fSDimitry Andric 4510b57cec5SDimitry Andric const int __bits_per_word = _I1::__bits_per_word; 4520b57cec5SDimitry Andric difference_type __n = __last - __first; 4535f757f3fSDimitry Andric if (__n > 0) { 4540b57cec5SDimitry Andric // do first word 4555f757f3fSDimitry Andric if (__first.__ctz_ != 0) { 4560b57cec5SDimitry Andric unsigned __clz = __bits_per_word - __first.__ctz_; 4575f757f3fSDimitry Andric difference_type __dn = std::min(static_cast<difference_type>(__clz), __n); 4580b57cec5SDimitry Andric __n -= __dn; 4590b57cec5SDimitry Andric __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn)); 4600b57cec5SDimitry Andric __storage_type __b1 = *__first.__seg_ & __m; 4610b57cec5SDimitry Andric *__first.__seg_ &= ~__m; 4620b57cec5SDimitry Andric __storage_type __b2 = *__result.__seg_ & __m; 4630b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 4640b57cec5SDimitry Andric *__result.__seg_ |= __b1; 4650b57cec5SDimitry Andric *__first.__seg_ |= __b2; 4660b57cec5SDimitry Andric __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; 4670b57cec5SDimitry Andric __result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word); 4680b57cec5SDimitry Andric ++__first.__seg_; 4690b57cec5SDimitry Andric // __first.__ctz_ = 0; 4700b57cec5SDimitry Andric } 4710b57cec5SDimitry Andric // __first.__ctz_ == 0; 4720b57cec5SDimitry Andric // do middle words 4730b57cec5SDimitry Andric for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_, ++__result.__seg_) 4740b57cec5SDimitry Andric swap(*__first.__seg_, *__result.__seg_); 4750b57cec5SDimitry Andric // do last word 4765f757f3fSDimitry Andric if (__n > 0) { 4770b57cec5SDimitry Andric __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); 4780b57cec5SDimitry Andric __storage_type __b1 = *__first.__seg_ & __m; 4790b57cec5SDimitry Andric *__first.__seg_ &= ~__m; 4800b57cec5SDimitry Andric __storage_type __b2 = *__result.__seg_ & __m; 4810b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 4820b57cec5SDimitry Andric *__result.__seg_ |= __b1; 4830b57cec5SDimitry Andric *__first.__seg_ |= __b2; 4840b57cec5SDimitry Andric __result.__ctz_ = static_cast<unsigned>(__n); 4850b57cec5SDimitry Andric } 4860b57cec5SDimitry Andric } 4870b57cec5SDimitry Andric return __result; 4880b57cec5SDimitry Andric} 4890b57cec5SDimitry Andric 49006c3fb27SDimitry Andrictemplate <class _Cl, class _Cr> 4915f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cr, false> __swap_ranges_unaligned( 4925f757f3fSDimitry Andric __bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, __bit_iterator<_Cr, false> __result) { 4935f757f3fSDimitry Andric using _I1 = __bit_iterator<_Cl, false>; 4945f757f3fSDimitry Andric using difference_type = typename _I1::difference_type; 4955f757f3fSDimitry Andric using __storage_type = typename _I1::__storage_type; 4965f757f3fSDimitry Andric 4970b57cec5SDimitry Andric const int __bits_per_word = _I1::__bits_per_word; 4980b57cec5SDimitry Andric difference_type __n = __last - __first; 4995f757f3fSDimitry Andric if (__n > 0) { 5000b57cec5SDimitry Andric // do first word 5015f757f3fSDimitry Andric if (__first.__ctz_ != 0) { 5020b57cec5SDimitry Andric unsigned __clz_f = __bits_per_word - __first.__ctz_; 5035f757f3fSDimitry Andric difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n); 5040b57cec5SDimitry Andric __n -= __dn; 5050b57cec5SDimitry Andric __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); 5060b57cec5SDimitry Andric __storage_type __b1 = *__first.__seg_ & __m; 5070b57cec5SDimitry Andric *__first.__seg_ &= ~__m; 5080b57cec5SDimitry Andric unsigned __clz_r = __bits_per_word - __result.__ctz_; 5095f757f3fSDimitry Andric __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r); 5100b57cec5SDimitry Andric __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn)); 5110b57cec5SDimitry Andric __storage_type __b2 = *__result.__seg_ & __m; 5120b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 5135f757f3fSDimitry Andric if (__result.__ctz_ > __first.__ctz_) { 5140b57cec5SDimitry Andric unsigned __s = __result.__ctz_ - __first.__ctz_; 5150b57cec5SDimitry Andric *__result.__seg_ |= __b1 << __s; 5160b57cec5SDimitry Andric *__first.__seg_ |= __b2 >> __s; 5175f757f3fSDimitry Andric } else { 5180b57cec5SDimitry Andric unsigned __s = __first.__ctz_ - __result.__ctz_; 5190b57cec5SDimitry Andric *__result.__seg_ |= __b1 >> __s; 5200b57cec5SDimitry Andric *__first.__seg_ |= __b2 << __s; 5210b57cec5SDimitry Andric } 5220b57cec5SDimitry Andric __result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word; 5230b57cec5SDimitry Andric __result.__ctz_ = static_cast<unsigned>((__ddn + __result.__ctz_) % __bits_per_word); 5240b57cec5SDimitry Andric __dn -= __ddn; 5255f757f3fSDimitry Andric if (__dn > 0) { 5260b57cec5SDimitry Andric __m = ~__storage_type(0) >> (__bits_per_word - __dn); 5270b57cec5SDimitry Andric __b2 = *__result.__seg_ & __m; 5280b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 5290b57cec5SDimitry Andric unsigned __s = __first.__ctz_ + __ddn; 5300b57cec5SDimitry Andric *__result.__seg_ |= __b1 >> __s; 5310b57cec5SDimitry Andric *__first.__seg_ |= __b2 << __s; 5320b57cec5SDimitry Andric __result.__ctz_ = static_cast<unsigned>(__dn); 5330b57cec5SDimitry Andric } 5340b57cec5SDimitry Andric ++__first.__seg_; 5350b57cec5SDimitry Andric // __first.__ctz_ = 0; 5360b57cec5SDimitry Andric } 5370b57cec5SDimitry Andric // __first.__ctz_ == 0; 5380b57cec5SDimitry Andric // do middle words 5390b57cec5SDimitry Andric __storage_type __m = ~__storage_type(0) << __result.__ctz_; 5400b57cec5SDimitry Andric unsigned __clz_r = __bits_per_word - __result.__ctz_; 5415f757f3fSDimitry Andric for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) { 5420b57cec5SDimitry Andric __storage_type __b1 = *__first.__seg_; 5430b57cec5SDimitry Andric __storage_type __b2 = *__result.__seg_ & __m; 5440b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 5450b57cec5SDimitry Andric *__result.__seg_ |= __b1 << __result.__ctz_; 5460b57cec5SDimitry Andric *__first.__seg_ = __b2 >> __result.__ctz_; 5470b57cec5SDimitry Andric ++__result.__seg_; 5480b57cec5SDimitry Andric __b2 = *__result.__seg_ & ~__m; 5490b57cec5SDimitry Andric *__result.__seg_ &= __m; 5500b57cec5SDimitry Andric *__result.__seg_ |= __b1 >> __clz_r; 5510b57cec5SDimitry Andric *__first.__seg_ |= __b2 << __clz_r; 5520b57cec5SDimitry Andric } 5530b57cec5SDimitry Andric // do last word 5545f757f3fSDimitry Andric if (__n > 0) { 5550b57cec5SDimitry Andric __m = ~__storage_type(0) >> (__bits_per_word - __n); 5560b57cec5SDimitry Andric __storage_type __b1 = *__first.__seg_ & __m; 5570b57cec5SDimitry Andric *__first.__seg_ &= ~__m; 5585f757f3fSDimitry Andric __storage_type __dn = std::min<__storage_type>(__n, __clz_r); 5590b57cec5SDimitry Andric __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn)); 5600b57cec5SDimitry Andric __storage_type __b2 = *__result.__seg_ & __m; 5610b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 5620b57cec5SDimitry Andric *__result.__seg_ |= __b1 << __result.__ctz_; 5630b57cec5SDimitry Andric *__first.__seg_ |= __b2 >> __result.__ctz_; 5640b57cec5SDimitry Andric __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; 5650b57cec5SDimitry Andric __result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word); 5660b57cec5SDimitry Andric __n -= __dn; 5675f757f3fSDimitry Andric if (__n > 0) { 5680b57cec5SDimitry Andric __m = ~__storage_type(0) >> (__bits_per_word - __n); 5690b57cec5SDimitry Andric __b2 = *__result.__seg_ & __m; 5700b57cec5SDimitry Andric *__result.__seg_ &= ~__m; 5710b57cec5SDimitry Andric *__result.__seg_ |= __b1 >> __dn; 5720b57cec5SDimitry Andric *__first.__seg_ |= __b2 << __dn; 5730b57cec5SDimitry Andric __result.__ctz_ = static_cast<unsigned>(__n); 5740b57cec5SDimitry Andric } 5750b57cec5SDimitry Andric } 5760b57cec5SDimitry Andric } 5770b57cec5SDimitry Andric return __result; 5780b57cec5SDimitry Andric} 5790b57cec5SDimitry Andric 58006c3fb27SDimitry Andrictemplate <class _Cl, class _Cr> 5815f757f3fSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cr, false> swap_ranges( 5825f757f3fSDimitry Andric __bit_iterator<_Cl, false> __first1, __bit_iterator<_Cl, false> __last1, __bit_iterator<_Cr, false> __first2) { 5830b57cec5SDimitry Andric if (__first1.__ctz_ == __first2.__ctz_) 5845f757f3fSDimitry Andric return std::__swap_ranges_aligned(__first1, __last1, __first2); 5855f757f3fSDimitry Andric return std::__swap_ranges_unaligned(__first1, __last1, __first2); 5860b57cec5SDimitry Andric} 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric// rotate 5890b57cec5SDimitry Andric 5900b57cec5SDimitry Andrictemplate <class _Cp> 5915f757f3fSDimitry Andricstruct __bit_array { 5925f757f3fSDimitry Andric using difference_type = typename _Cp::difference_type; 5935f757f3fSDimitry Andric using __storage_type = typename _Cp::__storage_type; 5945f757f3fSDimitry Andric using __storage_pointer = typename _Cp::__storage_pointer; 5955f757f3fSDimitry Andric using iterator = typename _Cp::iterator; 5965f757f3fSDimitry Andric 5970b57cec5SDimitry Andric static const unsigned __bits_per_word = _Cp::__bits_per_word; 5980b57cec5SDimitry Andric static const unsigned _Np = 4; 5990b57cec5SDimitry Andric 6000b57cec5SDimitry Andric difference_type __size_; 6010b57cec5SDimitry Andric __storage_type __word_[_Np]; 6020b57cec5SDimitry Andric 6035f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static difference_type capacity() { 6045f757f3fSDimitry Andric return static_cast<difference_type>(_Np * __bits_per_word); 6055f757f3fSDimitry Andric } 6065f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bit_array(difference_type __s) : __size_(__s) { 60761cfbce3SDimitry Andric if (__libcpp_is_constant_evaluated()) { 60861cfbce3SDimitry Andric for (size_t __i = 0; __i != __bit_array<_Cp>::_Np; ++__i) 60961cfbce3SDimitry Andric std::__construct_at(__word_ + __i, 0); 61061cfbce3SDimitry Andric } 61161cfbce3SDimitry Andric } 6125f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator begin() { 6130b57cec5SDimitry Andric return iterator(pointer_traits<__storage_pointer>::pointer_to(__word_[0]), 0); 6140b57cec5SDimitry Andric } 6155f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator end() { 6160b57cec5SDimitry Andric return iterator(pointer_traits<__storage_pointer>::pointer_to(__word_[0]) + __size_ / __bits_per_word, 6170b57cec5SDimitry Andric static_cast<unsigned>(__size_ % __bits_per_word)); 6180b57cec5SDimitry Andric } 6190b57cec5SDimitry Andric}; 6200b57cec5SDimitry Andric 6210b57cec5SDimitry Andrictemplate <class _Cp> 622bdd1243dSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> 6235f757f3fSDimitry Andricrotate(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __middle, __bit_iterator<_Cp, false> __last) { 6245f757f3fSDimitry Andric using _I1 = __bit_iterator<_Cp, false>; 6255f757f3fSDimitry Andric using difference_type = typename _I1::difference_type; 6265f757f3fSDimitry Andric 6270b57cec5SDimitry Andric difference_type __d1 = __middle - __first; 6280b57cec5SDimitry Andric difference_type __d2 = __last - __middle; 6290b57cec5SDimitry Andric _I1 __r = __first + __d2; 6305f757f3fSDimitry Andric while (__d1 != 0 && __d2 != 0) { 6315f757f3fSDimitry Andric if (__d1 <= __d2) { 6325f757f3fSDimitry Andric if (__d1 <= __bit_array<_Cp>::capacity()) { 6330b57cec5SDimitry Andric __bit_array<_Cp> __b(__d1); 6345f757f3fSDimitry Andric std::copy(__first, __middle, __b.begin()); 6355f757f3fSDimitry Andric std::copy(__b.begin(), __b.end(), std::copy(__middle, __last, __first)); 6360b57cec5SDimitry Andric break; 6375f757f3fSDimitry Andric } else { 6385f757f3fSDimitry Andric __bit_iterator<_Cp, false> __mp = std::swap_ranges(__first, __middle, __middle); 6390b57cec5SDimitry Andric __first = __middle; 6400b57cec5SDimitry Andric __middle = __mp; 6410b57cec5SDimitry Andric __d2 -= __d1; 6420b57cec5SDimitry Andric } 6435f757f3fSDimitry Andric } else { 6445f757f3fSDimitry Andric if (__d2 <= __bit_array<_Cp>::capacity()) { 6450b57cec5SDimitry Andric __bit_array<_Cp> __b(__d2); 6465f757f3fSDimitry Andric std::copy(__middle, __last, __b.begin()); 6475f757f3fSDimitry Andric std::copy_backward(__b.begin(), __b.end(), std::copy_backward(__first, __middle, __last)); 6480b57cec5SDimitry Andric break; 6495f757f3fSDimitry Andric } else { 6500b57cec5SDimitry Andric __bit_iterator<_Cp, false> __mp = __first + __d2; 6515f757f3fSDimitry Andric std::swap_ranges(__first, __mp, __middle); 6520b57cec5SDimitry Andric __first = __mp; 6530b57cec5SDimitry Andric __d1 -= __d2; 6540b57cec5SDimitry Andric } 6550b57cec5SDimitry Andric } 6560b57cec5SDimitry Andric } 6570b57cec5SDimitry Andric return __r; 6580b57cec5SDimitry Andric} 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric// equal 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andrictemplate <class _Cp, bool _IC1, bool _IC2> 6635f757f3fSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __equal_unaligned( 6645f757f3fSDimitry Andric __bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) { 6655f757f3fSDimitry Andric using _It = __bit_iterator<_Cp, _IC1>; 6665f757f3fSDimitry Andric using difference_type = typename _It::difference_type; 6675f757f3fSDimitry Andric using __storage_type = typename _It::__storage_type; 6685f757f3fSDimitry Andric 66961cfbce3SDimitry Andric const int __bits_per_word = _It::__bits_per_word; 6700b57cec5SDimitry Andric difference_type __n = __last1 - __first1; 6715f757f3fSDimitry Andric if (__n > 0) { 6720b57cec5SDimitry Andric // do first word 6735f757f3fSDimitry Andric if (__first1.__ctz_ != 0) { 6740b57cec5SDimitry Andric unsigned __clz_f = __bits_per_word - __first1.__ctz_; 6755f757f3fSDimitry Andric difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n); 6760b57cec5SDimitry Andric __n -= __dn; 6770b57cec5SDimitry Andric __storage_type __m = (~__storage_type(0) << __first1.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); 6780b57cec5SDimitry Andric __storage_type __b = *__first1.__seg_ & __m; 6790b57cec5SDimitry Andric unsigned __clz_r = __bits_per_word - __first2.__ctz_; 6805f757f3fSDimitry Andric __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r); 6810b57cec5SDimitry Andric __m = (~__storage_type(0) << __first2.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn)); 6825f757f3fSDimitry Andric if (__first2.__ctz_ > __first1.__ctz_) { 6830b57cec5SDimitry Andric if ((*__first2.__seg_ & __m) != (__b << (__first2.__ctz_ - __first1.__ctz_))) 6840b57cec5SDimitry Andric return false; 6855f757f3fSDimitry Andric } else { 6860b57cec5SDimitry Andric if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ - __first2.__ctz_))) 6870b57cec5SDimitry Andric return false; 6880b57cec5SDimitry Andric } 6890b57cec5SDimitry Andric __first2.__seg_ += (__ddn + __first2.__ctz_) / __bits_per_word; 6900b57cec5SDimitry Andric __first2.__ctz_ = static_cast<unsigned>((__ddn + __first2.__ctz_) % __bits_per_word); 6910b57cec5SDimitry Andric __dn -= __ddn; 6925f757f3fSDimitry Andric if (__dn > 0) { 6930b57cec5SDimitry Andric __m = ~__storage_type(0) >> (__bits_per_word - __dn); 6940b57cec5SDimitry Andric if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ + __ddn))) 6950b57cec5SDimitry Andric return false; 6960b57cec5SDimitry Andric __first2.__ctz_ = static_cast<unsigned>(__dn); 6970b57cec5SDimitry Andric } 6980b57cec5SDimitry Andric ++__first1.__seg_; 6990b57cec5SDimitry Andric // __first1.__ctz_ = 0; 7000b57cec5SDimitry Andric } 7010b57cec5SDimitry Andric // __first1.__ctz_ == 0; 7020b57cec5SDimitry Andric // do middle words 7030b57cec5SDimitry Andric unsigned __clz_r = __bits_per_word - __first2.__ctz_; 7040b57cec5SDimitry Andric __storage_type __m = ~__storage_type(0) << __first2.__ctz_; 7055f757f3fSDimitry Andric for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_) { 7060b57cec5SDimitry Andric __storage_type __b = *__first1.__seg_; 7070b57cec5SDimitry Andric if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_)) 7080b57cec5SDimitry Andric return false; 7090b57cec5SDimitry Andric ++__first2.__seg_; 7100b57cec5SDimitry Andric if ((*__first2.__seg_ & ~__m) != (__b >> __clz_r)) 7110b57cec5SDimitry Andric return false; 7120b57cec5SDimitry Andric } 7130b57cec5SDimitry Andric // do last word 7145f757f3fSDimitry Andric if (__n > 0) { 7150b57cec5SDimitry Andric __m = ~__storage_type(0) >> (__bits_per_word - __n); 7160b57cec5SDimitry Andric __storage_type __b = *__first1.__seg_ & __m; 7175f757f3fSDimitry Andric __storage_type __dn = std::min(__n, static_cast<difference_type>(__clz_r)); 7180b57cec5SDimitry Andric __m = (~__storage_type(0) << __first2.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn)); 7190b57cec5SDimitry Andric if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_)) 7200b57cec5SDimitry Andric return false; 7210b57cec5SDimitry Andric __first2.__seg_ += (__dn + __first2.__ctz_) / __bits_per_word; 7220b57cec5SDimitry Andric __first2.__ctz_ = static_cast<unsigned>((__dn + __first2.__ctz_) % __bits_per_word); 7230b57cec5SDimitry Andric __n -= __dn; 7245f757f3fSDimitry Andric if (__n > 0) { 7250b57cec5SDimitry Andric __m = ~__storage_type(0) >> (__bits_per_word - __n); 7260b57cec5SDimitry Andric if ((*__first2.__seg_ & __m) != (__b >> __dn)) 7270b57cec5SDimitry Andric return false; 7280b57cec5SDimitry Andric } 7290b57cec5SDimitry Andric } 7300b57cec5SDimitry Andric } 7310b57cec5SDimitry Andric return true; 7320b57cec5SDimitry Andric} 7330b57cec5SDimitry Andric 7340b57cec5SDimitry Andrictemplate <class _Cp, bool _IC1, bool _IC2> 7355f757f3fSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __equal_aligned( 7365f757f3fSDimitry Andric __bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) { 7375f757f3fSDimitry Andric using _It = __bit_iterator<_Cp, _IC1>; 7385f757f3fSDimitry Andric using difference_type = typename _It::difference_type; 7395f757f3fSDimitry Andric using __storage_type = typename _It::__storage_type; 7405f757f3fSDimitry Andric 74161cfbce3SDimitry Andric const int __bits_per_word = _It::__bits_per_word; 7420b57cec5SDimitry Andric difference_type __n = __last1 - __first1; 7435f757f3fSDimitry Andric if (__n > 0) { 7440b57cec5SDimitry Andric // do first word 7455f757f3fSDimitry Andric if (__first1.__ctz_ != 0) { 7460b57cec5SDimitry Andric unsigned __clz = __bits_per_word - __first1.__ctz_; 7475f757f3fSDimitry Andric difference_type __dn = std::min(static_cast<difference_type>(__clz), __n); 7480b57cec5SDimitry Andric __n -= __dn; 7490b57cec5SDimitry Andric __storage_type __m = (~__storage_type(0) << __first1.__ctz_) & (~__storage_type(0) >> (__clz - __dn)); 7500b57cec5SDimitry Andric if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m)) 7510b57cec5SDimitry Andric return false; 7520b57cec5SDimitry Andric ++__first2.__seg_; 7530b57cec5SDimitry Andric ++__first1.__seg_; 7540b57cec5SDimitry Andric // __first1.__ctz_ = 0; 7550b57cec5SDimitry Andric // __first2.__ctz_ = 0; 7560b57cec5SDimitry Andric } 7570b57cec5SDimitry Andric // __first1.__ctz_ == 0; 7580b57cec5SDimitry Andric // __first2.__ctz_ == 0; 7590b57cec5SDimitry Andric // do middle words 7600b57cec5SDimitry Andric for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_, ++__first2.__seg_) 7610b57cec5SDimitry Andric if (*__first2.__seg_ != *__first1.__seg_) 7620b57cec5SDimitry Andric return false; 7630b57cec5SDimitry Andric // do last word 7645f757f3fSDimitry Andric if (__n > 0) { 7650b57cec5SDimitry Andric __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); 7660b57cec5SDimitry Andric if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m)) 7670b57cec5SDimitry Andric return false; 7680b57cec5SDimitry Andric } 7690b57cec5SDimitry Andric } 7700b57cec5SDimitry Andric return true; 7710b57cec5SDimitry Andric} 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andrictemplate <class _Cp, bool _IC1, bool _IC2> 7745f757f3fSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool 7755f757f3fSDimitry Andricequal(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) { 7760b57cec5SDimitry Andric if (__first1.__ctz_ == __first2.__ctz_) 7775f757f3fSDimitry Andric return std::__equal_aligned(__first1, __last1, __first2); 7785f757f3fSDimitry Andric return std::__equal_unaligned(__first1, __last1, __first2); 7790b57cec5SDimitry Andric} 7800b57cec5SDimitry Andric 7815f757f3fSDimitry Andrictemplate <class _Cp, bool _IsConst, typename _Cp::__storage_type> 7825f757f3fSDimitry Andricclass __bit_iterator { 7830b57cec5SDimitry Andricpublic: 7845f757f3fSDimitry Andric using difference_type = typename _Cp::difference_type; 7855f757f3fSDimitry Andric using value_type = bool; 7865f757f3fSDimitry Andric using pointer = __bit_iterator; 78781ad6265SDimitry Andric#ifndef _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL 7885f757f3fSDimitry Andric using reference = __conditional_t<_IsConst, __bit_const_reference<_Cp>, __bit_reference<_Cp> >; 78981ad6265SDimitry Andric#else 790bdd1243dSDimitry Andric using reference = __conditional_t<_IsConst, bool, __bit_reference<_Cp> >; 79181ad6265SDimitry Andric#endif 7925f757f3fSDimitry Andric using iterator_category = random_access_iterator_tag; 7930b57cec5SDimitry Andric 7940b57cec5SDimitry Andricprivate: 7955f757f3fSDimitry Andric using __storage_type = typename _Cp::__storage_type; 7965f757f3fSDimitry Andric using __storage_pointer = 7975f757f3fSDimitry Andric __conditional_t<_IsConst, typename _Cp::__const_storage_pointer, typename _Cp::__storage_pointer>; 7985f757f3fSDimitry Andric 7990b57cec5SDimitry Andric static const unsigned __bits_per_word = _Cp::__bits_per_word; 8000b57cec5SDimitry Andric 8010b57cec5SDimitry Andric __storage_pointer __seg_; 8020b57cec5SDimitry Andric unsigned __ctz_; 8030b57cec5SDimitry Andric 8040b57cec5SDimitry Andricpublic: 8055f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator() _NOEXCEPT 80606c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 14 8075f757f3fSDimitry Andric : __seg_(nullptr), 8085f757f3fSDimitry Andric __ctz_(0) 8090b57cec5SDimitry Andric#endif 8105f757f3fSDimitry Andric { 8115f757f3fSDimitry Andric } 8120b57cec5SDimitry Andric 8134652422eSDimitry Andric // When _IsConst=false, this is the copy constructor. 8144652422eSDimitry Andric // It is non-trivial. Making it trivial would break ABI. 8154652422eSDimitry Andric // When _IsConst=true, this is a converting constructor; 8164652422eSDimitry Andric // the copy and move constructors are implicitly generated 8174652422eSDimitry Andric // and trivial. 8185f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator(const __bit_iterator<_Cp, false>& __it) _NOEXCEPT 8195f757f3fSDimitry Andric : __seg_(__it.__seg_), 8205f757f3fSDimitry Andric __ctz_(__it.__ctz_) {} 8210b57cec5SDimitry Andric 8224652422eSDimitry Andric // When _IsConst=false, we have a user-provided copy constructor, 8234652422eSDimitry Andric // so we must also provide a copy assignment operator because 8244652422eSDimitry Andric // the implicit generation of a defaulted one is deprecated. 8254652422eSDimitry Andric // When _IsConst=true, the assignment operators are 8264652422eSDimitry Andric // implicitly generated and trivial. 8275f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator& 8285f757f3fSDimitry Andric operator=(const _If<_IsConst, struct __private_nat, __bit_iterator>& __it) { 8294652422eSDimitry Andric __seg_ = __it.__seg_; 8304652422eSDimitry Andric __ctz_ = __it.__ctz_; 8314652422eSDimitry Andric return *this; 8324652422eSDimitry Andric } 83347395794SDimitry Andric 8345f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator*() const _NOEXCEPT { 835bdd1243dSDimitry Andric return __conditional_t<_IsConst, __bit_const_reference<_Cp>, __bit_reference<_Cp> >( 836bdd1243dSDimitry Andric __seg_, __storage_type(1) << __ctz_); 83781ad6265SDimitry Andric } 8380b57cec5SDimitry Andric 8395f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator& operator++() { 8400b57cec5SDimitry Andric if (__ctz_ != __bits_per_word - 1) 8410b57cec5SDimitry Andric ++__ctz_; 8425f757f3fSDimitry Andric else { 8430b57cec5SDimitry Andric __ctz_ = 0; 8440b57cec5SDimitry Andric ++__seg_; 8450b57cec5SDimitry Andric } 8460b57cec5SDimitry Andric return *this; 8470b57cec5SDimitry Andric } 8480b57cec5SDimitry Andric 8495f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator operator++(int) { 8500b57cec5SDimitry Andric __bit_iterator __tmp = *this; 8510b57cec5SDimitry Andric ++(*this); 8520b57cec5SDimitry Andric return __tmp; 8530b57cec5SDimitry Andric } 8540b57cec5SDimitry Andric 8555f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator& operator--() { 8560b57cec5SDimitry Andric if (__ctz_ != 0) 8570b57cec5SDimitry Andric --__ctz_; 8585f757f3fSDimitry Andric else { 8590b57cec5SDimitry Andric __ctz_ = __bits_per_word - 1; 8600b57cec5SDimitry Andric --__seg_; 8610b57cec5SDimitry Andric } 8620b57cec5SDimitry Andric return *this; 8630b57cec5SDimitry Andric } 8640b57cec5SDimitry Andric 8655f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator operator--(int) { 8660b57cec5SDimitry Andric __bit_iterator __tmp = *this; 8670b57cec5SDimitry Andric --(*this); 8680b57cec5SDimitry Andric return __tmp; 8690b57cec5SDimitry Andric } 8700b57cec5SDimitry Andric 8715f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator& operator+=(difference_type __n) { 8720b57cec5SDimitry Andric if (__n >= 0) 8730b57cec5SDimitry Andric __seg_ += (__n + __ctz_) / __bits_per_word; 8740b57cec5SDimitry Andric else 8755f757f3fSDimitry Andric __seg_ += static_cast<difference_type>(__n - __bits_per_word + __ctz_ + 1) / 8765f757f3fSDimitry Andric static_cast<difference_type>(__bits_per_word); 8770b57cec5SDimitry Andric __n &= (__bits_per_word - 1); 8780b57cec5SDimitry Andric __ctz_ = static_cast<unsigned>((__n + __ctz_) % __bits_per_word); 8790b57cec5SDimitry Andric return *this; 8800b57cec5SDimitry Andric } 8810b57cec5SDimitry Andric 8825f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator& operator-=(difference_type __n) { 8830b57cec5SDimitry Andric return *this += -__n; 8840b57cec5SDimitry Andric } 8850b57cec5SDimitry Andric 8865f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator operator+(difference_type __n) const { 8870b57cec5SDimitry Andric __bit_iterator __t(*this); 8880b57cec5SDimitry Andric __t += __n; 8890b57cec5SDimitry Andric return __t; 8900b57cec5SDimitry Andric } 8910b57cec5SDimitry Andric 8925f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator operator-(difference_type __n) const { 8930b57cec5SDimitry Andric __bit_iterator __t(*this); 8940b57cec5SDimitry Andric __t -= __n; 8950b57cec5SDimitry Andric return __t; 8960b57cec5SDimitry Andric } 8970b57cec5SDimitry Andric 8985f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator 8995f757f3fSDimitry Andric operator+(difference_type __n, const __bit_iterator& __it) { 9005f757f3fSDimitry Andric return __it + __n; 9015f757f3fSDimitry Andric } 9020b57cec5SDimitry Andric 9035f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend difference_type 9045f757f3fSDimitry Andric operator-(const __bit_iterator& __x, const __bit_iterator& __y) { 9055f757f3fSDimitry Andric return (__x.__seg_ - __y.__seg_) * __bits_per_word + __x.__ctz_ - __y.__ctz_; 9065f757f3fSDimitry Andric } 9070b57cec5SDimitry Andric 9085f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator[](difference_type __n) const { 9095f757f3fSDimitry Andric return *(*this + __n); 9105f757f3fSDimitry Andric } 9110b57cec5SDimitry Andric 9125f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool 9135f757f3fSDimitry Andric operator==(const __bit_iterator& __x, const __bit_iterator& __y) { 9145f757f3fSDimitry Andric return __x.__seg_ == __y.__seg_ && __x.__ctz_ == __y.__ctz_; 9155f757f3fSDimitry Andric } 9160b57cec5SDimitry Andric 917*36b606aeSDimitry Andric#if _LIBCPP_STD_VER <= 17 9185f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool 9195f757f3fSDimitry Andric operator!=(const __bit_iterator& __x, const __bit_iterator& __y) { 9205f757f3fSDimitry Andric return !(__x == __y); 9215f757f3fSDimitry Andric } 9220b57cec5SDimitry Andric 9235f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool 9245f757f3fSDimitry Andric operator<(const __bit_iterator& __x, const __bit_iterator& __y) { 9255f757f3fSDimitry Andric return __x.__seg_ < __y.__seg_ || (__x.__seg_ == __y.__seg_ && __x.__ctz_ < __y.__ctz_); 9265f757f3fSDimitry Andric } 9270b57cec5SDimitry Andric 9285f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool 9295f757f3fSDimitry Andric operator>(const __bit_iterator& __x, const __bit_iterator& __y) { 9305f757f3fSDimitry Andric return __y < __x; 9315f757f3fSDimitry Andric } 9320b57cec5SDimitry Andric 9335f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool 9345f757f3fSDimitry Andric operator<=(const __bit_iterator& __x, const __bit_iterator& __y) { 9355f757f3fSDimitry Andric return !(__y < __x); 9365f757f3fSDimitry Andric } 9370b57cec5SDimitry Andric 9385f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool 9395f757f3fSDimitry Andric operator>=(const __bit_iterator& __x, const __bit_iterator& __y) { 9405f757f3fSDimitry Andric return !(__x < __y); 9415f757f3fSDimitry Andric } 942*36b606aeSDimitry Andric#else // _LIBCPP_STD_VER <= 17 943*36b606aeSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr friend strong_ordering 944*36b606aeSDimitry Andric operator<=>(const __bit_iterator& __x, const __bit_iterator& __y) { 945*36b606aeSDimitry Andric if (__x.__seg_ < __y.__seg_) 946*36b606aeSDimitry Andric return strong_ordering::less; 947*36b606aeSDimitry Andric 948*36b606aeSDimitry Andric if (__x.__seg_ == __y.__seg_) 949*36b606aeSDimitry Andric return __x.__ctz_ <=> __y.__ctz_; 950*36b606aeSDimitry Andric 951*36b606aeSDimitry Andric return strong_ordering::greater; 952*36b606aeSDimitry Andric } 953*36b606aeSDimitry Andric#endif // _LIBCPP_STD_VER <= 17 9540b57cec5SDimitry Andric 9550b57cec5SDimitry Andricprivate: 9560fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI 9570fca6ea1SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bit_iterator(__storage_pointer __s, unsigned __ctz) _NOEXCEPT 9585f757f3fSDimitry Andric : __seg_(__s), 9595f757f3fSDimitry Andric __ctz_(__ctz) {} 9600b57cec5SDimitry Andric 9610b57cec5SDimitry Andric friend typename _Cp::__self; 9620b57cec5SDimitry Andric 9630b57cec5SDimitry Andric friend class __bit_reference<_Cp>; 9640b57cec5SDimitry Andric friend class __bit_const_reference<_Cp>; 9650b57cec5SDimitry Andric friend class __bit_iterator<_Cp, true>; 96661cfbce3SDimitry Andric template <class _Dp> 9675f757f3fSDimitry Andric friend struct __bit_array; 9680fca6ea1SDimitry Andric 969868ee3f2SDimitry Andric template <bool _FillVal, class _Dp> 9700fca6ea1SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 friend void 9710fca6ea1SDimitry Andric __fill_n_bool(__bit_iterator<_Dp, false> __first, typename _Dp::size_type __n); 97261cfbce3SDimitry Andric 97361cfbce3SDimitry Andric template <class _Dp, bool _IC> 9745f757f3fSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_aligned( 9755f757f3fSDimitry Andric __bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result); 97661cfbce3SDimitry Andric template <class _Dp, bool _IC> 9775f757f3fSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_unaligned( 9785f757f3fSDimitry Andric __bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result); 97961cfbce3SDimitry Andric template <class _Dp, bool _IC> 9805f757f3fSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> 9815f757f3fSDimitry Andric copy(__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result); 98261cfbce3SDimitry Andric template <class _Dp, bool _IC> 9835f757f3fSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_backward_aligned( 9845f757f3fSDimitry Andric __bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result); 98561cfbce3SDimitry Andric template <class _Dp, bool _IC> 9865f757f3fSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_backward_unaligned( 9875f757f3fSDimitry Andric __bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result); 98861cfbce3SDimitry Andric template <class _Dp, bool _IC> 9895f757f3fSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> 9905f757f3fSDimitry Andric copy_backward(__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result); 9915f757f3fSDimitry Andric template <class _Cl, class _Cr> 9925f757f3fSDimitry Andric friend __bit_iterator<_Cr, false> 9935f757f3fSDimitry Andric __swap_ranges_aligned(__bit_iterator<_Cl, false>, __bit_iterator<_Cl, false>, __bit_iterator<_Cr, false>); 9945f757f3fSDimitry Andric template <class _Cl, class _Cr> 9955f757f3fSDimitry Andric friend __bit_iterator<_Cr, false> 9965f757f3fSDimitry Andric __swap_ranges_unaligned(__bit_iterator<_Cl, false>, __bit_iterator<_Cl, false>, __bit_iterator<_Cr, false>); 9975f757f3fSDimitry Andric template <class _Cl, class _Cr> 9985f757f3fSDimitry Andric friend __bit_iterator<_Cr, false> 9995f757f3fSDimitry Andric swap_ranges(__bit_iterator<_Cl, false>, __bit_iterator<_Cl, false>, __bit_iterator<_Cr, false>); 100061cfbce3SDimitry Andric template <class _Dp> 10015f757f3fSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> 10025f757f3fSDimitry Andric rotate(__bit_iterator<_Dp, false>, __bit_iterator<_Dp, false>, __bit_iterator<_Dp, false>); 100361cfbce3SDimitry Andric template <class _Dp, bool _IC1, bool _IC2> 10045f757f3fSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool 10055f757f3fSDimitry Andric __equal_aligned(__bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC2>); 100661cfbce3SDimitry Andric template <class _Dp, bool _IC1, bool _IC2> 10075f757f3fSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool 10085f757f3fSDimitry Andric __equal_unaligned(__bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC2>); 100961cfbce3SDimitry Andric template <class _Dp, bool _IC1, bool _IC2> 10105f757f3fSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool 10115f757f3fSDimitry Andric equal(__bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC2>); 10125f757f3fSDimitry Andric template <bool _ToFind, class _Dp, bool _IC> 10135f757f3fSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, _IC> 10145f757f3fSDimitry Andric __find_bool(__bit_iterator<_Dp, _IC>, typename _Dp::size_type); 10155f757f3fSDimitry Andric template <bool _ToCount, class _Dp, bool _IC> 10160fca6ea1SDimitry Andric friend typename __bit_iterator<_Dp, _IC>::difference_type _LIBCPP_HIDE_FROM_ABI 10170fca6ea1SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 __count_bool(__bit_iterator<_Dp, _IC>, typename _Dp::size_type); 10180b57cec5SDimitry Andric}; 10190b57cec5SDimitry Andric 10200b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD 10210b57cec5SDimitry Andric 10220b57cec5SDimitry Andric_LIBCPP_POP_MACROS 10230b57cec5SDimitry Andric 10240b57cec5SDimitry Andric#endif // _LIBCPP___BIT_REFERENCE 1025