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 <vector>
28
29#include <import_export.h>
30
31#if defined( _MSC_VER )
32// ssize_t is a POSIX extension
33// wx usually defines it on windows as a helper
34// windows does have SSIZE_T (capital) for the same purpose
35#include <BaseTsd.h>
36typedef SSIZE_T ssize_t;
37#endif
38
40{
41public:
42 using iterator = std::vector<int>::iterator;
43 using const_iterator = std::vector<int>::const_iterator;
44
45 BASE_SET( size_t size = 64 ) : m_bits( size, 0 ) {}
46
47 bool test( size_t pos ) const
48 {
49 if( pos >= m_bits.size() )
50 return false;
51
52 return m_bits[pos] == 1;
53 }
54
55 bool any() const { return std::any_of( m_bits.begin(), m_bits.end(), []( int bit ) { return bit == 1; } ); }
56
57 bool all() const { return std::all_of( m_bits.begin(), m_bits.end(), []( int bit ) { return bit == 1; } ); }
58
59 bool none() const { return std::none_of( m_bits.begin(), m_bits.end(), []( int bit ) { return bit == 1; } ); }
60
61 BASE_SET& set( size_t pos = std::numeric_limits<size_t>::max(), bool value = true )
62 {
63 if( pos == std::numeric_limits<size_t>::max() )
64 {
65 std::fill( m_bits.begin(), m_bits.end(), value ? 1 : 0 );
66 return *this;
67 }
68
69 if( pos >= m_bits.size() )
70 m_bits.resize( pos + 1, 0 );
71
72 m_bits[pos] = value ? 1 : 0;
73 return *this;
74 }
75
76 BASE_SET& reset( size_t pos = std::numeric_limits<size_t>::max() )
77 {
78 if( pos == std::numeric_limits<size_t>::max() )
79 {
80 std::fill( m_bits.begin(), m_bits.end(), 0 );
81 return *this;
82 }
83
84 if( pos >= m_bits.size() )
85 m_bits.resize( pos + 1, 0 );
86
87 m_bits[pos] = 0;
88 return *this;
89 }
90
91 BASE_SET& flip( size_t pos = std::numeric_limits<size_t>::max() )
92 {
93 if( pos == std::numeric_limits<size_t>::max() )
94 {
95 std::transform( m_bits.begin(), m_bits.end(), m_bits.begin(), []( int bit ) { return bit ^ 1; } );
96 return *this;
97 }
98
99 if( pos >= m_bits.size() )
100 m_bits.resize( pos + 1, 0 );
101
102 m_bits[pos] ^= 1;
103 return *this;
104 }
105
106 size_t count() const { return std::count( m_bits.begin(), m_bits.end(), 1 ); }
107
108 size_t size() const { return m_bits.size(); }
109
110 void resize( size_t newSize ) { m_bits.resize( newSize, 0 ); }
111
112 int& operator[]( size_t pos ) { return m_bits[pos]; }
113
114 const int& operator[]( size_t pos ) const { return m_bits[pos]; }
115
116 int compare( const BASE_SET& other ) const
117 {
118 auto result = std::lexicographical_compare_three_way(
119 m_bits.begin(), m_bits.end(), other.m_bits.begin(), other.m_bits.end() );
120 return result == std::strong_ordering::equal ? 0 : ( result == std::strong_ordering::less ? -1 : 1 );
121 }
122
123 iterator begin() { return m_bits.begin(); }
124 iterator end() { return m_bits.end(); }
125 const_iterator begin() const { return m_bits.begin(); }
126 const_iterator end() const { return m_bits.end(); }
127
128 // Define equality operator
129 bool operator==( const BASE_SET& other ) const
130 {
131 std::size_t minSize = std::min( size(), other.size() );
132 if( !std::equal( m_bits.begin(), m_bits.begin() + minSize, other.m_bits.begin() ) )
133 return false;
134
135 if( std::any_of( m_bits.begin() + minSize, m_bits.end(), []( int bit ) { return bit != 0; } ) )
136 return false;
137
138 if( std::any_of( other.m_bits.begin() + minSize, other.m_bits.end(), []( int bit ) { return bit != 0; } ) )
139 return false;
140
141 return true;
142 }
143
144 // Define less-than operator for comparison
145 bool operator<( const BASE_SET& other ) const
146 {
147 return std::lexicographical_compare( m_bits.begin(), m_bits.end(), other.m_bits.begin(), other.m_bits.end() );
148 }
149
150 // Define output operator
151 friend std::ostream& operator<<( std::ostream& os, const BASE_SET& set )
152 {
153 return os << set.to_string();
154 }
155
156 // to_string method
157 template <typename CharT = char>
158 std::basic_string<CharT> to_string( CharT zero = CharT( '0' ), CharT one = CharT( '1' ) ) const
159 {
160 std::basic_string<CharT> result( size(), zero );
161
162 for( size_t i = 0; i < size(); ++i )
163 {
164 if( test( i ) )
165 {
166 result[size() - 1 - i] = one; // Reverse order to match std::bitset behavior
167 }
168 }
169
170 return result;
171 }
172
173 // Boolean operators
175 {
176 for( size_t i = 0; i < m_bits.size(); ++i )
177 m_bits[i] &= rhs.m_bits[i];
178
179 return *this;
180 }
181
183 {
184 for( size_t i = 0; i < m_bits.size(); ++i )
185 m_bits[i] |= rhs.m_bits[i];
186
187 return *this;
188 }
189
191 {
192 for( size_t i = 0; i < m_bits.size(); ++i )
193 m_bits[i] ^= rhs.m_bits[i];
194
195 return *this;
196 }
197
199 {
200 BASE_SET result = *this;
201 for( size_t i = 0; i < m_bits.size(); ++i )
202 result.m_bits[i] = !m_bits[i];
203
204 return result;
205 }
206
207 // Custom iterator to iterate over set bits
209 {
210 public:
211 using iterator_category = std::forward_iterator_tag;
212 using value_type = size_t;
213 using difference_type = std::ptrdiff_t;
214 using pointer = const size_t*;
215 using reference = const size_t&;
216
217 set_bits_iterator( const BASE_SET& baseSet, size_t index ) :
218 m_baseSet( baseSet ), m_index( index )
219 {
220 advance_to_next_set_bit();
221 }
222
223 size_t operator*() const { return m_index; }
224
226 {
227 ++m_index;
228 advance_to_next_set_bit();
229 return *this;
230 }
231
232 bool operator!=( const set_bits_iterator& other ) const { return m_index != other.m_index; }
233
234 bool operator==( const set_bits_iterator& other ) const { return m_index == other.m_index; }
235
236 private:
238 {
239 while( m_index < m_baseSet.size() && !m_baseSet.test( m_index ) )
240 ++m_index;
241 }
242
244 size_t m_index;
245 };
246
247 // Custom reverse iterator to iterate over set bits in reverse order
249 {
250 public:
251 using iterator_category = std::bidirectional_iterator_tag;
252 using value_type = ssize_t;
253 using difference_type = std::ptrdiff_t;
254 using pointer = const ssize_t*;
255 using reference = const ssize_t&;
256
257 set_bits_reverse_iterator( const BASE_SET& baseSet, ssize_t index ) :
258 m_baseSet( baseSet ), m_index( index )
259 {
260 advance_to_previous_set_bit();
261 }
262
263 ssize_t operator*() const { return m_index; }
264
266 {
267 --m_index;
268 advance_to_previous_set_bit();
269 return *this;
270 }
271
272 bool operator!=( const set_bits_reverse_iterator& other ) const
273 {
274 return m_index != other.m_index;
275 }
276
277 bool operator==( const set_bits_reverse_iterator& other ) const
278 {
279 return m_index == other.m_index;
280 }
281
282 private:
284 {
285 while( m_index >= 0 && !m_baseSet.test( m_index ) )
286 {
287 --m_index;
288 }
289 }
290
292 ssize_t m_index;
293 };
294
295 set_bits_iterator set_bits_begin() const { return set_bits_iterator( *this, 0 ); }
296 set_bits_iterator set_bits_end() const { return set_bits_iterator( *this, m_bits.size() ); }
297
299 {
300 return set_bits_reverse_iterator( *this, m_bits.size() - 1 );
301 }
303 {
304 return set_bits_reverse_iterator( *this, -1 );
305 }
306
307private:
308 std::vector<int> m_bits;
309};
310
311inline BASE_SET operator&( const BASE_SET& lhs, const BASE_SET& rhs )
312{
313 BASE_SET result = lhs;
314 result &= rhs;
315 return result;
316}
317
318inline BASE_SET operator|( const BASE_SET& lhs, const BASE_SET& rhs )
319{
320 BASE_SET result = lhs;
321 result |= rhs;
322 return result;
323}
324
325inline BASE_SET operator^( const BASE_SET& lhs, const BASE_SET& rhs )
326{
327 BASE_SET result = lhs;
328 result ^= rhs;
329 return result;
330}
331
332namespace std
333{
334template <>
335struct hash<BASE_SET>
336{
337 size_t operator()( const BASE_SET& bs ) const
338 {
339 size_t hashVal = 0;
340
341 for( const auto& bit : bs )
342 hashVal = hashVal * 31 + std::hash<int>()( bit );
343
344 return hashVal;
345 }
346};
347} // namespace std
348
349#endif // BASE_SET_H
BASE_SET operator|(const BASE_SET &lhs, const BASE_SET &rhs)
Definition: base_set.h:318
BASE_SET operator^(const BASE_SET &lhs, const BASE_SET &rhs)
Definition: base_set.h:325
BASE_SET operator&(const BASE_SET &lhs, const BASE_SET &rhs)
Definition: base_set.h:311
const size_t * pointer
Definition: base_set.h:214
set_bits_iterator & operator++()
Definition: base_set.h:225
std::forward_iterator_tag iterator_category
Definition: base_set.h:211
bool operator!=(const set_bits_iterator &other) const
Definition: base_set.h:232
bool operator==(const set_bits_iterator &other) const
Definition: base_set.h:234
const BASE_SET & m_baseSet
Definition: base_set.h:243
size_t operator*() const
Definition: base_set.h:223
std::ptrdiff_t difference_type
Definition: base_set.h:213
set_bits_iterator(const BASE_SET &baseSet, size_t index)
Definition: base_set.h:217
const size_t & reference
Definition: base_set.h:215
set_bits_reverse_iterator & operator++()
Definition: base_set.h:265
set_bits_reverse_iterator(const BASE_SET &baseSet, ssize_t index)
Definition: base_set.h:257
bool operator==(const set_bits_reverse_iterator &other) const
Definition: base_set.h:277
std::bidirectional_iterator_tag iterator_category
Definition: base_set.h:251
bool operator!=(const set_bits_reverse_iterator &other) const
Definition: base_set.h:272
BASE_SET & flip(size_t pos=std::numeric_limits< size_t >::max())
Definition: base_set.h:91
set_bits_reverse_iterator set_bits_rbegin() const
Definition: base_set.h:298
std::vector< int > m_bits
Definition: base_set.h:308
iterator end()
Definition: base_set.h:124
const_iterator end() const
Definition: base_set.h:126
bool operator<(const BASE_SET &other) const
Definition: base_set.h:145
std::basic_string< CharT > to_string(CharT zero=CharT( '0'), CharT one=CharT( '1')) const
Definition: base_set.h:158
std::vector< int >::iterator iterator
Definition: base_set.h:42
set_bits_iterator set_bits_end() const
Definition: base_set.h:296
bool none() const
Definition: base_set.h:59
BASE_SET(size_t size=64)
Definition: base_set.h:45
friend std::ostream & operator<<(std::ostream &os, const BASE_SET &set)
Definition: base_set.h:151
BASE_SET & set(size_t pos=std::numeric_limits< size_t >::max(), bool value=true)
Definition: base_set.h:61
bool test(size_t pos) const
Definition: base_set.h:47
bool any() const
Definition: base_set.h:55
BASE_SET & reset(size_t pos=std::numeric_limits< size_t >::max())
Definition: base_set.h:76
BASE_SET operator~() const
Definition: base_set.h:198
const int & operator[](size_t pos) const
Definition: base_set.h:114
set_bits_reverse_iterator set_bits_rend() const
Definition: base_set.h:302
std::vector< int >::const_iterator const_iterator
Definition: base_set.h:43
BASE_SET & operator|=(const BASE_SET &rhs)
Definition: base_set.h:182
BASE_SET & operator&=(const BASE_SET &rhs)
Definition: base_set.h:174
int compare(const BASE_SET &other) const
Definition: base_set.h:116
bool operator==(const BASE_SET &other) const
Definition: base_set.h:129
size_t size() const
Definition: base_set.h:108
iterator begin()
Definition: base_set.h:123
size_t count() const
Definition: base_set.h:106
BASE_SET & operator^=(const BASE_SET &rhs)
Definition: base_set.h:190
const_iterator begin() const
Definition: base_set.h:125
set_bits_iterator set_bits_begin() const
Definition: base_set.h:295
bool all() const
Definition: base_set.h:57
int & operator[](size_t pos)
Definition: base_set.h:112
void resize(size_t newSize)
Definition: base_set.h:110
const int minSize
Push and Shove router track width and via size dialog.
#define APIEXPORT
Macros which export functions from a DLL/DSO.
Definition: import_export.h:42
STL namespace.
size_t operator()(const BASE_SET &bs) const
Definition: base_set.h:337