sparrow 0.3.0
Loading...
Searching...
No Matches
bitset_iterator.hpp
Go to the documentation of this file.
1// Copyright 2024 Man Group Operations Limited
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#pragma once
16
20
21namespace sparrow
22{
23 template <class B>
24 class bitset_reference;
25
36 template <class B, bool is_const>
38 bitset_iterator<B, is_const>,
39 mpl::constify_t<typename B::value_type, is_const>,
40 std::random_access_iterator_tag,
41 std::conditional_t<is_const, bool, bitset_reference<B>>>
42 {
43 public:
44
49 std::contiguous_iterator_tag,
50 std::conditional_t<is_const, bool, bitset_reference<B>>>;
51 using reference = typename base_type::reference;
52 using difference_type = typename base_type::difference_type;
53
56 using size_type = typename B::size_type;
57
58 constexpr bitset_iterator() noexcept = default;
59 constexpr bitset_iterator(bitset_type* bitset, block_type* block, size_type index);
60
61 private:
62
63 constexpr reference dereference() const noexcept;
64 constexpr void increment();
65 constexpr void decrement();
66 constexpr void advance(difference_type n);
67 [[nodiscard]] constexpr difference_type distance_to(const self_type& rhs) const noexcept;
68 [[nodiscard]] constexpr bool equal(const self_type& rhs) const noexcept;
69 [[nodiscard]] constexpr bool less_than(const self_type& rhs) const noexcept;
70
71 [[nodiscard]] constexpr bool is_first_bit_of_block(size_type index) const noexcept;
72 [[nodiscard]] constexpr difference_type distance_to_begin() const;
73
74 bitset_type* p_bitset = nullptr;
75 block_type* p_block = nullptr;
76 // m_index is block-local index.
77 // Invariant: m_index < bitset_type::s_bits_per_block
78 size_type m_index;
79
80 friend class iterator_access;
81 };
82
83 template <class B, bool is_const>
84 constexpr bitset_iterator<B, is_const>::bitset_iterator(bitset_type* bitset, block_type* block, size_type index)
85 : p_bitset(bitset)
86 , p_block(block)
87 , m_index(index)
88 {
89 SPARROW_ASSERT_TRUE(m_index < bitset_type::s_bits_per_block);
90 }
91
92 template <class B, bool is_const>
93 constexpr auto bitset_iterator<B, is_const>::dereference() const noexcept -> reference
94 {
95 if constexpr (is_const)
96 {
97 if (p_bitset->data() == nullptr)
98 {
99 return true;
100 }
101 return (*p_block) & bitset_type::bit_mask(m_index);
102 }
103 else
104 {
105 return bitset_reference<B>(*p_bitset, *p_block, bitset_type::bit_mask(m_index));
106 }
107 }
108
109 template <class B, bool is_const>
111 {
112 ++m_index;
113 // If we have reached next block
114 if (is_first_bit_of_block(m_index))
115 {
116 ++p_block;
117 m_index = 0u;
118 }
119 SPARROW_ASSERT_TRUE(m_index < bitset_type::s_bits_per_block);
120 }
121
122 template <class B, bool is_const>
124 {
125 // decreasing moves to previous block
126 if (is_first_bit_of_block(m_index))
127 {
128 --p_block;
129 m_index = bitset_type::s_bits_per_block - 1;
130 }
131 else
132 {
133 --m_index;
134 }
135 SPARROW_ASSERT_TRUE(m_index < bitset_type::s_bits_per_block);
136 }
137
138 template <class B, bool is_const>
140 {
141 if (n >= 0)
142 {
143 if (std::cmp_less(n, bitset_type::s_bits_per_block - m_index))
144 {
145 m_index += static_cast<size_type>(n);
146 }
147 else
148 {
149 const size_type to_next_block = bitset_type::s_bits_per_block - m_index;
150 n -= static_cast<difference_type>(to_next_block);
151 const size_type block_n = static_cast<size_type>(n) / bitset_type::s_bits_per_block;
152 p_block += block_n + 1;
153 n -= static_cast<difference_type>(block_n * bitset_type::s_bits_per_block);
154 m_index = static_cast<size_type>(n);
155 }
156 }
157 else
158 {
159 auto mn = static_cast<size_type>(-n);
160 if (m_index >= mn)
161 {
162 m_index -= mn;
163 }
164 else
165 {
166 const size_type block_n = mn / bitset_type::s_bits_per_block;
167 p_block -= block_n;
168 mn -= block_n * bitset_type::s_bits_per_block;
169 if (m_index >= mn)
170 {
171 m_index -= mn;
172 }
173 else
174 {
175 mn -= m_index;
176 --p_block;
177 m_index = bitset_type::s_bits_per_block - mn;
178 }
179 }
180 }
181 SPARROW_ASSERT_TRUE(m_index < bitset_type::s_bits_per_block);
182 }
183
184 template <class B, bool is_const>
185 constexpr auto bitset_iterator<B, is_const>::distance_to(const self_type& rhs) const noexcept
187 {
188 if (p_block == rhs.p_block)
189 {
190 return static_cast<difference_type>(rhs.m_index - m_index);
191 }
192 else
193 {
194 const auto dist1 = distance_to_begin();
195 const auto dist2 = rhs.distance_to_begin();
196 return dist2 - dist1;
197 }
198 }
199
200 template <class B, bool is_const>
201 constexpr bool bitset_iterator<B, is_const>::equal(const self_type& rhs) const noexcept
202 {
203 return p_block == rhs.p_block && m_index == rhs.m_index;
204 }
205
206 template <class B, bool is_const>
207 constexpr bool bitset_iterator<B, is_const>::less_than(const self_type& rhs) const noexcept
208 {
209 return (p_block < rhs.p_block) || (p_block == rhs.p_block && m_index < rhs.m_index);
210 }
211
212 template <class B, bool is_const>
213 constexpr bool bitset_iterator<B, is_const>::is_first_bit_of_block(size_type index) const noexcept
214 {
215 return index % bitset_type::s_bits_per_block == 0;
216 }
217
218 template <class B, bool is_const>
220 {
221 const difference_type distance = p_block - p_bitset->begin().p_block;
222 SPARROW_ASSERT_TRUE(distance >= 0);
223 return static_cast<difference_type>(bitset_type::s_bits_per_block) * distance
224 + static_cast<difference_type>(m_index);
225 }
226}
typename base_type::reference reference
constexpr bitset_iterator() noexcept=default
mpl::constify_t< B, is_const > bitset_type
iterator_base< self_type, mpl::constify_t< typename B::value_type, is_const >, std::contiguous_iterator_tag, std::conditional_t< is_const, bool, bitset_reference< B > > > base_type
mpl::constify_t< typename B::block_type, is_const > block_type
typename B::size_type size_type
bitset_iterator< B, is_const > self_type
typename base_type::difference_type difference_type
Reference proxy used by the bitset_iterator class to make it possible to assign a bit of a bitset as ...
#define SPARROW_ASSERT_TRUE(expr__)
typename constify< T, is_const >::type constify_t
Definition mp_utils.hpp:390