Nemo  2.4.2
Simulate forward-in-time genetic evolution in a spatially explicit, individual-based stochastic simulator
bitstring.h
Go to the documentation of this file.
1 
27 #ifndef BITSRING_H
28 #define BITSRING_H
29 
30 #include <bitset>
31 #include <assert.h> //for CHAR_BIT
32 #include <limits.h>
33 #include <string.h>
34 #include <iostream>
35 
36 #ifdef _GLIBCPP_BITSET_BITS_PER_WORD
37 #define BITS_PER_WORD _GLIBCPP_BITSET_BITS_PER_WORD
38 #else
39 #define BITS_PER_WORD (CHAR_BIT*sizeof(unsigned long))
40 #endif
41 
42 #ifndef _GLIBCPP_BITSET_WORDS
43 #define BITSET_WORDS(__n) \
44 ((__n) < 1 ? 1 : ((__n) + BITS_PER_WORD - 1)/BITS_PER_WORD)
45 #else
46 #define BITSET_WORDS(__n) _GLIBCPP_BITSET_WORDS(__n)
47 #endif
48 
49 
50 #define MASK ULLONG_MAX
51 
53 class bitstring {
54 
55 public:
56 
57  typedef unsigned long _ul;
58 
59  class reference
60  {
61  friend class bitstring;
62 
64  size_t _bitpos;
65 
66  // left undefined
68 
69  public:
70  reference(bitstring& bs, size_t pos)
71  {
72  _word = bs.getword_atPos( pos );
73  _bitpos = pos % BITS_PER_WORD;
74  }
75 
77  { }
78 
79  // For b[i] = x;
81  {
82  if (x)
83  *_word |= ( 1UL << ( _bitpos % BITS_PER_WORD ) );
84  else
85  *_word &= ~( 1UL << ( _bitpos % BITS_PER_WORD ) );
86  return *this;
87  }
88 
89  // For b[i] = b[j];
91  {
92  if ((*(j._word) & ( 1UL << ( j._bitpos % BITS_PER_WORD ) ) ))
93  *_word |= ( 1UL << ( _bitpos % BITS_PER_WORD ) );
94  else
95  *_word &= ~( 1UL << ( _bitpos % BITS_PER_WORD ) );
96  return *this;
97  }
98 
99  // Flips the bit
100  bool operator~() const
101  { return (*(_word) & ( 1UL << ( _bitpos % BITS_PER_WORD ) ) ) == 0; }
102 
103  // For __x = b[i];
104  operator bool() const
105  { return (*(_word) & ( 1UL << ( _bitpos % BITS_PER_WORD ) ) ) != 0; }
106 
107  // For b[i].flip();
109  {
110  *_word ^= ( 1UL << ( _bitpos % BITS_PER_WORD ) );
111  return *this;
112  }
113  };
114 
115  friend class reference;
116 
117  bitstring () : _size(0), _words(0), _data(0) {}
118 
119  bitstring (size_t length)
120  : _size(length), _words( BITSET_WORDS(length) ), _data(0)
121  {
122  _data = new _ul [_words];
123  memset(_data, 0, _words * sizeof(_ul));
124  }
125 
126  bitstring (const bitstring& b)
127  : _size(b._size), _words(b._words), _data(0)
128  {
129  _data = new _ul [_words];
130  memcpy(_data, b._data, _words * sizeof(_ul));
131  }
132 
133  ~bitstring () {if(_data != NULL) delete [] _data;}
134 
135 
136  void reset(size_t length)
137  {
138  _size = length;
139 
140  _words = BITSET_WORDS(length);
141 
142  if(_data) delete [] _data;
143 
144  _data = new _ul [_words];
145  memset(_data, 0UL, _words * sizeof(_ul));
146  }
147 
149  void reset ( )
150  { for(unsigned int i = 0; i < _words; i++) _data[i] = 0UL; }
151 
152  _ul* getword_atPos (size_t pos) const
153  { return &_data[ pos / BITS_PER_WORD ]; }
154 
155  _ul* getword_atIdx (size_t index) const
156  { return &_data[ index ]; }
157 
158  size_t size ( ) const {return _size;}
159 
160  size_t nb_words ( ) const {return _words;}
161 
162  bool at (size_t word, unsigned long bitmask) const
163  {
164  return bool( _data[ word ] & bitmask );
165  }
166 
167  reference operator[] (size_t pos)
168  { return reference(*this, pos); }
169 
170  bool operator[] (size_t n) const
171  { return bool( _data[ n / BITS_PER_WORD ] & ( 1UL << ( n % BITS_PER_WORD ) ) ); }
172 
174  {
175  _size = b._size;
176  if (_words != b._words) {
177  _words = b._words;
178  if(_data != NULL) delete [] _data;
179  _data = new _ul [_words];
180  }
181  memcpy(_data, b._data, _words * sizeof(_ul));
182  return *this;
183  }
184 
186  {
187  for (size_t i = 0; i < _words; i++)
188  _data[i] &= x._data[i];
189  return *this;
190  }
191 
193  {
194  for (size_t i = 0; i < _words; i++)
195  _data[i] |= x._data[i];
196  return *this;
197  }
198 
200  {
201  for (size_t i = 0; i < _words; i++)
202  _data[i] ^= x._data[i];
203  return *this;
204  }
205 
207  {
208  for (size_t i = 0; i < _words; i++)
209  _data[i] = ~(_data[i]);
210  return *this;
211  }
212 
214  {
215  bitstring result(*this);
216  result &= x;
217  return result;
218  }
219 
221  {
222  bitstring result(*this);
223  result |= x;
224  return result;
225  }
226 
228  {
229  bitstring result(*this);
230  result ^= x;
231  return result;
232  }
233 
236 #ifdef __POPCNT__
237  unsigned int local_popcountl (_ul wd) const
238  {
239  return (unsigned int) __builtin_popcountl(wd);
240  }
241 #else
242  unsigned int local_popcountl (_ul wd) const
243  {
244  unsigned char* c = (unsigned char*)&wd;
245  unsigned short cnt = 0;
246 
247  for(unsigned int i = 0; i < sizeof(_ul); i++)
248  cnt += _bit_count[ (unsigned int)c[i] ];
249 
250  return (unsigned int) cnt;
251  }
252 #endif
253 
255  unsigned int count ( )
256  {
257  unsigned int cnt = 0;
258 
259  for(size_t i = 0; i < _words; i++)
260  cnt += local_popcountl(_data[i]);
261 
262  return cnt;
263  }
264 
266  unsigned int count (size_t from, size_t to)
267  {
268  assert(from < to && to <= _size);
269 
270  unsigned int cnt = 0;
271  size_t start_w = from / BITS_PER_WORD;
272  size_t end_w = to / BITS_PER_WORD;
273  size_t start_l = from % BITS_PER_WORD;
274  size_t end_l = to % BITS_PER_WORD;
275 
276  if (start_w == end_w) {
277  _ul mask = (MASK << start_l) & (MASK >> (BITS_PER_WORD - end_l));
278  return local_popcountl( _ul(_data[start_w] & mask) );
279  }
280 
281  // first partial word
282  cnt += local_popcountl(_data[start_w] & (MASK << start_l));
283 
284  // full words in between
285  for (size_t i = start_w + 1; i < end_w; ++i)
286  cnt += local_popcountl(_data[i]);
287 
288  // last partial word
289  if (end_l > 0)
290  cnt += local_popcountl(_data[end_w] & (MASK >> (BITS_PER_WORD - end_l)));
291 
292  return cnt;
293  }
294 
296  unsigned int count_and (const bitstring& mask) const
297  {
298  unsigned int cnt = 0;
299  for (size_t i = 0; i < _words; ++i)
300  cnt += local_popcountl(_data[i] & mask._data[i]);
301  return cnt;
302  }
303 
305  unsigned int count_xor (const bitstring& other) const
306  {
307  unsigned int cnt = 0;
308  for (size_t i = 0; i < _words; ++i)
309  cnt += local_popcountl(_data[i] ^ other._data[i]);
310  return cnt;
311  }
312 
314  unsigned int count_xor_and (const bitstring& other, const bitstring& mask) const
315  {
316  unsigned int cnt = 0;
317  for (size_t i = 0; i < _words; ++i)
318  cnt += local_popcountl((_data[i] ^ other._data[i]) & mask._data[i]);
319  return cnt;
320  }
321 
323  unsigned int count_and_and (const bitstring& other, const bitstring& mask) const
324  {
325  unsigned int cnt = 0;
326  for (size_t i = 0; i < _words; ++i)
327  cnt += local_popcountl((_data[i] & other._data[i]) & mask._data[i]);
328  return cnt;
329  }
330 
332  void set (size_t n) {_data[n / BITS_PER_WORD] |= (1UL << (n % BITS_PER_WORD));}
333 
335  void set (size_t n, bool x) {
336  if (x)
337  _data[n / BITS_PER_WORD] |= ( 1UL << ( n % BITS_PER_WORD ) );
338  else
339  _data[n / BITS_PER_WORD] &= ~( 1UL << ( n % BITS_PER_WORD ) );
340  }
341 
343  void flip (size_t n) {_data[n / BITS_PER_WORD] ^= (1UL << (n % BITS_PER_WORD));}
344 
346  void set_data (_ul* srce, size_t nbwrd)
347  {
348  // if(nbwrd != _words) {
349  // std::cerr<<"bitstring::set_data: different sizes in memcpy!!\n";
350  // exit(1);
351  // }
352  assert(nbwrd == _words);
353  memcpy(_data, srce, nbwrd * sizeof(_ul));
354  }
355 
357  void copy (const bitstring& b)
358  { memcpy(_data, b._data, _words * sizeof(_ul)); }
359 
361  void copy (const bitstring& b, size_t word_pos)
362  { _data[ word_pos ] = b._data[ word_pos ]; }
363 
365  void copy (const bitstring& b, size_t from, size_t to)
366  {
367  assert(to <= _size);
368 
369  if(to != from) { // only if we do have something to copy
370 
371  size_t start_w, end_w, start_l, end_l;
372  _ul mask, tmpl;
373 
374  start_w = from / BITS_PER_WORD;
375  end_w = to / BITS_PER_WORD;
376 
377  start_l = from % BITS_PER_WORD;
378  end_l = to % BITS_PER_WORD;
379 
380  if(start_w != end_w) {
381  //copy wihtin first word:
382  mask = (MASK << start_l);
383 
384  _data[ start_w ] &= ~mask;
385  tmpl = b._data[ start_w ] & mask;
386 
387  _data[ start_w ] |= tmpl;
388 
389  //copy words in-between:
390  size_t k = start_w + 1;
391 
392  memcpy(&_data[k], &b._data[k], (end_w - k)*sizeof(_ul));
393 
394  //copy within last word; skip when 'to' is word-aligned (end_l == 0),
395  //since end_w then sits one past the last valid word and there's
396  //nothing left to copy beyond what the memcpy above already did.
397  if (end_l != 0) {
398  mask = (MASK >> (BITS_PER_WORD - end_l) );
399 
400  _data[ end_w ] &= ~mask;
401  tmpl = b._data[ end_w ] & mask;
402 
403  _data[ end_w ] |= tmpl;
404  }
405 
406  } else {
407  //bits to copy are within a word:
408  mask = (MASK << start_l) & (MASK >> (BITS_PER_WORD - end_l) );
409 
410  _data[ start_w ] &= ~mask;
411  tmpl = b._data[ start_w ] & mask;
412 
413  _data[ start_w ] |= tmpl;
414 
415  }
416  }
417  }
418 
419  std::string to_string() const
420  {
421  const char one = '1';
422  std::string result;
423 
424  result.assign(_size, '0');
425 
426  for(size_t i = 0; i < _size; ++i) {
427  if(_data[ i / BITS_PER_WORD ] & ( 1UL << ( i % BITS_PER_WORD ) ))
428  result[i] = one;
429  }
430 
431  return result;
432  }
433 
434  std::string to_string(size_t from, size_t to) const
435  {
436  assert(from < to && to < _size+1);
437 
438  const char one = '1';
439 
440  size_t len = to - from;
441 
442  std::string result;
443 
444  result.assign(len, '0');
445 
446  for(size_t i = from, s = 0; i < to && s < len; ++i, ++s) {
447  if(_data[ i / BITS_PER_WORD ] & ( 1UL << ( i % BITS_PER_WORD ) ))
448  result[s] = one;
449  }
450  return result;
451  }
452 
453  void print (size_t from, size_t to) const
454  {
455  assert(from < to && to < _size+1);
456  for(unsigned int i = from; i < to; ++i)
457  std::cout<< (bool)(_data[ i / BITS_PER_WORD ] & ( 1UL << ( i % BITS_PER_WORD ) ));
458  std::cout<<std::endl;
459  }
460 
461  void print() const
462  {
463  for(unsigned int i = 0; i < _size; ++i)
464  std::cout<< (bool)(_data[ i / BITS_PER_WORD ] & ( 1UL << ( i % BITS_PER_WORD ) ));
465  std::cout<<std::endl;
466  }
467 
468 private:
470  size_t _size;
471 
473  size_t _words;
474 
477 
478 
479 #ifndef __POPCNT__
480  static unsigned char _bit_count[256];
481 #endif
482 
483 };
484 
485 #endif
486 
#define BITSET_WORDS(__n)
Definition: bitstring.h:43
#define MASK
Definition: bitstring.h:50
#define BITS_PER_WORD
Definition: bitstring.h:39
Definition: bitstring.h:60
reference(bitstring &bs, size_t pos)
Definition: bitstring.h:70
reference & operator=(bool x)
Definition: bitstring.h:80
_ul * _word
Definition: bitstring.h:63
reference & flip()
Definition: bitstring.h:108
size_t _bitpos
Definition: bitstring.h:64
~reference()
Definition: bitstring.h:76
bool operator~() const
Definition: bitstring.h:100
reference & operator=(const reference &j)
Definition: bitstring.h:90
Non-template and faster implementation of std::bitset.
Definition: bitstring.h:53
static unsigned char _bit_count[256]
Definition: bitstring.h:480
bitstring(const bitstring &b)
Definition: bitstring.h:126
bitstring operator|(const bitstring &x)
Definition: bitstring.h:220
unsigned int count()
Count number of set bits.
Definition: bitstring.h:255
bool at(size_t word, unsigned long bitmask) const
Definition: bitstring.h:162
unsigned int count(size_t from, size_t to)
Count set bits in the range [from, to).
Definition: bitstring.h:266
unsigned int count_and_and(const bitstring &other, const bitstring &mask) const
Fused AND + mask popcount: count set bits in ((this AND other) AND mask).
Definition: bitstring.h:323
_ul * getword_atPos(size_t pos) const
Definition: bitstring.h:152
unsigned long _ul
Definition: bitstring.h:57
bitstring()
Definition: bitstring.h:117
size_t size() const
Definition: bitstring.h:158
_ul * getword_atIdx(size_t index) const
Definition: bitstring.h:155
size_t _words
Number of _ul-long Words necessary to hold the _size bits.
Definition: bitstring.h:473
unsigned int count_xor(const bitstring &other) const
Fused XOR popcount: count set bits in (this XOR other).
Definition: bitstring.h:305
void print(size_t from, size_t to) const
Definition: bitstring.h:453
bitstring operator&(const bitstring &x)
Definition: bitstring.h:213
unsigned int count_and(const bitstring &mask) const
Masked popcount: count set bits in (this AND mask).
Definition: bitstring.h:296
bitstring & operator|=(const bitstring &x)
Definition: bitstring.h:192
std::string to_string() const
Definition: bitstring.h:419
reference operator[](size_t pos)
Definition: bitstring.h:167
void set(size_t n, bool x)
Set a bit to 0 or 1.
Definition: bitstring.h:335
void reset()
Set all bits to 0.
Definition: bitstring.h:149
bitstring & operator=(const bitstring &b)
Definition: bitstring.h:173
bitstring & operator^=(const bitstring &x)
Definition: bitstring.h:199
friend class reference
Definition: bitstring.h:115
void set(size_t n)
Set a bit to 1.
Definition: bitstring.h:332
bitstring operator~(void)
Definition: bitstring.h:206
unsigned int local_popcountl(_ul wd) const
Counts number of one's in a word using hardware POPCNT when available, falling back to a byte-table l...
Definition: bitstring.h:242
size_t _size
Number of bits in the sequence.
Definition: bitstring.h:470
_ul * _data
The sequence.
Definition: bitstring.h:476
~bitstring()
Definition: bitstring.h:133
void set_data(_ul *srce, size_t nbwrd)
Copy bits from an array of unsigned long words.
Definition: bitstring.h:346
std::string to_string(size_t from, size_t to) const
Definition: bitstring.h:434
void flip(size_t n)
Flip the bit at n.
Definition: bitstring.h:343
void print() const
Definition: bitstring.h:461
bitstring operator^(const bitstring &x)
Definition: bitstring.h:227
void copy(const bitstring &b, size_t word_pos)
Copy one word.
Definition: bitstring.h:361
bitstring & operator&=(const bitstring &x)
Definition: bitstring.h:185
bitstring(size_t length)
Definition: bitstring.h:119
unsigned int count_xor_and(const bitstring &other, const bitstring &mask) const
Fused XOR + mask popcount: count set bits in ((this XOR other) AND mask).
Definition: bitstring.h:314
void copy(const bitstring &b)
Unchecked copy, assumes we have sames sizes.
Definition: bitstring.h:357
void copy(const bitstring &b, size_t from, size_t to)
Copy a delimited sequence block.
Definition: bitstring.h:365
size_t nb_words() const
Definition: bitstring.h:160
void reset(size_t length)
Definition: bitstring.h:136

Generated for Nemo v2.4.2 by  doxygen 1.9.1

Catalogued on GSR