xref: /freebsd/contrib/llvm-project/libcxx/include/__bit_reference (revision 36b606ae6aa4b24061096ba18582e0a08ccd5dba)
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