libbf  0.1
 All Classes Functions Typedefs Friends Pages
bitvector.h
1 #ifndef BF_BITVECTOR_H
2 #define BF_BITVECTOR_H
3 
4 #include <iterator>
5 #include <limits>
6 #include <string>
7 #include <vector>
8 
9 namespace bf {
10 
12 class bitvector
13 {
14  friend std::string to_string(bitvector const&, bool, size_t);
15 
16 public:
17  typedef size_t block_type;
18  typedef size_t size_type;
19  static size_type constexpr npos = static_cast<size_type>(-1);
20  static block_type constexpr bits_per_block =
21  std::numeric_limits<block_type>::digits;
22 
23 public:
25  class reference
26  {
27  friend class bitvector;
28  void operator&() = delete;
29 
33  reference(block_type& block, block_type i);
34 
35  public:
36  reference& flip();
37  operator bool() const;
38  bool operator~() const;
39  reference& operator=(bool x);
40  reference& operator=(reference const& other);
41  reference& operator|=(bool x);
42  reference& operator&=(bool x);
43  reference& operator^=(bool x);
44  reference& operator-=(bool x);
45 
46  private:
47  block_type& block_;
48  block_type const mask_;
49  };
50 
53  typedef bool const_reference;
54 
56  bitvector();
57 
61  explicit bitvector(size_type size, bool value = false);
62 
64  template <typename InputIterator>
65  bitvector(InputIterator first, InputIterator last)
66  {
67  bits_.insert(bits_.end(), first, last);
68  num_bits_ = bits_.size() * bits_per_block;
69  }
70 
73  bitvector(bitvector const& other);
74 
77  bitvector(bitvector&& other);
78 
82 
84  friend void swap(bitvector x, bitvector y);
85 
86  //
87  // Bitwise operations
88  //
89  bitvector operator~() const;
90  bitvector operator<<(size_type n) const;
91  bitvector operator>>(size_type n) const;
92  bitvector& operator<<=(size_type n);
93  bitvector& operator>>=(size_type n);
94  bitvector& operator&=(bitvector const& other);
95  bitvector& operator|=(bitvector const& other);
96  bitvector& operator^=(bitvector const& other);
97  bitvector& operator-=(bitvector const& other);
98  friend bitvector operator&(bitvector const& x, bitvector const& y);
99  friend bitvector operator|(bitvector const& x, bitvector const& y);
100  friend bitvector operator^(bitvector const& x, bitvector const& y);
101  friend bitvector operator-(bitvector const& x, bitvector const& y);
102 
103  //
104  // Relational operators
105  //
106  friend bool operator==(bitvector const& x, bitvector const& y);
107  friend bool operator!=(bitvector const& x, bitvector const& y);
108  friend bool operator<(bitvector const& x, bitvector const& y);
109 
110  //
111  // Basic operations
112  //
118  template <
119  typename Iterator,
120  typename std::enable_if<
121  std::is_same<
122  typename std::iterator_traits<Iterator>::iterator_category,
123  std::forward_iterator_tag
124  >::value
125  >::type = 0
126  >
127  void append(Iterator first, Iterator last)
128  {
129  if (first == last)
130  return;
131 
132  auto excess = extra_bits();
133  auto delta = std::distance(first, last);
134  bits_.reserve(blocks() + delta);
135  if (excess == 0)
136  {
137  bits_.back() |= (*first << excess);
138  do
139  {
140  auto b = *first++ >> (bits_per_block - excess);
141  bits_.push_back(b | (first == last ? 0 : *first << excess));
142  } while (first != last);
143  }
144  else
145  {
146  bits_.insert(bits_.end(), first, last);
147  }
148 
149  num_bits_ += bits_per_block * delta;
150  }
151 
154  void append(block_type block);
155 
158  void push_back(bool bit);
159 
161  void clear() noexcept;
162 
166  void resize(size_type n, bool value = false);
167 
172  bitvector& set(size_type i, bool bit = true);
173 
176  bitvector& set();
177 
181  bitvector& reset(size_type i);
182 
185  bitvector& reset();
186 
190  bitvector& flip(size_type i);
191 
194  bitvector& flip();
195 
199  reference operator[](size_type i);
200 
204  const_reference operator[](size_type i) const;
205 
209  size_type count() const;
210 
213  size_type blocks() const;
214 
217  size_type size() const;
218 
221  bool empty() const;
222 
227  size_type find_first() const;
228 
235  size_type find_next(size_type i) const;
236 
237 private:
239  static size_type constexpr block_index(size_type i)
240  {
241  return i / bits_per_block;
242  }
243 
245  static block_type constexpr bit_index(size_type i)
246  {
247  return i % bits_per_block;
248  }
249 
251  static block_type constexpr bit_mask(size_type i)
252  {
253  return block_type(1) << bit_index(i);
254  }
255 
260  static size_type constexpr bits_to_blocks(size_type bits)
261  {
262  return bits / bits_per_block
263  + static_cast<size_type>(bits % bits_per_block != 0);
264  }
265 
269  static size_type lowest_bit(block_type block);
270 
272  block_type extra_bits() const;
273 
274  // If the number of bits in the vector are not not a multiple of
275  // bitvector::bits_per_block, then the last block exhibits unused bits which
276  // this function resets.
277  void zero_unused_bits();
278 
285  size_type find_from(size_type i) const;
286 
287  std::vector<block_type> bits_;
288  size_type num_bits_;
289 };
290 
306 std::string to_string(bitvector const& b,
307  bool msb_to_lsb = true,
308  bool all = false,
309  size_t cut_off = 0);
310 
311 } // namespace bf
312 
313 #endif