KiCad PCB EDA Suite
Loading...
Searching...
No Matches
base_set.h
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19#ifndef BASE_SET_H
20#define BASE_SET_H
21
22#include <algorithm>
23#include <iterator>
24#include <limits>
25#include <ostream>
26#include <stdexcept>
27#include <dynamic_bitset.h>
28
29#include <core/kicad_algo.h>
30#include <kicommon.h>
31
32#if defined( _MSC_VER )
33// ssize_t is a POSIX extension
34// wx usually defines it on windows as a helper
35// windows does have SSIZE_T (capital) for the same purpose
36#include <BaseTsd.h>
37typedef SSIZE_T ssize_t;
38#endif
39
40class KICOMMON_API BASE_SET : public sul::dynamic_bitset<uint64_t>
41{
42public:
44 {
45 public:
46 using iterator_category = std::random_access_iterator_tag;
47 using value_type = bool;
48 using difference_type = std::ptrdiff_t;
49 using pointer = void;
50 using reference = bool;
51
52 iterator( BASE_SET* set, size_t pos ) : m_set( set ), m_pos( pos ) {}
53 bool operator*() const { return m_set->test( m_pos ); }
55 {
56 ++m_pos;
57 return *this;
58 }
60 {
61 return iterator( m_set, m_pos + n );
62 }
63 difference_type operator-( const iterator& other ) const
64 {
65 return static_cast<difference_type>(m_pos) - static_cast<difference_type>(other.m_pos);
66 }
67 auto operator<=>( const iterator& ) const = default;
68
69 private:
71 size_t m_pos;
72 };
73
75 {
76 public:
77 using iterator_category = std::random_access_iterator_tag;
78 using value_type = bool;
79 using difference_type = std::ptrdiff_t;
80 using pointer = void;
81 using reference = bool;
82
83 const_iterator( const BASE_SET* set, size_t pos ) : m_set( set ), m_pos( pos ) {}
84 bool operator*() const { return m_set->test( m_pos ); }
86 {
87 ++m_pos;
88 return *this;
89 }
91 {
92 return const_iterator( m_set, m_pos + n );
93 }
95 {
96 return static_cast<difference_type>(m_pos) - static_cast<difference_type>(other.m_pos);
97 }
98 auto operator<=>( const const_iterator& ) const = default;
99
100 private:
102 size_t m_pos;
103 };
104
105 iterator begin() { return iterator(this, 0); }
106 iterator end() { return iterator(this, size()); }
107 const_iterator begin() const { return const_iterator(this, 0); }
108 const_iterator end() const { return const_iterator(this, size()); }
109
110 BASE_SET( size_t size = 64 ) : sul::dynamic_bitset<uint64_t>( size ) {}
111
112 // Overloads for set, reset, and flip operations
113
114 // Set a bit at the specified position
115 BASE_SET& set(size_t pos)
116 {
117 if( pos >= size() )
118 sul::dynamic_bitset<uint64_t>::resize( pos + 1 );
119
120 sul::dynamic_bitset<uint64_t>::set(pos);
121 return *this;
122 }
123
124 // Set a bit at the specified position to a given value
125 BASE_SET& set(size_t pos, bool value)
126 {
127 if( pos >= size() )
128 sul::dynamic_bitset<uint64_t>::resize( pos + 1 );
129
130 sul::dynamic_bitset<uint64_t>::set(pos, value);
131 return *this;
132 }
133
134 // Set all bits to 1
136 {
137 sul::dynamic_bitset<uint64_t>::set();
138 return *this;
139 }
140
141 // Reset (clear) a bit at the specified position
142 BASE_SET& reset(size_t pos)
143 {
144 if( pos >= size() )
145 sul::dynamic_bitset<uint64_t>::resize( pos + 1 );
146
147 sul::dynamic_bitset<uint64_t>::reset(pos);
148 return *this;
149 }
150
151 // Reset (clear) all bits
153 {
154 sul::dynamic_bitset<uint64_t>::reset();
155 return *this;
156 }
157
158 // Flip a bit at the specified position
159 BASE_SET& flip(size_t pos)
160 {
161 if( pos >= size() )
162 sul::dynamic_bitset<uint64_t>::resize( pos + 1 );
163
164 sul::dynamic_bitset<uint64_t>::flip(pos);
165 return *this;
166 }
167
168 // Flip all bits
170 {
171 sul::dynamic_bitset<uint64_t>::flip();
172 return *this;
173 }
174
175 // Overloads for boolean operators
176
177 // Bitwise NOT operator
179 {
180 BASE_SET result(*this);
181 result.flip();
182 return result;
183 }
184
185 // Compound assignment AND operator
187 {
188 sul::dynamic_bitset<uint64_t>::operator&=(other);
189 return *this;
190 }
191
192 // Compound assignment OR operator
194 {
195 sul::dynamic_bitset<uint64_t>::operator|=(other);
196 return *this;
197 }
198
199 // Compound assignment XOR operator
201 {
202 sul::dynamic_bitset<uint64_t>::operator^=(other);
203 return *this;
204 }
205
206 int compare( const BASE_SET& other ) const
207 {
208 return alg::lexicographical_compare_three_way( begin(), end(), other.begin(), other.end() );
209 }
210
211 // Define less-than operator for comparison
212 bool operator<( const BASE_SET& other ) const
213 {
214 return alg::lexicographical_compare_three_way( begin(), end(), other.begin(), other.end() ) < 0;
215 }
216
217 // Custom iterator to iterate over set bits
219 {
220 public:
221 using iterator_category = std::forward_iterator_tag;
222 using value_type = size_t;
223 using difference_type = std::ptrdiff_t;
224 using pointer = const size_t*;
225 using reference = const size_t&;
226
227 set_bits_iterator( const BASE_SET& baseSet, size_t index ) :
228 m_baseSet( baseSet ), m_index( index )
229 {
230 advance_to_next_set_bit();
231 }
232
233 size_t operator*() const { return m_index; }
234
236 {
237 ++m_index;
238 advance_to_next_set_bit();
239 return *this;
240 }
241
242 bool operator!=( const set_bits_iterator& other ) const { return m_index != other.m_index; }
243
244 bool operator==( const set_bits_iterator& other ) const { return m_index == other.m_index; }
245
246 protected:
248 {
249 while( m_index < m_baseSet.size() && !m_baseSet.test( m_index ) )
250 ++m_index;
251 }
252
254 size_t m_index;
255 };
256
257 // Custom reverse iterator to iterate over set bits in reverse order
259 {
260 public:
261 using iterator_category = std::bidirectional_iterator_tag;
262 using value_type = ssize_t;
263 using difference_type = std::ptrdiff_t;
264 using pointer = const ssize_t*;
265 using reference = const ssize_t&;
266
267 set_bits_reverse_iterator( const BASE_SET& baseSet, ssize_t index ) :
268 m_baseSet( baseSet ), m_index( index )
269 {
270 advance_to_previous_set_bit();
271 }
272
273 ssize_t operator*() const { return m_index; }
274
276 {
277 --m_index;
278 advance_to_previous_set_bit();
279 return *this;
280 }
281
282 bool operator!=( const set_bits_reverse_iterator& other ) const
283 {
284 return m_index != other.m_index;
285 }
286
287 bool operator==( const set_bits_reverse_iterator& other ) const
288 {
289 return m_index == other.m_index;
290 }
291
292 protected:
294 {
295 while( m_index >= 0 && !m_baseSet.test( m_index ) )
296 {
297 --m_index;
298 }
299 }
300
302 ssize_t m_index;
303 };
304
305 set_bits_iterator set_bits_begin() const { return set_bits_iterator( *this, 0 ); }
306 set_bits_iterator set_bits_end() const { return set_bits_iterator( *this, size() ); }
307
309 {
310 return set_bits_reverse_iterator( *this, size() - 1 );
311 }
313 {
314 return set_bits_reverse_iterator( *this, -1 );
315 }
316
317};
318
319inline BASE_SET operator&( const BASE_SET& lhs, const BASE_SET& rhs )
320{
321 BASE_SET result = lhs;
322 result &= rhs;
323 return result;
324}
325
326inline BASE_SET operator|( const BASE_SET& lhs, const BASE_SET& rhs )
327{
328 BASE_SET result = lhs;
329 result |= rhs;
330 return result;
331}
332
333inline BASE_SET operator^( const BASE_SET& lhs, const BASE_SET& rhs )
334{
335 BASE_SET result = lhs;
336 result ^= rhs;
337 return result;
338}
339
340namespace std
341{
342template <>
343struct hash<BASE_SET>
344{
345 size_t operator()( const BASE_SET& bs ) const
346 {
347 size_t hashVal = 0;
348
349 for( const auto& bit : bs )
350 hashVal = hashVal * 31 + std::hash<int>()( bit );
351
352 return hashVal;
353 }
354};
355} // namespace std
356
357#endif // BASE_SET_H
BASE_SET operator|(const BASE_SET &lhs, const BASE_SET &rhs)
Definition: base_set.h:326
BASE_SET operator^(const BASE_SET &lhs, const BASE_SET &rhs)
Definition: base_set.h:333
BASE_SET operator&(const BASE_SET &lhs, const BASE_SET &rhs)
Definition: base_set.h:319
auto operator<=>(const const_iterator &) const =default
std::random_access_iterator_tag iterator_category
Definition: base_set.h:77
const BASE_SET * m_set
Definition: base_set.h:101
const_iterator operator+(difference_type n) const
Definition: base_set.h:90
const_iterator(const BASE_SET *set, size_t pos)
Definition: base_set.h:83
difference_type operator-(const const_iterator &other) const
Definition: base_set.h:94
bool operator*() const
Definition: base_set.h:84
std::ptrdiff_t difference_type
Definition: base_set.h:79
const_iterator & operator++()
Definition: base_set.h:85
auto operator<=>(const iterator &) const =default
iterator & operator++()
Definition: base_set.h:54
difference_type operator-(const iterator &other) const
Definition: base_set.h:63
BASE_SET * m_set
Definition: base_set.h:70
bool operator*() const
Definition: base_set.h:53
iterator(BASE_SET *set, size_t pos)
Definition: base_set.h:52
std::ptrdiff_t difference_type
Definition: base_set.h:48
std::random_access_iterator_tag iterator_category
Definition: base_set.h:46
iterator operator+(difference_type n) const
Definition: base_set.h:59
const size_t * pointer
Definition: base_set.h:224
set_bits_iterator & operator++()
Definition: base_set.h:235
std::forward_iterator_tag iterator_category
Definition: base_set.h:221
bool operator!=(const set_bits_iterator &other) const
Definition: base_set.h:242
bool operator==(const set_bits_iterator &other) const
Definition: base_set.h:244
const BASE_SET & m_baseSet
Definition: base_set.h:253
size_t operator*() const
Definition: base_set.h:233
std::ptrdiff_t difference_type
Definition: base_set.h:223
set_bits_iterator(const BASE_SET &baseSet, size_t index)
Definition: base_set.h:227
const size_t & reference
Definition: base_set.h:225
set_bits_reverse_iterator & operator++()
Definition: base_set.h:275
set_bits_reverse_iterator(const BASE_SET &baseSet, ssize_t index)
Definition: base_set.h:267
bool operator==(const set_bits_reverse_iterator &other) const
Definition: base_set.h:287
std::bidirectional_iterator_tag iterator_category
Definition: base_set.h:261
bool operator!=(const set_bits_reverse_iterator &other) const
Definition: base_set.h:282
set_bits_reverse_iterator set_bits_rbegin() const
Definition: base_set.h:308
iterator end()
Definition: base_set.h:106
BASE_SET & flip()
Definition: base_set.h:169
const_iterator end() const
Definition: base_set.h:108
bool operator<(const BASE_SET &other) const
Definition: base_set.h:212
set_bits_iterator set_bits_end() const
Definition: base_set.h:306
BASE_SET & reset(size_t pos)
Definition: base_set.h:142
BASE_SET(size_t size=64)
Definition: base_set.h:110
BASE_SET & operator^=(const BASE_SET &other)
Definition: base_set.h:200
BASE_SET & flip(size_t pos)
Definition: base_set.h:159
BASE_SET & set(size_t pos, bool value)
Definition: base_set.h:125
BASE_SET operator~() const
Definition: base_set.h:178
set_bits_reverse_iterator set_bits_rend() const
Definition: base_set.h:312
BASE_SET & set()
Definition: base_set.h:135
BASE_SET & reset()
Definition: base_set.h:152
int compare(const BASE_SET &other) const
Definition: base_set.h:206
iterator begin()
Definition: base_set.h:105
BASE_SET & set(size_t pos)
Definition: base_set.h:115
const_iterator begin() const
Definition: base_set.h:107
set_bits_iterator set_bits_begin() const
Definition: base_set.h:305
BASE_SET & operator|=(const BASE_SET &other)
Definition: base_set.h:193
BASE_SET & operator&=(const BASE_SET &other)
Definition: base_set.h:186
#define KICOMMON_API
Definition: kicommon.h:28
int lexicographical_compare_three_way(Container1Iter aC1_first, Container1Iter aC1_last, Container2Iter aC2_first, Container2Iter aC2_last)
Compares two containers lexicographically.
Definition: kicad_algo.h:246
STL namespace.
size_t operator()(const BASE_SET &bs) const
Definition: base_set.h:345