GraphLab: Distributed Graph-Parallel API  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dense_bitset.hpp
1 /**
2  * Copyright (c) 2009 Carnegie Mellon University.
3  * All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing,
12  * software distributed under the License is distributed on an "AS
13  * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14  * express or implied. See the License for the specific language
15  * governing permissions and limitations under the License.
16  *
17  * For more about this software visit:
18  *
19  * http://www.graphlab.ml.cmu.edu
20  *
21  */
22 
23 
24 #ifndef GRAPHLAB_DENSE_BITSET_HPP
25 #define GRAPHLAB_DENSE_BITSET_HPP
26 
27 #include <cstdio>
28 #include <cstdlib>
29 #include <cstring>
30 #include <stdint.h>
32 #include <graphlab/parallel/atomic_ops.hpp>
33 #include <graphlab/serialization/serialization_includes.hpp>
34 
35 namespace graphlab {
36 
37  /** \ingroup util
38  * Implements an atomic dense bitset
39  */
40  class dense_bitset {
41  public:
42 
43  /// Constructs a bitset of 0 length
44  dense_bitset() : array(NULL), len(0), arrlen(0) {
45  }
46 
47  /// Constructs a bitset with 'size' bits. All bits will be cleared.
48  explicit dense_bitset(size_t size) : array(NULL), len(size) {
49  resize(size);
50  clear();
51  }
52 
53  /// Make a copy of the bitset db
55  array = NULL;
56  len = 0;
57  arrlen = 0;
58  *this = db;
59  }
60 
61  /// destructor
62  ~dense_bitset() {free(array);}
63 
64  /// Make a copy of the bitset db
65  inline dense_bitset& operator=(const dense_bitset& db) {
66  resize(db.size());
67  len = db.len;
68  arrlen = db.arrlen;
69  memcpy(array, db.array, sizeof(size_t) * arrlen);
70  return *this;
71  }
72 
73  /** Resizes the current bitset to hold n bits.
74  Existing bits will not be changed. If the array size is increased,
75  the value of the new bits are undefined.
76 
77  \Warning When shirnking, the current implementation may still leave the
78  "deleted" bits in place which will mess up the popcount.
79  */
80  inline void resize(size_t n) {
81  len = n;
82  //need len bits
83  arrlen = (n / (sizeof(size_t) * 8)) + (n % (sizeof(size_t) * 8) > 0);
84  array = (size_t*)realloc(array, sizeof(size_t) * arrlen);
85  fix_trailing_bits();
86  }
87 
88  /// Sets all bits to 0
89  inline void clear() {
90  for (size_t i = 0; i < arrlen; ++i) array[i] = 0;
91  }
92 
93  inline bool empty() const {
94  for (size_t i = 0; i < arrlen; ++i) if (array[i]) return false;
95  return true;
96  }
97 
98  /// Sets all bits to 1
99  inline void fill() {
100  for (size_t i = 0;i < arrlen; ++i) array[i] = (size_t) - 1;
101  fix_trailing_bits();
102  }
103 
104  /// Prefetches the word containing the bit b
105  inline void prefetch(size_t b) const{
106  __builtin_prefetch(&(array[b / (8 * sizeof(size_t))]));
107  }
108 
109  /// Returns the value of the bit b
110  inline bool get(size_t b) const{
111  size_t arrpos, bitpos;
112  bit_to_pos(b, arrpos, bitpos);
113  return array[arrpos] & (size_t(1) << size_t(bitpos));
114  }
115 
116  //! Atomically sets the bit at position b to true returning the old value
117  inline bool set_bit(size_t b) {
118  // use CAS to set the bit
119  size_t arrpos, bitpos;
120  bit_to_pos(b, arrpos, bitpos);
121  const size_t mask(size_t(1) << size_t(bitpos));
122  return __sync_fetch_and_or(array + arrpos, mask) & mask;
123  }
124 
125  //! Atomically xors a bit with 1
126  inline bool xor_bit(size_t b) {
127  // use CAS to set the bit
128  size_t arrpos, bitpos;
129  bit_to_pos(b, arrpos, bitpos);
130  const size_t mask(size_t(1) << size_t(bitpos));
131  return __sync_fetch_and_xor(array + arrpos, mask) & mask;
132  }
133 
134  //! Returns the value of the word containing the bit b
135  inline size_t containing_word(size_t b) {
136  size_t arrpos, bitpos;
137  bit_to_pos(b, arrpos, bitpos);
138  return array[arrpos];
139  }
140 
141  //! Returns the value of the word containing the bit b
142  inline size_t get_containing_word_and_zero(size_t b) {
143  size_t arrpos, bitpos;
144  bit_to_pos(b, arrpos, bitpos);
145  return fetch_and_store(array[arrpos], size_t(0));
146  }
147 
148  /**
149  * \brief Transfers approximately b bits from another bitset to this bitset
150  *
151  * "Moves" at least b bits from the other bitset to this bitset
152  * starting from the given position.
153  * At return, b will contain the actual number of bits moved,
154  * and start will point to the end of the transfered region.
155  *
156  * Semantically what this accomplishes is something like:
157  *
158  * \code
159  * idx = start;
160  * if other.get_bit(idx) == false {
161  * idx = next true bit after idx in other (with loop around)
162  * }
163  * for(transferred = 0; transferred < b; transferred++) {
164  * other.clear_bit(idx);
165  * this->set_bit(idx);
166  * idx = next true bit after idx in other.
167  * if no more bits, return
168  * }
169  * \endcode
170  * However, the implementation here may transfer more than b bits.
171  * ( up to b + 2 * wordsize_in_bits )
172  */
174  size_t& start,
175  size_t& b) {
176  // must be identical in length
177  ASSERT_EQ(other.len, len);
178  ASSERT_EQ(other.arrlen, arrlen);
179  size_t arrpos, bitpos;
180  bit_to_pos(start, arrpos, bitpos);
181  size_t initial_arrpos = arrpos;
182  if (arrpos >= arrlen) arrpos = 0;
183  // ok. we will only look at arrpos
184  size_t transferred = 0;
185  while(transferred < b) {
186  if (other.array[arrpos] > 0) {
187  transferred += __builtin_popcountl(other.array[arrpos]);
188  array[arrpos] |= other.array[arrpos];
189  other.array[arrpos] = 0;
190  }
191  ++arrpos;
192  if (arrpos >= other.arrlen) arrpos = 0;
193  else if (arrpos == initial_arrpos) break;
194  }
195  start = 8 * sizeof(size_t) * arrpos;
196  b = transferred;
197  }
198 
199 
200  /** Set the bit at position b to true returning the old value.
201  Unlike set_bit(), this uses a non-atomic set which is faster,
202  but is unsafe if accessed by multiple threads.
203  */
204  inline bool set_bit_unsync(size_t b) {
205  // use CAS to set the bit
206  size_t arrpos, bitpos;
207  bit_to_pos(b, arrpos, bitpos);
208  const size_t mask(size_t(1) << size_t(bitpos));
209  bool ret = array[arrpos] & mask;
210  array[arrpos] |= mask;
211  return ret;
212  }
213 
214  //! Atomically sets the state of the bit to the new value returning the old value
215  inline bool set(size_t b, bool value) {
216  if (value) return set_bit(b);
217  else return clear_bit(b);
218  }
219 
220  /** Set the state of the bit returning the old value.
221  This version uses a non-atomic set which is faster, but
222  is unsafe if accessed by multiple threads.
223  */
224  inline bool set_unsync(size_t b, bool value) {
225  if (value) return set_bit_unsync(b);
226  else return clear_bit_unsync(b);
227  }
228 
229 
230  //! Atomically set the bit at b to false returning the old value
231  inline bool clear_bit(size_t b) {
232  // use CAS to set the bit
233  size_t arrpos, bitpos;
234  bit_to_pos(b, arrpos, bitpos);
235  const size_t test_mask(size_t(1) << size_t(bitpos));
236  const size_t clear_mask(~test_mask);
237  return __sync_fetch_and_and(array + arrpos, clear_mask) & test_mask;
238  }
239 
240  /** Clears the state of the bit returning the old value.
241  This version uses a non-atomic set which is faster, but
242  is unsafe if accessed by multiple threads.
243  */
244  inline bool clear_bit_unsync(size_t b) {
245  // use CAS to set the bit
246  size_t arrpos, bitpos;
247  bit_to_pos(b, arrpos, bitpos);
248  const size_t test_mask(size_t(1) << size_t(bitpos));
249  const size_t clear_mask(~test_mask);
250  bool ret = array[arrpos] & test_mask;
251  array[arrpos] &= clear_mask;
252  return ret;
253  }
254 
255  struct bit_pos_iterator {
256  typedef std::input_iterator_tag iterator_category;
257  typedef size_t value_type;
258  typedef size_t difference_type;
259  typedef const size_t reference;
260  typedef const size_t* pointer;
261  size_t pos;
262  const dense_bitset* db;
263  bit_pos_iterator():pos(-1),db(NULL) {}
264  bit_pos_iterator(const dense_bitset* const db, size_t pos):pos(pos),db(db) {}
265 
266  size_t operator*() const {
267  return pos;
268  }
269  size_t operator++(){
270  if (db->next_bit(pos) == false) pos = (size_t)(-1);
271  return pos;
272  }
273  size_t operator++(int){
274  size_t prevpos = pos;
275  if (db->next_bit(pos) == false) pos = (size_t)(-1);
276  return prevpos;
277  }
278  bool operator==(const bit_pos_iterator& other) const {
279  ASSERT_TRUE(db == other.db);
280  return other.pos == pos;
281  }
282  bool operator!=(const bit_pos_iterator& other) const {
283  ASSERT_TRUE(db == other.db);
284  return other.pos != pos;
285  }
286  };
287 
288  typedef bit_pos_iterator iterator;
289  typedef bit_pos_iterator const_iterator;
290 
291 
292  bit_pos_iterator begin() const {
293  size_t pos;
294  if (first_bit(pos) == false) pos = size_t(-1);
295  return bit_pos_iterator(this, pos);
296  }
297 
298  bit_pos_iterator end() const {
299  return bit_pos_iterator(this, (size_t)(-1));
300  }
301 
302  /** Returns true with b containing the position of the
303  first bit set to true.
304  If such a bit does not exist, this function returns false.
305  */
306  inline bool first_bit(size_t &b) const {
307  for (size_t i = 0; i < arrlen; ++i) {
308  if (array[i]) {
309  b = (size_t)(i * (sizeof(size_t) * 8)) + first_bit_in_block(array[i]);
310  return true;
311  }
312  }
313  return false;
314  }
315 
316 
317  /** Returns true with b containing the position of the
318  first bit set to false.
319  If such a bit does not exist, this function returns false.
320  */
321  inline bool first_zero_bit(size_t &b) const {
322  for (size_t i = 0; i < arrlen; ++i) {
323  if (~array[i]) {
324  b = (size_t)(i * (sizeof(size_t) * 8)) + first_bit_in_block(~array[i]);
325  return true;
326  }
327  }
328  return false;
329  }
330 
331  /** Where b is a bit index, this function will return in b,
332  the position of the next bit set to true, and return true.
333  If all bits after b are false, this function returns false.
334  */
335  inline bool next_bit(size_t &b) const {
336  size_t arrpos, bitpos;
337  bit_to_pos(b, arrpos, bitpos);
338  //try to find the next bit in this block
339  bitpos = next_bit_in_block(bitpos, array[arrpos]);
340  if (bitpos != 0) {
341  b = (size_t)(arrpos * (sizeof(size_t) * 8)) + bitpos;
342  return true;
343  }
344  else {
345  // we have to loop through the rest of the array
346  for (size_t i = arrpos + 1; i < arrlen; ++i) {
347  if (array[i]) {
348  b = (size_t)(i * (sizeof(size_t) * 8)) + first_bit_in_block(array[i]);
349  return true;
350  }
351  }
352  }
353  return false;
354  }
355 
356  /// Returns the number of bits in this bitset
357  inline size_t size() const {
358  return len;
359  }
360 
361  /// Serializes this bitset to an archive
362  inline void save(oarchive& oarc) const {
363  oarc <<len << arrlen;
364  if (arrlen > 0) serialize(oarc, array, arrlen*sizeof(size_t));
365  }
366 
367  /// Deserializes this bitset from an archive
368  inline void load(iarchive& iarc) {
369  if (array != NULL) free(array);
370  array = NULL;
371  iarc >> len >> arrlen;
372  if (arrlen > 0) {
373  array = (size_t*)malloc(arrlen*sizeof(size_t));
374  deserialize(iarc, array, arrlen*sizeof(size_t));
375  }
376  }
377 
378 
379  size_t popcount() const {
380  size_t ret = 0;
381  for (size_t i = 0;i < arrlen; ++i) {
382  ret += __builtin_popcountl(array[i]);
383  }
384  return ret;
385  }
386 
387  dense_bitset operator&(const dense_bitset& other) const {
388  ASSERT_EQ(size(), other.size());
389  dense_bitset ret(size());
390  for (size_t i = 0; i < arrlen; ++i) {
391  ret.array[i] = array[i] & other.array[i];
392  }
393  return ret;
394  }
395 
396 
397  dense_bitset operator|(const dense_bitset& other) const {
398  ASSERT_EQ(size(), other.size());
399  dense_bitset ret(size());
400  for (size_t i = 0; i < arrlen; ++i) {
401  ret.array[i] = array[i] | other.array[i];
402  }
403  return ret;
404  }
405 
406  dense_bitset operator-(const dense_bitset& other) const {
407  ASSERT_EQ(size(), other.size());
408  dense_bitset ret(size());
409  for (size_t i = 0; i < arrlen; ++i) {
410  ret.array[i] = array[i] - (array[i] & other.array[i]);
411  }
412  return ret;
413  }
414 
415 
416  dense_bitset& operator&=(const dense_bitset& other) {
417  ASSERT_EQ(size(), other.size());
418  for (size_t i = 0; i < arrlen; ++i) {
419  array[i] &= other.array[i];
420  }
421  return *this;
422  }
423 
424 
425  dense_bitset& operator|=(const dense_bitset& other) {
426  ASSERT_EQ(size(), other.size());
427  for (size_t i = 0; i < arrlen; ++i) {
428  array[i] |= other.array[i];
429  }
430  return *this;
431  }
432 
433  dense_bitset& operator-=(const dense_bitset& other) {
434  ASSERT_EQ(size(), other.size());
435  for (size_t i = 0; i < arrlen; ++i) {
436  array[i] = array[i] - (array[i] & other.array[i]);
437  }
438  return *this;
439  }
440 
441  void invert() {
442  for (size_t i = 0; i < arrlen; ++i) {
443  array[i] = ~array[i];
444  }
445  fix_trailing_bits();
446  }
447 
448  private:
449 
450  inline static void bit_to_pos(size_t b, size_t& arrpos, size_t& bitpos) {
451  // the compiler better optimize this...
452  arrpos = b / (8 * sizeof(size_t));
453  bitpos = b & (8 * sizeof(size_t) - 1);
454  }
455 
456  // returns 0 on failure
457  inline size_t next_bit_in_block(const size_t& b, const size_t& block) const {
458  size_t belowselectedbit = size_t(-1) - (((size_t(1) << b) - 1)|(size_t(1)<<b));
459  size_t x = block & belowselectedbit ;
460  if (x == 0) return 0;
461  else return (size_t)__builtin_ctzl(x);
462  }
463 
464  // returns 0 on failure
465  inline size_t first_bit_in_block(const size_t& block) const{
466  if (block == 0) return 0;
467  else return (size_t)__builtin_ctzl(block);
468  }
469 
470 
471  void fix_trailing_bits() {
472  // how many bits are in the last block
473  size_t lastbits = len % (8 * sizeof(size_t));
474  if (lastbits == 0) return;
475  array[arrlen - 1] &= ((size_t(1) << lastbits) - 1);
476  }
477 
478  size_t* array;
479  size_t len;
480  size_t arrlen;
481 
482  template <int len>
483  friend class fixed_dense_bitset;
484  };
485 
486 
487 
488 
489 
490 
491 
492 
493 
494 
495 
496 
497 
498 
499 
500 
501 
502 
503 
504 
505 
506 
507 
508 
509 
510 
511  /**
512  Like bitset, but of a fixed length as defined by the template parameter
513  */
514  template <int len>
516  public:
517  /// Constructs a bitset of 0 length
519  clear();
520  }
521 
522  /// Make a copy of the bitset db
524  *this = db;
525  }
526 
527  /** Initialize this fixed dense bitset by copying
528  ceil(len/(wordlen)) words from mem
529  */
530  void initialize_from_mem(void* mem, size_t memlen) {
531  memcpy(array, mem, memlen);
532  }
533 
534  /// destructor
536 
537  /// Make a copy of the bitset db
539  memcpy(array, db.array, sizeof(size_t) * arrlen);
540  return *this;
541  }
542 
543  /// Sets all bits to 0
544  inline void clear() {
545  memset((void*)array, 0, sizeof(size_t) * arrlen);
546  }
547 
548  /// Sets all bits to 1
549  inline void fill() {
550  for (size_t i = 0;i < arrlen; ++i) array[i] = -1;
551  fix_trailing_bits();
552  }
553 
554  inline bool empty() const {
555  for (size_t i = 0; i < arrlen; ++i) if (array[i]) return false;
556  return true;
557  }
558 
559  /// Prefetches the word containing the bit b
560  inline void prefetch(size_t b) const{
561  __builtin_prefetch(&(array[b / (8 * sizeof(size_t))]));
562  }
563 
564  /// Returns the value of the bit b
565  inline bool get(size_t b) const{
566  size_t arrpos, bitpos;
567  bit_to_pos(b, arrpos, bitpos);
568  return array[arrpos] & (size_t(1) << size_t(bitpos));
569  }
570 
571  //! Atomically sets the bit at b to true returning the old value
572  inline bool set_bit(size_t b) {
573  // use CAS to set the bit
574  size_t arrpos, bitpos;
575  bit_to_pos(b, arrpos, bitpos);
576  const size_t mask(size_t(1) << size_t(bitpos));
577  return __sync_fetch_and_or(array + arrpos, mask) & mask;
578  }
579 
580 
581  //! Returns the value of the word containing the bit b
582  inline size_t containing_word(size_t b) {
583  size_t arrpos, bitpos;
584  bit_to_pos(b, arrpos, bitpos);
585  return array[arrpos];
586  }
587 
588 
589  /** Set the bit at position b to true returning the old value.
590  Unlike set_bit(), this uses a non-atomic set which is faster,
591  but is unsafe if accessed by multiple threads.
592  */
593  inline bool set_bit_unsync(size_t b) {
594  // use CAS to set the bit
595  size_t arrpos, bitpos;
596  bit_to_pos(b, arrpos, bitpos);
597  const size_t mask(size_t(1) << size_t(bitpos));
598  bool ret = array[arrpos] & mask;
599  array[arrpos] |= mask;
600  return ret;
601  }
602 
603  /** Set the state of the bit returning the old value.
604  This version uses a non-atomic set which is faster, but
605  is unsafe if accessed by multiple threads.
606  */
607  inline bool set(size_t b, bool value) {
608  if (value) return set_bit(b);
609  else return clear_bit(b);
610  }
611 
612  /** Set the state of the bit returning the old value.
613  This version uses a non-atomic set which is faster, but
614  is unsafe if accessed by multiple threads.
615  */
616  inline bool set_unsync(size_t b, bool value) {
617  if (value) return set_bit_unsync(b);
618  else return clear_bit_unsync(b);
619  }
620 
621 
622  //! Atomically set the bit at b to false returning the old value
623  inline bool clear_bit(size_t b) {
624  // use CAS to set the bit
625  size_t arrpos, bitpos;
626  bit_to_pos(b, arrpos, bitpos);
627  const size_t test_mask(size_t(1) << size_t(bitpos));
628  const size_t clear_mask(~test_mask);
629  return __sync_fetch_and_and(array + arrpos, clear_mask) & test_mask;
630  }
631 
632  /** Clears the state of the bit returning the old value.
633  This version uses a non-atomic set which is faster, but
634  is unsafe if accessed by multiple threads.
635  */
636  inline bool clear_bit_unsync(size_t b) {
637  // use CAS to set the bit
638  size_t arrpos, bitpos;
639  bit_to_pos(b, arrpos, bitpos);
640  const size_t test_mask(size_t(1) << size_t(bitpos));
641  const size_t clear_mask(~test_mask);
642  bool ret = array[arrpos] & test_mask;
643  array[arrpos] &= clear_mask;
644  return ret;
645  }
646 
647 
648  struct bit_pos_iterator {
649  typedef std::input_iterator_tag iterator_category;
650  typedef size_t value_type;
651  typedef size_t difference_type;
652  typedef const size_t reference;
653  typedef const size_t* pointer;
654  size_t pos;
655  const fixed_dense_bitset* db;
656  bit_pos_iterator():pos(-1),db(NULL) {}
657  bit_pos_iterator(const fixed_dense_bitset* const db, size_t pos):pos(pos),db(db) {}
658 
659  size_t operator*() const {
660  return pos;
661  }
662  size_t operator++(){
663  if (db->next_bit(pos) == false) pos = (size_t)(-1);
664  return pos;
665  }
666  size_t operator++(int){
667  size_t prevpos = pos;
668  if (db->next_bit(pos) == false) pos = (size_t)(-1);
669  return prevpos;
670  }
671  bool operator==(const bit_pos_iterator& other) const {
672  ASSERT_TRUE(db == other.db);
673  return other.pos == pos;
674  }
675  bool operator!=(const bit_pos_iterator& other) const {
676  ASSERT_TRUE(db == other.db);
677  return other.pos != pos;
678  }
679  };
680 
681  typedef bit_pos_iterator iterator;
682  typedef bit_pos_iterator const_iterator;
683 
684 
685  bit_pos_iterator begin() const {
686  size_t pos;
687  if (first_bit(pos) == false) pos = size_t(-1);
688  return bit_pos_iterator(this, pos);
689  }
690 
691  bit_pos_iterator end() const {
692  return bit_pos_iterator(this, (size_t)(-1));
693  }
694 
695  /** Returns true with b containing the position of the
696  first bit set to true.
697  If such a bit does not exist, this function returns false.
698  */
699  inline bool first_bit(size_t &b) const {
700  for (size_t i = 0; i < arrlen; ++i) {
701  if (array[i]) {
702  b = (size_t)(i * (sizeof(size_t) * 8)) + first_bit_in_block(array[i]);
703  return true;
704  }
705  }
706  return false;
707  }
708 
709  /** Returns true with b containing the position of the
710  first bit set to false.
711  If such a bit does not exist, this function returns false.
712  */
713  inline bool first_zero_bit(size_t &b) const {
714  for (size_t i = 0; i < arrlen; ++i) {
715  if (~array[i]) {
716  b = (size_t)(i * (sizeof(size_t) * 8)) + first_bit_in_block(~array[i]);
717  return true;
718  }
719  }
720  return false;
721  }
722 
723 
724 
725  /** Where b is a bit index, this function will return in b,
726  the position of the next bit set to true, and return true.
727  If all bits after b are false, this function returns false.
728  */
729  inline bool next_bit(size_t &b) const {
730  size_t arrpos, bitpos;
731  bit_to_pos(b, arrpos, bitpos);
732  //try to find the next bit in this block
733  bitpos = next_bit_in_block(bitpos, array[arrpos]);
734  if (bitpos != 0) {
735  b = (size_t)(arrpos * (sizeof(size_t) * 8)) + bitpos;
736  return true;
737  }
738  else {
739  // we have to loop through the rest of the array
740  for (size_t i = arrpos + 1; i < arrlen; ++i) {
741  if (array[i]) {
742  b = (size_t)(i * (sizeof(size_t) * 8)) + first_bit_in_block(array[i]);
743  return true;
744  }
745  }
746  }
747  return false;
748  }
749 
750  /// Returns the number of bits in this bitset
751  inline size_t size() const {
752  return len;
753  }
754 
755  /// Serializes this bitset to an archive
756  inline void save(oarchive& oarc) const {
757  //oarc <<len << arrlen;
758  //if (arrlen > 0)
759  serialize(oarc, array, arrlen*sizeof(size_t));
760  }
761 
762  /// Deserializes this bitset from an archive
763  inline void load(iarchive& iarc) {
764  /*size_t l;
765  size_t arl;
766  iarc >> l >> arl;
767  ASSERT_EQ(l, len);
768  ASSERT_EQ(arl, arrlen);*/
769  //if (arrlen > 0) {
770  deserialize(iarc, array, arrlen*sizeof(size_t));
771  //}
772  }
773 
774  size_t popcount() const {
775  size_t ret = 0;
776  for (size_t i = 0;i < arrlen; ++i) {
777  ret += __builtin_popcountl(array[i]);
778  }
779  return ret;
780  }
781 
782  private:
783  inline static void bit_to_pos(size_t b, size_t &arrpos, size_t &bitpos) {
784  // the compiler better optimize this...
785  arrpos = b / (8 * sizeof(size_t));
786  bitpos = b & (8 * sizeof(size_t) - 1);
787  }
788 
789 
790  // returns 0 on failure
791  inline size_t next_bit_in_block(const size_t &b, const size_t &block) const {
792  size_t belowselectedbit = size_t(-1) - (((size_t(1) << b) - 1)|(size_t(1)<<b));
793  size_t x = block & belowselectedbit ;
794  if (x == 0) return 0;
795  else return (size_t)__builtin_ctzl(x);
796  }
797 
798  // returns 0 on failure
799  inline size_t first_bit_in_block(const size_t &block) const {
800  // use CAS to set the bit
801  if (block == 0) return 0;
802  else return (size_t)__builtin_ctzl(block);
803  }
804 
805  void fix_trailing_bits() {
806  // how many bits are in the last block
807  size_t lastbits = len % (8 * sizeof(size_t));
808  if (lastbits == 0) return;
809  array[arrlen - 1] &= ((size_t(1) << lastbits) - 1);
810  }
811 
812 
813  static const size_t arrlen;
814  size_t array[len / (sizeof(size_t) * 8) + (len % (sizeof(size_t) * 8) > 0)];
815  };
816 
817  template<int len>
818  const size_t fixed_dense_bitset<len>::arrlen = len / (sizeof(size_t) * 8) + (len % (sizeof(size_t) * 8) > 0);
819 }
820 #endif
821