xref: /llvm-project/libcxx/include/__cxx03/__bit_reference (revision ce7771902dc50d900de639d499a60486b83f70e0)
1e78f53d1SNikolas Klauser// -*- C++ -*-
2e78f53d1SNikolas Klauser//===----------------------------------------------------------------------===//
3e78f53d1SNikolas Klauser//
4e78f53d1SNikolas Klauser// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5e78f53d1SNikolas Klauser// See https://llvm.org/LICENSE.txt for license information.
6e78f53d1SNikolas Klauser// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7e78f53d1SNikolas Klauser//
8e78f53d1SNikolas Klauser//===----------------------------------------------------------------------===//
9e78f53d1SNikolas Klauser
10*ce777190SNikolas Klauser#ifndef _LIBCPP___CXX03___BIT_REFERENCE
11*ce777190SNikolas Klauser#define _LIBCPP___CXX03___BIT_REFERENCE
12e78f53d1SNikolas Klauser
1373fbae83SNikolas Klauser#include <__cxx03/__algorithm/copy_n.h>
1473fbae83SNikolas Klauser#include <__cxx03/__algorithm/fill_n.h>
1573fbae83SNikolas Klauser#include <__cxx03/__algorithm/min.h>
1673fbae83SNikolas Klauser#include <__cxx03/__bit/countr.h>
1773fbae83SNikolas Klauser#include <__cxx03/__bit/invert_if.h>
1873fbae83SNikolas Klauser#include <__cxx03/__bit/popcount.h>
1973fbae83SNikolas Klauser#include <__cxx03/__compare/ordering.h>
2073fbae83SNikolas Klauser#include <__cxx03/__config>
2173fbae83SNikolas Klauser#include <__cxx03/__fwd/bit_reference.h>
2273fbae83SNikolas Klauser#include <__cxx03/__iterator/iterator_traits.h>
2373fbae83SNikolas Klauser#include <__cxx03/__memory/construct_at.h>
2473fbae83SNikolas Klauser#include <__cxx03/__memory/pointer_traits.h>
2573fbae83SNikolas Klauser#include <__cxx03/__type_traits/conditional.h>
2673fbae83SNikolas Klauser#include <__cxx03/__utility/swap.h>
2773fbae83SNikolas Klauser#include <__cxx03/cstring>
28e78f53d1SNikolas Klauser
29e78f53d1SNikolas Klauser#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
30e78f53d1SNikolas Klauser#  pragma GCC system_header
31e78f53d1SNikolas Klauser#endif
32e78f53d1SNikolas Klauser
33e78f53d1SNikolas Klauser_LIBCPP_PUSH_MACROS
3473fbae83SNikolas Klauser#include <__cxx03/__undef_macros>
35e78f53d1SNikolas Klauser
36e78f53d1SNikolas Klauser_LIBCPP_BEGIN_NAMESPACE_STD
37e78f53d1SNikolas Klauser
38e78f53d1SNikolas Klausertemplate <class _Cp>
39e78f53d1SNikolas Klauserclass __bit_const_reference;
40e78f53d1SNikolas Klauser
41e78f53d1SNikolas Klausertemplate <class _Tp>
42e78f53d1SNikolas Klauserstruct __has_storage_type {
43e78f53d1SNikolas Klauser  static const bool value = false;
44e78f53d1SNikolas Klauser};
45e78f53d1SNikolas Klauser
46e78f53d1SNikolas Klausertemplate <class _Cp, bool = __has_storage_type<_Cp>::value>
47e78f53d1SNikolas Klauserclass __bit_reference {
48e78f53d1SNikolas Klauser  using __storage_type    = typename _Cp::__storage_type;
49e78f53d1SNikolas Klauser  using __storage_pointer = typename _Cp::__storage_pointer;
50e78f53d1SNikolas Klauser
51e78f53d1SNikolas Klauser  __storage_pointer __seg_;
52e78f53d1SNikolas Klauser  __storage_type __mask_;
53e78f53d1SNikolas Klauser
54e78f53d1SNikolas Klauser  friend typename _Cp::__self;
55e78f53d1SNikolas Klauser
56e78f53d1SNikolas Klauser  friend class __bit_const_reference<_Cp>;
57e78f53d1SNikolas Klauser  friend class __bit_iterator<_Cp, false>;
58e78f53d1SNikolas Klauser
59e78f53d1SNikolas Klauserpublic:
60e78f53d1SNikolas Klauser  using __container = typename _Cp::__self;
61e78f53d1SNikolas Klauser
62e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_reference(const __bit_reference&) = default;
63e78f53d1SNikolas Klauser
64e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 operator bool() const _NOEXCEPT {
65e78f53d1SNikolas Klauser    return static_cast<bool>(*__seg_ & __mask_);
66e78f53d1SNikolas Klauser  }
67e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool operator~() const _NOEXCEPT {
68e78f53d1SNikolas Klauser    return !static_cast<bool>(*this);
69e78f53d1SNikolas Klauser  }
70e78f53d1SNikolas Klauser
71e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_reference& operator=(bool __x) _NOEXCEPT {
72e78f53d1SNikolas Klauser    if (__x)
73e78f53d1SNikolas Klauser      *__seg_ |= __mask_;
74e78f53d1SNikolas Klauser    else
75e78f53d1SNikolas Klauser      *__seg_ &= ~__mask_;
76e78f53d1SNikolas Klauser    return *this;
77e78f53d1SNikolas Klauser  }
78e78f53d1SNikolas Klauser
79e78f53d1SNikolas Klauser#if _LIBCPP_STD_VER >= 23
80e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI constexpr const __bit_reference& operator=(bool __x) const noexcept {
81e78f53d1SNikolas Klauser    if (__x)
82e78f53d1SNikolas Klauser      *__seg_ |= __mask_;
83e78f53d1SNikolas Klauser    else
84e78f53d1SNikolas Klauser      *__seg_ &= ~__mask_;
85e78f53d1SNikolas Klauser    return *this;
86e78f53d1SNikolas Klauser  }
87e78f53d1SNikolas Klauser#endif
88e78f53d1SNikolas Klauser
89e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_reference& operator=(const __bit_reference& __x) _NOEXCEPT {
90e78f53d1SNikolas Klauser    return operator=(static_cast<bool>(__x));
91e78f53d1SNikolas Klauser  }
92e78f53d1SNikolas Klauser
93e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void flip() _NOEXCEPT { *__seg_ ^= __mask_; }
94e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false> operator&() const _NOEXCEPT {
95e78f53d1SNikolas Klauser    return __bit_iterator<_Cp, false>(__seg_, static_cast<unsigned>(std::__libcpp_ctz(__mask_)));
96e78f53d1SNikolas Klauser  }
97e78f53d1SNikolas Klauser
98e78f53d1SNikolas Klauserprivate:
99e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
100e78f53d1SNikolas Klauser  _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bit_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT
101e78f53d1SNikolas Klauser      : __seg_(__s),
102e78f53d1SNikolas Klauser        __mask_(__m) {}
103e78f53d1SNikolas Klauser};
104e78f53d1SNikolas Klauser
105e78f53d1SNikolas Klausertemplate <class _Cp>
106e78f53d1SNikolas Klauserclass __bit_reference<_Cp, false> {};
107e78f53d1SNikolas Klauser
108e78f53d1SNikolas Klausertemplate <class _Cp>
109e78f53d1SNikolas Klauserinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
110e78f53d1SNikolas Klauserswap(__bit_reference<_Cp> __x, __bit_reference<_Cp> __y) _NOEXCEPT {
111e78f53d1SNikolas Klauser  bool __t = __x;
112e78f53d1SNikolas Klauser  __x      = __y;
113e78f53d1SNikolas Klauser  __y      = __t;
114e78f53d1SNikolas Klauser}
115e78f53d1SNikolas Klauser
116e78f53d1SNikolas Klausertemplate <class _Cp, class _Dp>
117e78f53d1SNikolas Klauserinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
118e78f53d1SNikolas Klauserswap(__bit_reference<_Cp> __x, __bit_reference<_Dp> __y) _NOEXCEPT {
119e78f53d1SNikolas Klauser  bool __t = __x;
120e78f53d1SNikolas Klauser  __x      = __y;
121e78f53d1SNikolas Klauser  __y      = __t;
122e78f53d1SNikolas Klauser}
123e78f53d1SNikolas Klauser
124e78f53d1SNikolas Klausertemplate <class _Cp>
125e78f53d1SNikolas Klauserinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(__bit_reference<_Cp> __x, bool& __y) _NOEXCEPT {
126e78f53d1SNikolas Klauser  bool __t = __x;
127e78f53d1SNikolas Klauser  __x      = __y;
128e78f53d1SNikolas Klauser  __y      = __t;
129e78f53d1SNikolas Klauser}
130e78f53d1SNikolas Klauser
131e78f53d1SNikolas Klausertemplate <class _Cp>
132e78f53d1SNikolas Klauserinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(bool& __x, __bit_reference<_Cp> __y) _NOEXCEPT {
133e78f53d1SNikolas Klauser  bool __t = __x;
134e78f53d1SNikolas Klauser  __x      = __y;
135e78f53d1SNikolas Klauser  __y      = __t;
136e78f53d1SNikolas Klauser}
137e78f53d1SNikolas Klauser
138e78f53d1SNikolas Klausertemplate <class _Cp>
139e78f53d1SNikolas Klauserclass __bit_const_reference {
140e78f53d1SNikolas Klauser  using __storage_type    = typename _Cp::__storage_type;
141e78f53d1SNikolas Klauser  using __storage_pointer = typename _Cp::__const_storage_pointer;
142e78f53d1SNikolas Klauser
143e78f53d1SNikolas Klauser  __storage_pointer __seg_;
144e78f53d1SNikolas Klauser  __storage_type __mask_;
145e78f53d1SNikolas Klauser
146e78f53d1SNikolas Klauser  friend typename _Cp::__self;
147e78f53d1SNikolas Klauser  friend class __bit_iterator<_Cp, true>;
148e78f53d1SNikolas Klauser
149e78f53d1SNikolas Klauserpublic:
150e78f53d1SNikolas Klauser  using __container = typename _Cp::__self;
151e78f53d1SNikolas Klauser
152e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI __bit_const_reference(const __bit_const_reference&) = default;
153e78f53d1SNikolas Klauser  __bit_const_reference& operator=(const __bit_const_reference&)            = delete;
154e78f53d1SNikolas Klauser
155e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_const_reference(const __bit_reference<_Cp>& __x) _NOEXCEPT
156e78f53d1SNikolas Klauser      : __seg_(__x.__seg_),
157e78f53d1SNikolas Klauser        __mask_(__x.__mask_) {}
158e78f53d1SNikolas Klauser
159e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR operator bool() const _NOEXCEPT {
160e78f53d1SNikolas Klauser    return static_cast<bool>(*__seg_ & __mask_);
161e78f53d1SNikolas Klauser  }
162e78f53d1SNikolas Klauser
163e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, true> operator&() const _NOEXCEPT {
164e78f53d1SNikolas Klauser    return __bit_iterator<_Cp, true>(__seg_, static_cast<unsigned>(std::__libcpp_ctz(__mask_)));
165e78f53d1SNikolas Klauser  }
166e78f53d1SNikolas Klauser
167e78f53d1SNikolas Klauserprivate:
168e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
169e78f53d1SNikolas Klauser  _LIBCPP_CONSTEXPR explicit __bit_const_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT
170e78f53d1SNikolas Klauser      : __seg_(__s),
171e78f53d1SNikolas Klauser        __mask_(__m) {}
172e78f53d1SNikolas Klauser};
173e78f53d1SNikolas Klauser
174e78f53d1SNikolas Klauser// copy
175e78f53d1SNikolas Klauser
176e78f53d1SNikolas Klausertemplate <class _Cp, bool _IsConst>
177e78f53d1SNikolas Klauser_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_aligned(
178e78f53d1SNikolas Klauser    __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
179e78f53d1SNikolas Klauser  using _In             = __bit_iterator<_Cp, _IsConst>;
180e78f53d1SNikolas Klauser  using difference_type = typename _In::difference_type;
181e78f53d1SNikolas Klauser  using __storage_type  = typename _In::__storage_type;
182e78f53d1SNikolas Klauser
183e78f53d1SNikolas Klauser  const int __bits_per_word = _In::__bits_per_word;
184e78f53d1SNikolas Klauser  difference_type __n       = __last - __first;
185e78f53d1SNikolas Klauser  if (__n > 0) {
186e78f53d1SNikolas Klauser    // do first word
187e78f53d1SNikolas Klauser    if (__first.__ctz_ != 0) {
188e78f53d1SNikolas Klauser      unsigned __clz       = __bits_per_word - __first.__ctz_;
189e78f53d1SNikolas Klauser      difference_type __dn = std::min(static_cast<difference_type>(__clz), __n);
190e78f53d1SNikolas Klauser      __n -= __dn;
191e78f53d1SNikolas Klauser      __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn));
192e78f53d1SNikolas Klauser      __storage_type __b = *__first.__seg_ & __m;
193e78f53d1SNikolas Klauser      *__result.__seg_ &= ~__m;
194e78f53d1SNikolas Klauser      *__result.__seg_ |= __b;
195e78f53d1SNikolas Klauser      __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
196e78f53d1SNikolas Klauser      __result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
197e78f53d1SNikolas Klauser      ++__first.__seg_;
198e78f53d1SNikolas Klauser      // __first.__ctz_ = 0;
199e78f53d1SNikolas Klauser    }
200e78f53d1SNikolas Klauser    // __first.__ctz_ == 0;
201e78f53d1SNikolas Klauser    // do middle words
202e78f53d1SNikolas Klauser    __storage_type __nw = __n / __bits_per_word;
203e78f53d1SNikolas Klauser    std::copy_n(std::__to_address(__first.__seg_), __nw, std::__to_address(__result.__seg_));
204e78f53d1SNikolas Klauser    __n -= __nw * __bits_per_word;
205e78f53d1SNikolas Klauser    __result.__seg_ += __nw;
206e78f53d1SNikolas Klauser    // do last word
207e78f53d1SNikolas Klauser    if (__n > 0) {
208e78f53d1SNikolas Klauser      __first.__seg_ += __nw;
209e78f53d1SNikolas Klauser      __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
210e78f53d1SNikolas Klauser      __storage_type __b = *__first.__seg_ & __m;
211e78f53d1SNikolas Klauser      *__result.__seg_ &= ~__m;
212e78f53d1SNikolas Klauser      *__result.__seg_ |= __b;
213e78f53d1SNikolas Klauser      __result.__ctz_ = static_cast<unsigned>(__n);
214e78f53d1SNikolas Klauser    }
215e78f53d1SNikolas Klauser  }
216e78f53d1SNikolas Klauser  return __result;
217e78f53d1SNikolas Klauser}
218e78f53d1SNikolas Klauser
219e78f53d1SNikolas Klausertemplate <class _Cp, bool _IsConst>
220e78f53d1SNikolas Klauser_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_unaligned(
221e78f53d1SNikolas Klauser    __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
222e78f53d1SNikolas Klauser  using _In             = __bit_iterator<_Cp, _IsConst>;
223e78f53d1SNikolas Klauser  using difference_type = typename _In::difference_type;
224e78f53d1SNikolas Klauser  using __storage_type  = typename _In::__storage_type;
225e78f53d1SNikolas Klauser
226e78f53d1SNikolas Klauser  const int __bits_per_word = _In::__bits_per_word;
227e78f53d1SNikolas Klauser  difference_type __n       = __last - __first;
228e78f53d1SNikolas Klauser  if (__n > 0) {
229e78f53d1SNikolas Klauser    // do first word
230e78f53d1SNikolas Klauser    if (__first.__ctz_ != 0) {
231e78f53d1SNikolas Klauser      unsigned __clz_f     = __bits_per_word - __first.__ctz_;
232e78f53d1SNikolas Klauser      difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n);
233e78f53d1SNikolas Klauser      __n -= __dn;
234e78f53d1SNikolas Klauser      __storage_type __m   = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
235e78f53d1SNikolas Klauser      __storage_type __b   = *__first.__seg_ & __m;
236e78f53d1SNikolas Klauser      unsigned __clz_r     = __bits_per_word - __result.__ctz_;
237e78f53d1SNikolas Klauser      __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
238e78f53d1SNikolas Klauser      __m                  = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn));
239e78f53d1SNikolas Klauser      *__result.__seg_ &= ~__m;
240e78f53d1SNikolas Klauser      if (__result.__ctz_ > __first.__ctz_)
241e78f53d1SNikolas Klauser        *__result.__seg_ |= __b << (__result.__ctz_ - __first.__ctz_);
242e78f53d1SNikolas Klauser      else
243e78f53d1SNikolas Klauser        *__result.__seg_ |= __b >> (__first.__ctz_ - __result.__ctz_);
244e78f53d1SNikolas Klauser      __result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word;
245e78f53d1SNikolas Klauser      __result.__ctz_ = static_cast<unsigned>((__ddn + __result.__ctz_) % __bits_per_word);
246e78f53d1SNikolas Klauser      __dn -= __ddn;
247e78f53d1SNikolas Klauser      if (__dn > 0) {
248e78f53d1SNikolas Klauser        __m = ~__storage_type(0) >> (__bits_per_word - __dn);
249e78f53d1SNikolas Klauser        *__result.__seg_ &= ~__m;
250e78f53d1SNikolas Klauser        *__result.__seg_ |= __b >> (__first.__ctz_ + __ddn);
251e78f53d1SNikolas Klauser        __result.__ctz_ = static_cast<unsigned>(__dn);
252e78f53d1SNikolas Klauser      }
253e78f53d1SNikolas Klauser      ++__first.__seg_;
254e78f53d1SNikolas Klauser      // __first.__ctz_ = 0;
255e78f53d1SNikolas Klauser    }
256e78f53d1SNikolas Klauser    // __first.__ctz_ == 0;
257e78f53d1SNikolas Klauser    // do middle words
258e78f53d1SNikolas Klauser    unsigned __clz_r   = __bits_per_word - __result.__ctz_;
259e78f53d1SNikolas Klauser    __storage_type __m = ~__storage_type(0) << __result.__ctz_;
260e78f53d1SNikolas Klauser    for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) {
261e78f53d1SNikolas Klauser      __storage_type __b = *__first.__seg_;
262e78f53d1SNikolas Klauser      *__result.__seg_ &= ~__m;
263e78f53d1SNikolas Klauser      *__result.__seg_ |= __b << __result.__ctz_;
264e78f53d1SNikolas Klauser      ++__result.__seg_;
265e78f53d1SNikolas Klauser      *__result.__seg_ &= __m;
266e78f53d1SNikolas Klauser      *__result.__seg_ |= __b >> __clz_r;
267e78f53d1SNikolas Klauser    }
268e78f53d1SNikolas Klauser    // do last word
269e78f53d1SNikolas Klauser    if (__n > 0) {
270e78f53d1SNikolas Klauser      __m                 = ~__storage_type(0) >> (__bits_per_word - __n);
271e78f53d1SNikolas Klauser      __storage_type __b  = *__first.__seg_ & __m;
272e78f53d1SNikolas Klauser      __storage_type __dn = std::min(__n, static_cast<difference_type>(__clz_r));
273e78f53d1SNikolas Klauser      __m                 = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn));
274e78f53d1SNikolas Klauser      *__result.__seg_ &= ~__m;
275e78f53d1SNikolas Klauser      *__result.__seg_ |= __b << __result.__ctz_;
276e78f53d1SNikolas Klauser      __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
277e78f53d1SNikolas Klauser      __result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
278e78f53d1SNikolas Klauser      __n -= __dn;
279e78f53d1SNikolas Klauser      if (__n > 0) {
280e78f53d1SNikolas Klauser        __m = ~__storage_type(0) >> (__bits_per_word - __n);
281e78f53d1SNikolas Klauser        *__result.__seg_ &= ~__m;
282e78f53d1SNikolas Klauser        *__result.__seg_ |= __b >> __dn;
283e78f53d1SNikolas Klauser        __result.__ctz_ = static_cast<unsigned>(__n);
284e78f53d1SNikolas Klauser      }
285e78f53d1SNikolas Klauser    }
286e78f53d1SNikolas Klauser  }
287e78f53d1SNikolas Klauser  return __result;
288e78f53d1SNikolas Klauser}
289e78f53d1SNikolas Klauser
290e78f53d1SNikolas Klausertemplate <class _Cp, bool _IsConst>
291e78f53d1SNikolas Klauserinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false>
292e78f53d1SNikolas Klausercopy(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
293e78f53d1SNikolas Klauser  if (__first.__ctz_ == __result.__ctz_)
294e78f53d1SNikolas Klauser    return std::__copy_aligned(__first, __last, __result);
295e78f53d1SNikolas Klauser  return std::__copy_unaligned(__first, __last, __result);
296e78f53d1SNikolas Klauser}
297e78f53d1SNikolas Klauser
298e78f53d1SNikolas Klauser// copy_backward
299e78f53d1SNikolas Klauser
300e78f53d1SNikolas Klausertemplate <class _Cp, bool _IsConst>
301e78f53d1SNikolas Klauser_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_backward_aligned(
302e78f53d1SNikolas Klauser    __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
303e78f53d1SNikolas Klauser  using _In             = __bit_iterator<_Cp, _IsConst>;
304e78f53d1SNikolas Klauser  using difference_type = typename _In::difference_type;
305e78f53d1SNikolas Klauser  using __storage_type  = typename _In::__storage_type;
306e78f53d1SNikolas Klauser
307e78f53d1SNikolas Klauser  const int __bits_per_word = _In::__bits_per_word;
308e78f53d1SNikolas Klauser  difference_type __n       = __last - __first;
309e78f53d1SNikolas Klauser  if (__n > 0) {
310e78f53d1SNikolas Klauser    // do first word
311e78f53d1SNikolas Klauser    if (__last.__ctz_ != 0) {
312e78f53d1SNikolas Klauser      difference_type __dn = std::min(static_cast<difference_type>(__last.__ctz_), __n);
313e78f53d1SNikolas Klauser      __n -= __dn;
314e78f53d1SNikolas Klauser      unsigned __clz     = __bits_per_word - __last.__ctz_;
315e78f53d1SNikolas Klauser      __storage_type __m = (~__storage_type(0) << (__last.__ctz_ - __dn)) & (~__storage_type(0) >> __clz);
316e78f53d1SNikolas Klauser      __storage_type __b = *__last.__seg_ & __m;
317e78f53d1SNikolas Klauser      *__result.__seg_ &= ~__m;
318e78f53d1SNikolas Klauser      *__result.__seg_ |= __b;
319e78f53d1SNikolas Klauser      __result.__ctz_ = static_cast<unsigned>(((-__dn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word);
320e78f53d1SNikolas Klauser      // __last.__ctz_ = 0
321e78f53d1SNikolas Klauser    }
322e78f53d1SNikolas Klauser    // __last.__ctz_ == 0 || __n == 0
323e78f53d1SNikolas Klauser    // __result.__ctz_ == 0 || __n == 0
324e78f53d1SNikolas Klauser    // do middle words
325e78f53d1SNikolas Klauser    __storage_type __nw = __n / __bits_per_word;
326e78f53d1SNikolas Klauser    __result.__seg_ -= __nw;
327e78f53d1SNikolas Klauser    __last.__seg_ -= __nw;
328e78f53d1SNikolas Klauser    std::copy_n(std::__to_address(__last.__seg_), __nw, std::__to_address(__result.__seg_));
329e78f53d1SNikolas Klauser    __n -= __nw * __bits_per_word;
330e78f53d1SNikolas Klauser    // do last word
331e78f53d1SNikolas Klauser    if (__n > 0) {
332e78f53d1SNikolas Klauser      __storage_type __m = ~__storage_type(0) << (__bits_per_word - __n);
333e78f53d1SNikolas Klauser      __storage_type __b = *--__last.__seg_ & __m;
334e78f53d1SNikolas Klauser      *--__result.__seg_ &= ~__m;
335e78f53d1SNikolas Klauser      *__result.__seg_ |= __b;
336e78f53d1SNikolas Klauser      __result.__ctz_ = static_cast<unsigned>(-__n & (__bits_per_word - 1));
337e78f53d1SNikolas Klauser    }
338e78f53d1SNikolas Klauser  }
339e78f53d1SNikolas Klauser  return __result;
340e78f53d1SNikolas Klauser}
341e78f53d1SNikolas Klauser
342e78f53d1SNikolas Klausertemplate <class _Cp, bool _IsConst>
343e78f53d1SNikolas Klauser_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_backward_unaligned(
344e78f53d1SNikolas Klauser    __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
345e78f53d1SNikolas Klauser  using _In             = __bit_iterator<_Cp, _IsConst>;
346e78f53d1SNikolas Klauser  using difference_type = typename _In::difference_type;
347e78f53d1SNikolas Klauser  using __storage_type  = typename _In::__storage_type;
348e78f53d1SNikolas Klauser
349e78f53d1SNikolas Klauser  const int __bits_per_word = _In::__bits_per_word;
350e78f53d1SNikolas Klauser  difference_type __n       = __last - __first;
351e78f53d1SNikolas Klauser  if (__n > 0) {
352e78f53d1SNikolas Klauser    // do first word
353e78f53d1SNikolas Klauser    if (__last.__ctz_ != 0) {
354e78f53d1SNikolas Klauser      difference_type __dn = std::min(static_cast<difference_type>(__last.__ctz_), __n);
355e78f53d1SNikolas Klauser      __n -= __dn;
356e78f53d1SNikolas Klauser      unsigned __clz_l     = __bits_per_word - __last.__ctz_;
357e78f53d1SNikolas Klauser      __storage_type __m   = (~__storage_type(0) << (__last.__ctz_ - __dn)) & (~__storage_type(0) >> __clz_l);
358e78f53d1SNikolas Klauser      __storage_type __b   = *__last.__seg_ & __m;
359e78f53d1SNikolas Klauser      unsigned __clz_r     = __bits_per_word - __result.__ctz_;
360e78f53d1SNikolas Klauser      __storage_type __ddn = std::min(__dn, static_cast<difference_type>(__result.__ctz_));
361e78f53d1SNikolas Klauser      if (__ddn > 0) {
362e78f53d1SNikolas Klauser        __m = (~__storage_type(0) << (__result.__ctz_ - __ddn)) & (~__storage_type(0) >> __clz_r);
363e78f53d1SNikolas Klauser        *__result.__seg_ &= ~__m;
364e78f53d1SNikolas Klauser        if (__result.__ctz_ > __last.__ctz_)
365e78f53d1SNikolas Klauser          *__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_);
366e78f53d1SNikolas Klauser        else
367e78f53d1SNikolas Klauser          *__result.__seg_ |= __b >> (__last.__ctz_ - __result.__ctz_);
368e78f53d1SNikolas Klauser        __result.__ctz_ = static_cast<unsigned>(((-__ddn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word);
369e78f53d1SNikolas Klauser        __dn -= __ddn;
370e78f53d1SNikolas Klauser      }
371e78f53d1SNikolas Klauser      if (__dn > 0) {
372e78f53d1SNikolas Klauser        // __result.__ctz_ == 0
373e78f53d1SNikolas Klauser        --__result.__seg_;
374e78f53d1SNikolas Klauser        __result.__ctz_ = static_cast<unsigned>(-__dn & (__bits_per_word - 1));
375e78f53d1SNikolas Klauser        __m             = ~__storage_type(0) << __result.__ctz_;
376e78f53d1SNikolas Klauser        *__result.__seg_ &= ~__m;
377e78f53d1SNikolas Klauser        __last.__ctz_ -= __dn + __ddn;
378e78f53d1SNikolas Klauser        *__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_);
379e78f53d1SNikolas Klauser      }
380e78f53d1SNikolas Klauser      // __last.__ctz_ = 0
381e78f53d1SNikolas Klauser    }
382e78f53d1SNikolas Klauser    // __last.__ctz_ == 0 || __n == 0
383e78f53d1SNikolas Klauser    // __result.__ctz_ != 0 || __n == 0
384e78f53d1SNikolas Klauser    // do middle words
385e78f53d1SNikolas Klauser    unsigned __clz_r   = __bits_per_word - __result.__ctz_;
386e78f53d1SNikolas Klauser    __storage_type __m = ~__storage_type(0) >> __clz_r;
387e78f53d1SNikolas Klauser    for (; __n >= __bits_per_word; __n -= __bits_per_word) {
388e78f53d1SNikolas Klauser      __storage_type __b = *--__last.__seg_;
389e78f53d1SNikolas Klauser      *__result.__seg_ &= ~__m;
390e78f53d1SNikolas Klauser      *__result.__seg_ |= __b >> __clz_r;
391e78f53d1SNikolas Klauser      *--__result.__seg_ &= __m;
392e78f53d1SNikolas Klauser      *__result.__seg_ |= __b << __result.__ctz_;
393e78f53d1SNikolas Klauser    }
394e78f53d1SNikolas Klauser    // do last word
395e78f53d1SNikolas Klauser    if (__n > 0) {
396e78f53d1SNikolas Klauser      __m                 = ~__storage_type(0) << (__bits_per_word - __n);
397e78f53d1SNikolas Klauser      __storage_type __b  = *--__last.__seg_ & __m;
398e78f53d1SNikolas Klauser      __clz_r             = __bits_per_word - __result.__ctz_;
399e78f53d1SNikolas Klauser      __storage_type __dn = std::min(__n, static_cast<difference_type>(__result.__ctz_));
400e78f53d1SNikolas Klauser      __m                 = (~__storage_type(0) << (__result.__ctz_ - __dn)) & (~__storage_type(0) >> __clz_r);
401e78f53d1SNikolas Klauser      *__result.__seg_ &= ~__m;
402e78f53d1SNikolas Klauser      *__result.__seg_ |= __b >> (__bits_per_word - __result.__ctz_);
403e78f53d1SNikolas Klauser      __result.__ctz_ = static_cast<unsigned>(((-__dn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word);
404e78f53d1SNikolas Klauser      __n -= __dn;
405e78f53d1SNikolas Klauser      if (__n > 0) {
406e78f53d1SNikolas Klauser        // __result.__ctz_ == 0
407e78f53d1SNikolas Klauser        --__result.__seg_;
408e78f53d1SNikolas Klauser        __result.__ctz_ = static_cast<unsigned>(-__n & (__bits_per_word - 1));
409e78f53d1SNikolas Klauser        __m             = ~__storage_type(0) << __result.__ctz_;
410e78f53d1SNikolas Klauser        *__result.__seg_ &= ~__m;
411e78f53d1SNikolas Klauser        *__result.__seg_ |= __b << (__result.__ctz_ - (__bits_per_word - __n - __dn));
412e78f53d1SNikolas Klauser      }
413e78f53d1SNikolas Klauser    }
414e78f53d1SNikolas Klauser  }
415e78f53d1SNikolas Klauser  return __result;
416e78f53d1SNikolas Klauser}
417e78f53d1SNikolas Klauser
418e78f53d1SNikolas Klausertemplate <class _Cp, bool _IsConst>
419e78f53d1SNikolas Klauserinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false> copy_backward(
420e78f53d1SNikolas Klauser    __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
421e78f53d1SNikolas Klauser  if (__last.__ctz_ == __result.__ctz_)
422e78f53d1SNikolas Klauser    return std::__copy_backward_aligned(__first, __last, __result);
423e78f53d1SNikolas Klauser  return std::__copy_backward_unaligned(__first, __last, __result);
424e78f53d1SNikolas Klauser}
425e78f53d1SNikolas Klauser
426e78f53d1SNikolas Klauser// move
427e78f53d1SNikolas Klauser
428e78f53d1SNikolas Klausertemplate <class _Cp, bool _IsConst>
429e78f53d1SNikolas Klauserinline _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false>
430e78f53d1SNikolas Klausermove(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
431e78f53d1SNikolas Klauser  return std::copy(__first, __last, __result);
432e78f53d1SNikolas Klauser}
433e78f53d1SNikolas Klauser
434e78f53d1SNikolas Klauser// move_backward
435e78f53d1SNikolas Klauser
436e78f53d1SNikolas Klausertemplate <class _Cp, bool _IsConst>
437e78f53d1SNikolas Klauserinline _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> move_backward(
438e78f53d1SNikolas Klauser    __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
439e78f53d1SNikolas Klauser  return std::copy_backward(__first, __last, __result);
440e78f53d1SNikolas Klauser}
441e78f53d1SNikolas Klauser
442e78f53d1SNikolas Klauser// swap_ranges
443e78f53d1SNikolas Klauser
444e78f53d1SNikolas Klausertemplate <class _Cl, class _Cr>
445e78f53d1SNikolas Klauser_LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cr, false> __swap_ranges_aligned(
446e78f53d1SNikolas Klauser    __bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, __bit_iterator<_Cr, false> __result) {
447e78f53d1SNikolas Klauser  using _I1             = __bit_iterator<_Cl, false>;
448e78f53d1SNikolas Klauser  using difference_type = typename _I1::difference_type;
449e78f53d1SNikolas Klauser  using __storage_type  = typename _I1::__storage_type;
450e78f53d1SNikolas Klauser
451e78f53d1SNikolas Klauser  const int __bits_per_word = _I1::__bits_per_word;
452e78f53d1SNikolas Klauser  difference_type __n       = __last - __first;
453e78f53d1SNikolas Klauser  if (__n > 0) {
454e78f53d1SNikolas Klauser    // do first word
455e78f53d1SNikolas Klauser    if (__first.__ctz_ != 0) {
456e78f53d1SNikolas Klauser      unsigned __clz       = __bits_per_word - __first.__ctz_;
457e78f53d1SNikolas Klauser      difference_type __dn = std::min(static_cast<difference_type>(__clz), __n);
458e78f53d1SNikolas Klauser      __n -= __dn;
459e78f53d1SNikolas Klauser      __storage_type __m  = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn));
460e78f53d1SNikolas Klauser      __storage_type __b1 = *__first.__seg_ & __m;
461e78f53d1SNikolas Klauser      *__first.__seg_ &= ~__m;
462e78f53d1SNikolas Klauser      __storage_type __b2 = *__result.__seg_ & __m;
463e78f53d1SNikolas Klauser      *__result.__seg_ &= ~__m;
464e78f53d1SNikolas Klauser      *__result.__seg_ |= __b1;
465e78f53d1SNikolas Klauser      *__first.__seg_ |= __b2;
466e78f53d1SNikolas Klauser      __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
467e78f53d1SNikolas Klauser      __result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
468e78f53d1SNikolas Klauser      ++__first.__seg_;
469e78f53d1SNikolas Klauser      // __first.__ctz_ = 0;
470e78f53d1SNikolas Klauser    }
471e78f53d1SNikolas Klauser    // __first.__ctz_ == 0;
472e78f53d1SNikolas Klauser    // do middle words
473e78f53d1SNikolas Klauser    for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_, ++__result.__seg_)
474e78f53d1SNikolas Klauser      swap(*__first.__seg_, *__result.__seg_);
475e78f53d1SNikolas Klauser    // do last word
476e78f53d1SNikolas Klauser    if (__n > 0) {
477e78f53d1SNikolas Klauser      __storage_type __m  = ~__storage_type(0) >> (__bits_per_word - __n);
478e78f53d1SNikolas Klauser      __storage_type __b1 = *__first.__seg_ & __m;
479e78f53d1SNikolas Klauser      *__first.__seg_ &= ~__m;
480e78f53d1SNikolas Klauser      __storage_type __b2 = *__result.__seg_ & __m;
481e78f53d1SNikolas Klauser      *__result.__seg_ &= ~__m;
482e78f53d1SNikolas Klauser      *__result.__seg_ |= __b1;
483e78f53d1SNikolas Klauser      *__first.__seg_ |= __b2;
484e78f53d1SNikolas Klauser      __result.__ctz_ = static_cast<unsigned>(__n);
485e78f53d1SNikolas Klauser    }
486e78f53d1SNikolas Klauser  }
487e78f53d1SNikolas Klauser  return __result;
488e78f53d1SNikolas Klauser}
489e78f53d1SNikolas Klauser
490e78f53d1SNikolas Klausertemplate <class _Cl, class _Cr>
491e78f53d1SNikolas Klauser_LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cr, false> __swap_ranges_unaligned(
492e78f53d1SNikolas Klauser    __bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, __bit_iterator<_Cr, false> __result) {
493e78f53d1SNikolas Klauser  using _I1             = __bit_iterator<_Cl, false>;
494e78f53d1SNikolas Klauser  using difference_type = typename _I1::difference_type;
495e78f53d1SNikolas Klauser  using __storage_type  = typename _I1::__storage_type;
496e78f53d1SNikolas Klauser
497e78f53d1SNikolas Klauser  const int __bits_per_word = _I1::__bits_per_word;
498e78f53d1SNikolas Klauser  difference_type __n       = __last - __first;
499e78f53d1SNikolas Klauser  if (__n > 0) {
500e78f53d1SNikolas Klauser    // do first word
501e78f53d1SNikolas Klauser    if (__first.__ctz_ != 0) {
502e78f53d1SNikolas Klauser      unsigned __clz_f     = __bits_per_word - __first.__ctz_;
503e78f53d1SNikolas Klauser      difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n);
504e78f53d1SNikolas Klauser      __n -= __dn;
505e78f53d1SNikolas Klauser      __storage_type __m  = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
506e78f53d1SNikolas Klauser      __storage_type __b1 = *__first.__seg_ & __m;
507e78f53d1SNikolas Klauser      *__first.__seg_ &= ~__m;
508e78f53d1SNikolas Klauser      unsigned __clz_r     = __bits_per_word - __result.__ctz_;
509e78f53d1SNikolas Klauser      __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
510e78f53d1SNikolas Klauser      __m                  = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn));
511e78f53d1SNikolas Klauser      __storage_type __b2  = *__result.__seg_ & __m;
512e78f53d1SNikolas Klauser      *__result.__seg_ &= ~__m;
513e78f53d1SNikolas Klauser      if (__result.__ctz_ > __first.__ctz_) {
514e78f53d1SNikolas Klauser        unsigned __s = __result.__ctz_ - __first.__ctz_;
515e78f53d1SNikolas Klauser        *__result.__seg_ |= __b1 << __s;
516e78f53d1SNikolas Klauser        *__first.__seg_ |= __b2 >> __s;
517e78f53d1SNikolas Klauser      } else {
518e78f53d1SNikolas Klauser        unsigned __s = __first.__ctz_ - __result.__ctz_;
519e78f53d1SNikolas Klauser        *__result.__seg_ |= __b1 >> __s;
520e78f53d1SNikolas Klauser        *__first.__seg_ |= __b2 << __s;
521e78f53d1SNikolas Klauser      }
522e78f53d1SNikolas Klauser      __result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word;
523e78f53d1SNikolas Klauser      __result.__ctz_ = static_cast<unsigned>((__ddn + __result.__ctz_) % __bits_per_word);
524e78f53d1SNikolas Klauser      __dn -= __ddn;
525e78f53d1SNikolas Klauser      if (__dn > 0) {
526e78f53d1SNikolas Klauser        __m  = ~__storage_type(0) >> (__bits_per_word - __dn);
527e78f53d1SNikolas Klauser        __b2 = *__result.__seg_ & __m;
528e78f53d1SNikolas Klauser        *__result.__seg_ &= ~__m;
529e78f53d1SNikolas Klauser        unsigned __s = __first.__ctz_ + __ddn;
530e78f53d1SNikolas Klauser        *__result.__seg_ |= __b1 >> __s;
531e78f53d1SNikolas Klauser        *__first.__seg_ |= __b2 << __s;
532e78f53d1SNikolas Klauser        __result.__ctz_ = static_cast<unsigned>(__dn);
533e78f53d1SNikolas Klauser      }
534e78f53d1SNikolas Klauser      ++__first.__seg_;
535e78f53d1SNikolas Klauser      // __first.__ctz_ = 0;
536e78f53d1SNikolas Klauser    }
537e78f53d1SNikolas Klauser    // __first.__ctz_ == 0;
538e78f53d1SNikolas Klauser    // do middle words
539e78f53d1SNikolas Klauser    __storage_type __m = ~__storage_type(0) << __result.__ctz_;
540e78f53d1SNikolas Klauser    unsigned __clz_r   = __bits_per_word - __result.__ctz_;
541e78f53d1SNikolas Klauser    for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) {
542e78f53d1SNikolas Klauser      __storage_type __b1 = *__first.__seg_;
543e78f53d1SNikolas Klauser      __storage_type __b2 = *__result.__seg_ & __m;
544e78f53d1SNikolas Klauser      *__result.__seg_ &= ~__m;
545e78f53d1SNikolas Klauser      *__result.__seg_ |= __b1 << __result.__ctz_;
546e78f53d1SNikolas Klauser      *__first.__seg_ = __b2 >> __result.__ctz_;
547e78f53d1SNikolas Klauser      ++__result.__seg_;
548e78f53d1SNikolas Klauser      __b2 = *__result.__seg_ & ~__m;
549e78f53d1SNikolas Klauser      *__result.__seg_ &= __m;
550e78f53d1SNikolas Klauser      *__result.__seg_ |= __b1 >> __clz_r;
551e78f53d1SNikolas Klauser      *__first.__seg_ |= __b2 << __clz_r;
552e78f53d1SNikolas Klauser    }
553e78f53d1SNikolas Klauser    // do last word
554e78f53d1SNikolas Klauser    if (__n > 0) {
555e78f53d1SNikolas Klauser      __m                 = ~__storage_type(0) >> (__bits_per_word - __n);
556e78f53d1SNikolas Klauser      __storage_type __b1 = *__first.__seg_ & __m;
557e78f53d1SNikolas Klauser      *__first.__seg_ &= ~__m;
558e78f53d1SNikolas Klauser      __storage_type __dn = std::min<__storage_type>(__n, __clz_r);
559e78f53d1SNikolas Klauser      __m                 = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn));
560e78f53d1SNikolas Klauser      __storage_type __b2 = *__result.__seg_ & __m;
561e78f53d1SNikolas Klauser      *__result.__seg_ &= ~__m;
562e78f53d1SNikolas Klauser      *__result.__seg_ |= __b1 << __result.__ctz_;
563e78f53d1SNikolas Klauser      *__first.__seg_ |= __b2 >> __result.__ctz_;
564e78f53d1SNikolas Klauser      __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
565e78f53d1SNikolas Klauser      __result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
566e78f53d1SNikolas Klauser      __n -= __dn;
567e78f53d1SNikolas Klauser      if (__n > 0) {
568e78f53d1SNikolas Klauser        __m  = ~__storage_type(0) >> (__bits_per_word - __n);
569e78f53d1SNikolas Klauser        __b2 = *__result.__seg_ & __m;
570e78f53d1SNikolas Klauser        *__result.__seg_ &= ~__m;
571e78f53d1SNikolas Klauser        *__result.__seg_ |= __b1 >> __dn;
572e78f53d1SNikolas Klauser        *__first.__seg_ |= __b2 << __dn;
573e78f53d1SNikolas Klauser        __result.__ctz_ = static_cast<unsigned>(__n);
574e78f53d1SNikolas Klauser      }
575e78f53d1SNikolas Klauser    }
576e78f53d1SNikolas Klauser  }
577e78f53d1SNikolas Klauser  return __result;
578e78f53d1SNikolas Klauser}
579e78f53d1SNikolas Klauser
580e78f53d1SNikolas Klausertemplate <class _Cl, class _Cr>
581e78f53d1SNikolas Klauserinline _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cr, false> swap_ranges(
582e78f53d1SNikolas Klauser    __bit_iterator<_Cl, false> __first1, __bit_iterator<_Cl, false> __last1, __bit_iterator<_Cr, false> __first2) {
583e78f53d1SNikolas Klauser  if (__first1.__ctz_ == __first2.__ctz_)
584e78f53d1SNikolas Klauser    return std::__swap_ranges_aligned(__first1, __last1, __first2);
585e78f53d1SNikolas Klauser  return std::__swap_ranges_unaligned(__first1, __last1, __first2);
586e78f53d1SNikolas Klauser}
587e78f53d1SNikolas Klauser
588e78f53d1SNikolas Klauser// rotate
589e78f53d1SNikolas Klauser
590e78f53d1SNikolas Klausertemplate <class _Cp>
591e78f53d1SNikolas Klauserstruct __bit_array {
592e78f53d1SNikolas Klauser  using difference_type   = typename _Cp::difference_type;
593e78f53d1SNikolas Klauser  using __storage_type    = typename _Cp::__storage_type;
594e78f53d1SNikolas Klauser  using __storage_pointer = typename _Cp::__storage_pointer;
595e78f53d1SNikolas Klauser  using iterator          = typename _Cp::iterator;
596e78f53d1SNikolas Klauser
597e78f53d1SNikolas Klauser  static const unsigned __bits_per_word = _Cp::__bits_per_word;
598e78f53d1SNikolas Klauser  static const unsigned _Np             = 4;
599e78f53d1SNikolas Klauser
600e78f53d1SNikolas Klauser  difference_type __size_;
601e78f53d1SNikolas Klauser  __storage_type __word_[_Np];
602e78f53d1SNikolas Klauser
603e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static difference_type capacity() {
604e78f53d1SNikolas Klauser    return static_cast<difference_type>(_Np * __bits_per_word);
605e78f53d1SNikolas Klauser  }
606e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bit_array(difference_type __s) : __size_(__s) {
607e78f53d1SNikolas Klauser    if (__libcpp_is_constant_evaluated()) {
608e78f53d1SNikolas Klauser      for (size_t __i = 0; __i != __bit_array<_Cp>::_Np; ++__i)
609e78f53d1SNikolas Klauser        std::__construct_at(__word_ + __i, 0);
610e78f53d1SNikolas Klauser    }
611e78f53d1SNikolas Klauser  }
612e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator begin() {
613e78f53d1SNikolas Klauser    return iterator(pointer_traits<__storage_pointer>::pointer_to(__word_[0]), 0);
614e78f53d1SNikolas Klauser  }
615e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator end() {
616e78f53d1SNikolas Klauser    return iterator(pointer_traits<__storage_pointer>::pointer_to(__word_[0]) + __size_ / __bits_per_word,
617e78f53d1SNikolas Klauser                    static_cast<unsigned>(__size_ % __bits_per_word));
618e78f53d1SNikolas Klauser  }
619e78f53d1SNikolas Klauser};
620e78f53d1SNikolas Klauser
621e78f53d1SNikolas Klausertemplate <class _Cp>
622e78f53d1SNikolas Klauser_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false>
623e78f53d1SNikolas Klauserrotate(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __middle, __bit_iterator<_Cp, false> __last) {
624e78f53d1SNikolas Klauser  using _I1             = __bit_iterator<_Cp, false>;
625e78f53d1SNikolas Klauser  using difference_type = typename _I1::difference_type;
626e78f53d1SNikolas Klauser
627e78f53d1SNikolas Klauser  difference_type __d1 = __middle - __first;
628e78f53d1SNikolas Klauser  difference_type __d2 = __last - __middle;
629e78f53d1SNikolas Klauser  _I1 __r              = __first + __d2;
630e78f53d1SNikolas Klauser  while (__d1 != 0 && __d2 != 0) {
631e78f53d1SNikolas Klauser    if (__d1 <= __d2) {
632e78f53d1SNikolas Klauser      if (__d1 <= __bit_array<_Cp>::capacity()) {
633e78f53d1SNikolas Klauser        __bit_array<_Cp> __b(__d1);
634e78f53d1SNikolas Klauser        std::copy(__first, __middle, __b.begin());
635e78f53d1SNikolas Klauser        std::copy(__b.begin(), __b.end(), std::copy(__middle, __last, __first));
636e78f53d1SNikolas Klauser        break;
637e78f53d1SNikolas Klauser      } else {
638e78f53d1SNikolas Klauser        __bit_iterator<_Cp, false> __mp = std::swap_ranges(__first, __middle, __middle);
639e78f53d1SNikolas Klauser        __first                         = __middle;
640e78f53d1SNikolas Klauser        __middle                        = __mp;
641e78f53d1SNikolas Klauser        __d2 -= __d1;
642e78f53d1SNikolas Klauser      }
643e78f53d1SNikolas Klauser    } else {
644e78f53d1SNikolas Klauser      if (__d2 <= __bit_array<_Cp>::capacity()) {
645e78f53d1SNikolas Klauser        __bit_array<_Cp> __b(__d2);
646e78f53d1SNikolas Klauser        std::copy(__middle, __last, __b.begin());
647e78f53d1SNikolas Klauser        std::copy_backward(__b.begin(), __b.end(), std::copy_backward(__first, __middle, __last));
648e78f53d1SNikolas Klauser        break;
649e78f53d1SNikolas Klauser      } else {
650e78f53d1SNikolas Klauser        __bit_iterator<_Cp, false> __mp = __first + __d2;
651e78f53d1SNikolas Klauser        std::swap_ranges(__first, __mp, __middle);
652e78f53d1SNikolas Klauser        __first = __mp;
653e78f53d1SNikolas Klauser        __d1 -= __d2;
654e78f53d1SNikolas Klauser      }
655e78f53d1SNikolas Klauser    }
656e78f53d1SNikolas Klauser  }
657e78f53d1SNikolas Klauser  return __r;
658e78f53d1SNikolas Klauser}
659e78f53d1SNikolas Klauser
660e78f53d1SNikolas Klauser// equal
661e78f53d1SNikolas Klauser
662e78f53d1SNikolas Klausertemplate <class _Cp, bool _IC1, bool _IC2>
663e78f53d1SNikolas Klauser_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __equal_unaligned(
664e78f53d1SNikolas Klauser    __bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) {
665e78f53d1SNikolas Klauser  using _It             = __bit_iterator<_Cp, _IC1>;
666e78f53d1SNikolas Klauser  using difference_type = typename _It::difference_type;
667e78f53d1SNikolas Klauser  using __storage_type  = typename _It::__storage_type;
668e78f53d1SNikolas Klauser
669e78f53d1SNikolas Klauser  const int __bits_per_word = _It::__bits_per_word;
670e78f53d1SNikolas Klauser  difference_type __n       = __last1 - __first1;
671e78f53d1SNikolas Klauser  if (__n > 0) {
672e78f53d1SNikolas Klauser    // do first word
673e78f53d1SNikolas Klauser    if (__first1.__ctz_ != 0) {
674e78f53d1SNikolas Klauser      unsigned __clz_f     = __bits_per_word - __first1.__ctz_;
675e78f53d1SNikolas Klauser      difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n);
676e78f53d1SNikolas Klauser      __n -= __dn;
677e78f53d1SNikolas Klauser      __storage_type __m   = (~__storage_type(0) << __first1.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
678e78f53d1SNikolas Klauser      __storage_type __b   = *__first1.__seg_ & __m;
679e78f53d1SNikolas Klauser      unsigned __clz_r     = __bits_per_word - __first2.__ctz_;
680e78f53d1SNikolas Klauser      __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
681e78f53d1SNikolas Klauser      __m                  = (~__storage_type(0) << __first2.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn));
682e78f53d1SNikolas Klauser      if (__first2.__ctz_ > __first1.__ctz_) {
683e78f53d1SNikolas Klauser        if ((*__first2.__seg_ & __m) != (__b << (__first2.__ctz_ - __first1.__ctz_)))
684e78f53d1SNikolas Klauser          return false;
685e78f53d1SNikolas Klauser      } else {
686e78f53d1SNikolas Klauser        if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ - __first2.__ctz_)))
687e78f53d1SNikolas Klauser          return false;
688e78f53d1SNikolas Klauser      }
689e78f53d1SNikolas Klauser      __first2.__seg_ += (__ddn + __first2.__ctz_) / __bits_per_word;
690e78f53d1SNikolas Klauser      __first2.__ctz_ = static_cast<unsigned>((__ddn + __first2.__ctz_) % __bits_per_word);
691e78f53d1SNikolas Klauser      __dn -= __ddn;
692e78f53d1SNikolas Klauser      if (__dn > 0) {
693e78f53d1SNikolas Klauser        __m = ~__storage_type(0) >> (__bits_per_word - __dn);
694e78f53d1SNikolas Klauser        if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ + __ddn)))
695e78f53d1SNikolas Klauser          return false;
696e78f53d1SNikolas Klauser        __first2.__ctz_ = static_cast<unsigned>(__dn);
697e78f53d1SNikolas Klauser      }
698e78f53d1SNikolas Klauser      ++__first1.__seg_;
699e78f53d1SNikolas Klauser      // __first1.__ctz_ = 0;
700e78f53d1SNikolas Klauser    }
701e78f53d1SNikolas Klauser    // __first1.__ctz_ == 0;
702e78f53d1SNikolas Klauser    // do middle words
703e78f53d1SNikolas Klauser    unsigned __clz_r   = __bits_per_word - __first2.__ctz_;
704e78f53d1SNikolas Klauser    __storage_type __m = ~__storage_type(0) << __first2.__ctz_;
705e78f53d1SNikolas Klauser    for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_) {
706e78f53d1SNikolas Klauser      __storage_type __b = *__first1.__seg_;
707e78f53d1SNikolas Klauser      if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_))
708e78f53d1SNikolas Klauser        return false;
709e78f53d1SNikolas Klauser      ++__first2.__seg_;
710e78f53d1SNikolas Klauser      if ((*__first2.__seg_ & ~__m) != (__b >> __clz_r))
711e78f53d1SNikolas Klauser        return false;
712e78f53d1SNikolas Klauser    }
713e78f53d1SNikolas Klauser    // do last word
714e78f53d1SNikolas Klauser    if (__n > 0) {
715e78f53d1SNikolas Klauser      __m                 = ~__storage_type(0) >> (__bits_per_word - __n);
716e78f53d1SNikolas Klauser      __storage_type __b  = *__first1.__seg_ & __m;
717e78f53d1SNikolas Klauser      __storage_type __dn = std::min(__n, static_cast<difference_type>(__clz_r));
718e78f53d1SNikolas Klauser      __m                 = (~__storage_type(0) << __first2.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn));
719e78f53d1SNikolas Klauser      if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_))
720e78f53d1SNikolas Klauser        return false;
721e78f53d1SNikolas Klauser      __first2.__seg_ += (__dn + __first2.__ctz_) / __bits_per_word;
722e78f53d1SNikolas Klauser      __first2.__ctz_ = static_cast<unsigned>((__dn + __first2.__ctz_) % __bits_per_word);
723e78f53d1SNikolas Klauser      __n -= __dn;
724e78f53d1SNikolas Klauser      if (__n > 0) {
725e78f53d1SNikolas Klauser        __m = ~__storage_type(0) >> (__bits_per_word - __n);
726e78f53d1SNikolas Klauser        if ((*__first2.__seg_ & __m) != (__b >> __dn))
727e78f53d1SNikolas Klauser          return false;
728e78f53d1SNikolas Klauser      }
729e78f53d1SNikolas Klauser    }
730e78f53d1SNikolas Klauser  }
731e78f53d1SNikolas Klauser  return true;
732e78f53d1SNikolas Klauser}
733e78f53d1SNikolas Klauser
734e78f53d1SNikolas Klausertemplate <class _Cp, bool _IC1, bool _IC2>
735e78f53d1SNikolas Klauser_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __equal_aligned(
736e78f53d1SNikolas Klauser    __bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) {
737e78f53d1SNikolas Klauser  using _It             = __bit_iterator<_Cp, _IC1>;
738e78f53d1SNikolas Klauser  using difference_type = typename _It::difference_type;
739e78f53d1SNikolas Klauser  using __storage_type  = typename _It::__storage_type;
740e78f53d1SNikolas Klauser
741e78f53d1SNikolas Klauser  const int __bits_per_word = _It::__bits_per_word;
742e78f53d1SNikolas Klauser  difference_type __n       = __last1 - __first1;
743e78f53d1SNikolas Klauser  if (__n > 0) {
744e78f53d1SNikolas Klauser    // do first word
745e78f53d1SNikolas Klauser    if (__first1.__ctz_ != 0) {
746e78f53d1SNikolas Klauser      unsigned __clz       = __bits_per_word - __first1.__ctz_;
747e78f53d1SNikolas Klauser      difference_type __dn = std::min(static_cast<difference_type>(__clz), __n);
748e78f53d1SNikolas Klauser      __n -= __dn;
749e78f53d1SNikolas Klauser      __storage_type __m = (~__storage_type(0) << __first1.__ctz_) & (~__storage_type(0) >> (__clz - __dn));
750e78f53d1SNikolas Klauser      if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m))
751e78f53d1SNikolas Klauser        return false;
752e78f53d1SNikolas Klauser      ++__first2.__seg_;
753e78f53d1SNikolas Klauser      ++__first1.__seg_;
754e78f53d1SNikolas Klauser      // __first1.__ctz_ = 0;
755e78f53d1SNikolas Klauser      // __first2.__ctz_ = 0;
756e78f53d1SNikolas Klauser    }
757e78f53d1SNikolas Klauser    // __first1.__ctz_ == 0;
758e78f53d1SNikolas Klauser    // __first2.__ctz_ == 0;
759e78f53d1SNikolas Klauser    // do middle words
760e78f53d1SNikolas Klauser    for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_, ++__first2.__seg_)
761e78f53d1SNikolas Klauser      if (*__first2.__seg_ != *__first1.__seg_)
762e78f53d1SNikolas Klauser        return false;
763e78f53d1SNikolas Klauser    // do last word
764e78f53d1SNikolas Klauser    if (__n > 0) {
765e78f53d1SNikolas Klauser      __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
766e78f53d1SNikolas Klauser      if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m))
767e78f53d1SNikolas Klauser        return false;
768e78f53d1SNikolas Klauser    }
769e78f53d1SNikolas Klauser  }
770e78f53d1SNikolas Klauser  return true;
771e78f53d1SNikolas Klauser}
772e78f53d1SNikolas Klauser
773e78f53d1SNikolas Klausertemplate <class _Cp, bool _IC1, bool _IC2>
774e78f53d1SNikolas Klauserinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
775e78f53d1SNikolas Klauserequal(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) {
776e78f53d1SNikolas Klauser  if (__first1.__ctz_ == __first2.__ctz_)
777e78f53d1SNikolas Klauser    return std::__equal_aligned(__first1, __last1, __first2);
778e78f53d1SNikolas Klauser  return std::__equal_unaligned(__first1, __last1, __first2);
779e78f53d1SNikolas Klauser}
780e78f53d1SNikolas Klauser
781e78f53d1SNikolas Klausertemplate <class _Cp, bool _IsConst, typename _Cp::__storage_type>
782e78f53d1SNikolas Klauserclass __bit_iterator {
783e78f53d1SNikolas Klauserpublic:
784e78f53d1SNikolas Klauser  using difference_type = typename _Cp::difference_type;
785e78f53d1SNikolas Klauser  using value_type      = bool;
786e78f53d1SNikolas Klauser  using pointer         = __bit_iterator;
787e78f53d1SNikolas Klauser#ifndef _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL
788e78f53d1SNikolas Klauser  using reference = __conditional_t<_IsConst, __bit_const_reference<_Cp>, __bit_reference<_Cp> >;
789e78f53d1SNikolas Klauser#else
790e78f53d1SNikolas Klauser  using reference = __conditional_t<_IsConst, bool, __bit_reference<_Cp> >;
791e78f53d1SNikolas Klauser#endif
792e78f53d1SNikolas Klauser  using iterator_category = random_access_iterator_tag;
793e78f53d1SNikolas Klauser
794e78f53d1SNikolas Klauserprivate:
795e78f53d1SNikolas Klauser  using __storage_type = typename _Cp::__storage_type;
796e78f53d1SNikolas Klauser  using __storage_pointer =
797e78f53d1SNikolas Klauser      __conditional_t<_IsConst, typename _Cp::__const_storage_pointer, typename _Cp::__storage_pointer>;
798e78f53d1SNikolas Klauser
799e78f53d1SNikolas Klauser  static const unsigned __bits_per_word = _Cp::__bits_per_word;
800e78f53d1SNikolas Klauser
801e78f53d1SNikolas Klauser  __storage_pointer __seg_;
802e78f53d1SNikolas Klauser  unsigned __ctz_;
803e78f53d1SNikolas Klauser
804e78f53d1SNikolas Klauserpublic:
805e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator() _NOEXCEPT
806e78f53d1SNikolas Klauser#if _LIBCPP_STD_VER >= 14
807e78f53d1SNikolas Klauser      : __seg_(nullptr),
808e78f53d1SNikolas Klauser        __ctz_(0)
809e78f53d1SNikolas Klauser#endif
810e78f53d1SNikolas Klauser  {
811e78f53d1SNikolas Klauser  }
812e78f53d1SNikolas Klauser
813e78f53d1SNikolas Klauser  // When _IsConst=false, this is the copy constructor.
814e78f53d1SNikolas Klauser  // It is non-trivial. Making it trivial would break ABI.
815e78f53d1SNikolas Klauser  // When _IsConst=true, this is a converting constructor;
816e78f53d1SNikolas Klauser  // the copy and move constructors are implicitly generated
817e78f53d1SNikolas Klauser  // and trivial.
818e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator(const __bit_iterator<_Cp, false>& __it) _NOEXCEPT
819e78f53d1SNikolas Klauser      : __seg_(__it.__seg_),
820e78f53d1SNikolas Klauser        __ctz_(__it.__ctz_) {}
821e78f53d1SNikolas Klauser
822e78f53d1SNikolas Klauser  // When _IsConst=false, we have a user-provided copy constructor,
823e78f53d1SNikolas Klauser  // so we must also provide a copy assignment operator because
824e78f53d1SNikolas Klauser  // the implicit generation of a defaulted one is deprecated.
825e78f53d1SNikolas Klauser  // When _IsConst=true, the assignment operators are
826e78f53d1SNikolas Klauser  // implicitly generated and trivial.
827e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator&
828e78f53d1SNikolas Klauser  operator=(const _If<_IsConst, struct __private_nat, __bit_iterator>& __it) {
829e78f53d1SNikolas Klauser    __seg_ = __it.__seg_;
830e78f53d1SNikolas Klauser    __ctz_ = __it.__ctz_;
831e78f53d1SNikolas Klauser    return *this;
832e78f53d1SNikolas Klauser  }
833e78f53d1SNikolas Klauser
834e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator*() const _NOEXCEPT {
835e78f53d1SNikolas Klauser    return __conditional_t<_IsConst, __bit_const_reference<_Cp>, __bit_reference<_Cp> >(
836e78f53d1SNikolas Klauser        __seg_, __storage_type(1) << __ctz_);
837e78f53d1SNikolas Klauser  }
838e78f53d1SNikolas Klauser
839e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator& operator++() {
840e78f53d1SNikolas Klauser    if (__ctz_ != __bits_per_word - 1)
841e78f53d1SNikolas Klauser      ++__ctz_;
842e78f53d1SNikolas Klauser    else {
843e78f53d1SNikolas Klauser      __ctz_ = 0;
844e78f53d1SNikolas Klauser      ++__seg_;
845e78f53d1SNikolas Klauser    }
846e78f53d1SNikolas Klauser    return *this;
847e78f53d1SNikolas Klauser  }
848e78f53d1SNikolas Klauser
849e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator operator++(int) {
850e78f53d1SNikolas Klauser    __bit_iterator __tmp = *this;
851e78f53d1SNikolas Klauser    ++(*this);
852e78f53d1SNikolas Klauser    return __tmp;
853e78f53d1SNikolas Klauser  }
854e78f53d1SNikolas Klauser
855e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator& operator--() {
856e78f53d1SNikolas Klauser    if (__ctz_ != 0)
857e78f53d1SNikolas Klauser      --__ctz_;
858e78f53d1SNikolas Klauser    else {
859e78f53d1SNikolas Klauser      __ctz_ = __bits_per_word - 1;
860e78f53d1SNikolas Klauser      --__seg_;
861e78f53d1SNikolas Klauser    }
862e78f53d1SNikolas Klauser    return *this;
863e78f53d1SNikolas Klauser  }
864e78f53d1SNikolas Klauser
865e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator operator--(int) {
866e78f53d1SNikolas Klauser    __bit_iterator __tmp = *this;
867e78f53d1SNikolas Klauser    --(*this);
868e78f53d1SNikolas Klauser    return __tmp;
869e78f53d1SNikolas Klauser  }
870e78f53d1SNikolas Klauser
871e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator& operator+=(difference_type __n) {
872e78f53d1SNikolas Klauser    if (__n >= 0)
873e78f53d1SNikolas Klauser      __seg_ += (__n + __ctz_) / __bits_per_word;
874e78f53d1SNikolas Klauser    else
875e78f53d1SNikolas Klauser      __seg_ += static_cast<difference_type>(__n - __bits_per_word + __ctz_ + 1) /
876e78f53d1SNikolas Klauser                static_cast<difference_type>(__bits_per_word);
877e78f53d1SNikolas Klauser    __n &= (__bits_per_word - 1);
878e78f53d1SNikolas Klauser    __ctz_ = static_cast<unsigned>((__n + __ctz_) % __bits_per_word);
879e78f53d1SNikolas Klauser    return *this;
880e78f53d1SNikolas Klauser  }
881e78f53d1SNikolas Klauser
882e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator& operator-=(difference_type __n) {
883e78f53d1SNikolas Klauser    return *this += -__n;
884e78f53d1SNikolas Klauser  }
885e78f53d1SNikolas Klauser
886e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator operator+(difference_type __n) const {
887e78f53d1SNikolas Klauser    __bit_iterator __t(*this);
888e78f53d1SNikolas Klauser    __t += __n;
889e78f53d1SNikolas Klauser    return __t;
890e78f53d1SNikolas Klauser  }
891e78f53d1SNikolas Klauser
892e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator operator-(difference_type __n) const {
893e78f53d1SNikolas Klauser    __bit_iterator __t(*this);
894e78f53d1SNikolas Klauser    __t -= __n;
895e78f53d1SNikolas Klauser    return __t;
896e78f53d1SNikolas Klauser  }
897e78f53d1SNikolas Klauser
898e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator
899e78f53d1SNikolas Klauser  operator+(difference_type __n, const __bit_iterator& __it) {
900e78f53d1SNikolas Klauser    return __it + __n;
901e78f53d1SNikolas Klauser  }
902e78f53d1SNikolas Klauser
903e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend difference_type
904e78f53d1SNikolas Klauser  operator-(const __bit_iterator& __x, const __bit_iterator& __y) {
905e78f53d1SNikolas Klauser    return (__x.__seg_ - __y.__seg_) * __bits_per_word + __x.__ctz_ - __y.__ctz_;
906e78f53d1SNikolas Klauser  }
907e78f53d1SNikolas Klauser
908e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator[](difference_type __n) const {
909e78f53d1SNikolas Klauser    return *(*this + __n);
910e78f53d1SNikolas Klauser  }
911e78f53d1SNikolas Klauser
912e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
913e78f53d1SNikolas Klauser  operator==(const __bit_iterator& __x, const __bit_iterator& __y) {
914e78f53d1SNikolas Klauser    return __x.__seg_ == __y.__seg_ && __x.__ctz_ == __y.__ctz_;
915e78f53d1SNikolas Klauser  }
916e78f53d1SNikolas Klauser
917e78f53d1SNikolas Klauser#if _LIBCPP_STD_VER <= 17
918e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
919e78f53d1SNikolas Klauser  operator!=(const __bit_iterator& __x, const __bit_iterator& __y) {
920e78f53d1SNikolas Klauser    return !(__x == __y);
921e78f53d1SNikolas Klauser  }
922e78f53d1SNikolas Klauser
923e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
924e78f53d1SNikolas Klauser  operator<(const __bit_iterator& __x, const __bit_iterator& __y) {
925e78f53d1SNikolas Klauser    return __x.__seg_ < __y.__seg_ || (__x.__seg_ == __y.__seg_ && __x.__ctz_ < __y.__ctz_);
926e78f53d1SNikolas Klauser  }
927e78f53d1SNikolas Klauser
928e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
929e78f53d1SNikolas Klauser  operator>(const __bit_iterator& __x, const __bit_iterator& __y) {
930e78f53d1SNikolas Klauser    return __y < __x;
931e78f53d1SNikolas Klauser  }
932e78f53d1SNikolas Klauser
933e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
934e78f53d1SNikolas Klauser  operator<=(const __bit_iterator& __x, const __bit_iterator& __y) {
935e78f53d1SNikolas Klauser    return !(__y < __x);
936e78f53d1SNikolas Klauser  }
937e78f53d1SNikolas Klauser
938e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
939e78f53d1SNikolas Klauser  operator>=(const __bit_iterator& __x, const __bit_iterator& __y) {
940e78f53d1SNikolas Klauser    return !(__x < __y);
941e78f53d1SNikolas Klauser  }
942e78f53d1SNikolas Klauser#else  // _LIBCPP_STD_VER <= 17
943e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI constexpr friend strong_ordering
944e78f53d1SNikolas Klauser  operator<=>(const __bit_iterator& __x, const __bit_iterator& __y) {
945e78f53d1SNikolas Klauser    if (__x.__seg_ < __y.__seg_)
946e78f53d1SNikolas Klauser      return strong_ordering::less;
947e78f53d1SNikolas Klauser
948e78f53d1SNikolas Klauser    if (__x.__seg_ == __y.__seg_)
949e78f53d1SNikolas Klauser      return __x.__ctz_ <=> __y.__ctz_;
950e78f53d1SNikolas Klauser
951e78f53d1SNikolas Klauser    return strong_ordering::greater;
952e78f53d1SNikolas Klauser  }
953e78f53d1SNikolas Klauser#endif // _LIBCPP_STD_VER <= 17
954e78f53d1SNikolas Klauser
955e78f53d1SNikolas Klauserprivate:
956e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
957e78f53d1SNikolas Klauser  _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bit_iterator(__storage_pointer __s, unsigned __ctz) _NOEXCEPT
958e78f53d1SNikolas Klauser      : __seg_(__s),
959e78f53d1SNikolas Klauser        __ctz_(__ctz) {}
960e78f53d1SNikolas Klauser
961e78f53d1SNikolas Klauser  friend typename _Cp::__self;
962e78f53d1SNikolas Klauser
963e78f53d1SNikolas Klauser  friend class __bit_reference<_Cp>;
964e78f53d1SNikolas Klauser  friend class __bit_const_reference<_Cp>;
965e78f53d1SNikolas Klauser  friend class __bit_iterator<_Cp, true>;
966e78f53d1SNikolas Klauser  template <class _Dp>
967e78f53d1SNikolas Klauser  friend struct __bit_array;
968e78f53d1SNikolas Klauser
969e78f53d1SNikolas Klauser  template <bool _FillVal, class _Dp>
970e78f53d1SNikolas Klauser  _LIBCPP_CONSTEXPR_SINCE_CXX20 friend void
971e78f53d1SNikolas Klauser  __fill_n_bool(__bit_iterator<_Dp, false> __first, typename _Dp::size_type __n);
972e78f53d1SNikolas Klauser
973e78f53d1SNikolas Klauser  template <class _Dp, bool _IC>
974e78f53d1SNikolas Klauser  _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_aligned(
975e78f53d1SNikolas Klauser      __bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
976e78f53d1SNikolas Klauser  template <class _Dp, bool _IC>
977e78f53d1SNikolas Klauser  _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_unaligned(
978e78f53d1SNikolas Klauser      __bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
979e78f53d1SNikolas Klauser  template <class _Dp, bool _IC>
980e78f53d1SNikolas Klauser  _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false>
981e78f53d1SNikolas Klauser  copy(__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
982e78f53d1SNikolas Klauser  template <class _Dp, bool _IC>
983e78f53d1SNikolas Klauser  _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_backward_aligned(
984e78f53d1SNikolas Klauser      __bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
985e78f53d1SNikolas Klauser  template <class _Dp, bool _IC>
986e78f53d1SNikolas Klauser  _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_backward_unaligned(
987e78f53d1SNikolas Klauser      __bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
988e78f53d1SNikolas Klauser  template <class _Dp, bool _IC>
989e78f53d1SNikolas Klauser  _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false>
990e78f53d1SNikolas Klauser  copy_backward(__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
991e78f53d1SNikolas Klauser  template <class _Cl, class _Cr>
992e78f53d1SNikolas Klauser  friend __bit_iterator<_Cr, false>
993e78f53d1SNikolas Klauser      __swap_ranges_aligned(__bit_iterator<_Cl, false>, __bit_iterator<_Cl, false>, __bit_iterator<_Cr, false>);
994e78f53d1SNikolas Klauser  template <class _Cl, class _Cr>
995e78f53d1SNikolas Klauser  friend __bit_iterator<_Cr, false>
996e78f53d1SNikolas Klauser      __swap_ranges_unaligned(__bit_iterator<_Cl, false>, __bit_iterator<_Cl, false>, __bit_iterator<_Cr, false>);
997e78f53d1SNikolas Klauser  template <class _Cl, class _Cr>
998e78f53d1SNikolas Klauser  friend __bit_iterator<_Cr, false>
999e78f53d1SNikolas Klauser      swap_ranges(__bit_iterator<_Cl, false>, __bit_iterator<_Cl, false>, __bit_iterator<_Cr, false>);
1000e78f53d1SNikolas Klauser  template <class _Dp>
1001e78f53d1SNikolas Klauser  _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false>
1002e78f53d1SNikolas Klauser      rotate(__bit_iterator<_Dp, false>, __bit_iterator<_Dp, false>, __bit_iterator<_Dp, false>);
1003e78f53d1SNikolas Klauser  template <class _Dp, bool _IC1, bool _IC2>
1004e78f53d1SNikolas Klauser  _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
1005e78f53d1SNikolas Klauser      __equal_aligned(__bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC2>);
1006e78f53d1SNikolas Klauser  template <class _Dp, bool _IC1, bool _IC2>
1007e78f53d1SNikolas Klauser  _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
1008e78f53d1SNikolas Klauser      __equal_unaligned(__bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC2>);
1009e78f53d1SNikolas Klauser  template <class _Dp, bool _IC1, bool _IC2>
1010e78f53d1SNikolas Klauser  _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
1011e78f53d1SNikolas Klauser      equal(__bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC2>);
1012e78f53d1SNikolas Klauser  template <bool _ToFind, class _Dp, bool _IC>
1013e78f53d1SNikolas Klauser  _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, _IC>
1014e78f53d1SNikolas Klauser      __find_bool(__bit_iterator<_Dp, _IC>, typename _Dp::size_type);
1015e78f53d1SNikolas Klauser  template <bool _ToCount, class _Dp, bool _IC>
1016e78f53d1SNikolas Klauser  friend typename __bit_iterator<_Dp, _IC>::difference_type _LIBCPP_HIDE_FROM_ABI
1017e78f53d1SNikolas Klauser  _LIBCPP_CONSTEXPR_SINCE_CXX20 __count_bool(__bit_iterator<_Dp, _IC>, typename _Dp::size_type);
1018e78f53d1SNikolas Klauser};
1019e78f53d1SNikolas Klauser
1020e78f53d1SNikolas Klauser_LIBCPP_END_NAMESPACE_STD
1021e78f53d1SNikolas Klauser
1022e78f53d1SNikolas Klauser_LIBCPP_POP_MACROS
1023e78f53d1SNikolas Klauser
1024*ce777190SNikolas Klauser#endif // _LIBCPP___CXX03___BIT_REFERENCE
1025