TiledArray  0.7.0
bitset.h
Go to the documentation of this file.
1 /*
2  * This file is a part of TiledArray.
3  * Copyright (C) 2013 Virginia Tech
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 #ifndef TILEDARRAY_BITSET_H__INCLUDED
21 #define TILEDARRAY_BITSET_H__INCLUDED
22 
23 #include <TiledArray/error.h>
25 #include <climits>
26 #include <iosfwd>
27 #include <iomanip>
28 
29 namespace TiledArray {
30  namespace detail {
31 
33 
39  template <typename Block = unsigned long>
40  class Bitset {
41  private:
42  static_assert( (std::is_integral<Block>::value || std::is_same<Block, char>::value),
43  "Bitset template type Block must be an integral or char type");
44 
45  static const std::size_t block_bits;
46  static const Block zero;
47  static const Block one;
48  static const Block xffff;
49 
50  public:
51 
52  class reference {
53 
54  friend class Bitset<Block>;
55 
56  reference(Block& block, Block mask) : block_(block), mask_(mask) { }
57 
58  // Not allowed
59  void operator&();
60 
61  public:
62 
63  reference& operator=(bool value) {
64  assign(value);
65  return *this;
66  }
67 
68  reference& operator=(const reference& other) {
69  assign(other);
70  return *this;
71  }
72 
73  reference& operator|=(bool value) {
74  if(value) set();
75  return *this;
76  }
77 
78  reference& operator&=(bool value) {
79  if(!value) reset();
80  return *this;
81  }
82 
83  reference& operator^=(bool value) {
84  if(value) flip();
85  return *this;
86  }
87 
88  reference& operator-=(bool value) {
89  if(value) reset();
90  return *this;
91  }
92 
93  operator bool() const { return block_ & mask_; }
94 
95  bool operator~() const { return !(block_ & mask_); }
96 
98  block_ ^= mask_;
99  return *this;
100  }
101 
102  private:
103 
104  void assign(bool value) {
105  if(value)
106  set();
107  else
108  reset();
109  }
110 
111  void set() { block_ |= mask_; }
112 
113  void reset() { block_ &= ~mask_; }
114 
115  Block& block_;
116  const Block mask_;
117  }; // class reference
118 
119  private:
120 
122  class ConstTransformOp {
123  public:
124  typedef std::size_t argument_type;
125  typedef Block result_type;
126 
127  ConstTransformOp(const Bitset<Block>& bitset) : bitset_(&bitset) { }
128 
129  ConstTransformOp(const ConstTransformOp& other) : bitset_(other.bitset_) { }
130 
131 
132  ConstTransformOp& operator=(const ConstTransformOp& other) {
133  bitset_ = other.bitset_;
134 
135  return *this;
136  }
137 
138  Block operator()(std::size_t i) const { return (*bitset_)[i]; }
139 
140  private:
141  const Bitset<Block>* bitset_;
142  }; // class ConstTransformOp
143 
145  class TransformOp {
146  public:
147  typedef std::size_t argument_type;
148  typedef reference result_type;
149 
150  TransformOp(const Bitset<Block>& bitset) : bitset_(bitset) { }
151  reference operator()(std::size_t i) const { return const_cast<Bitset<Block>&>(bitset_)[i]; }
152  private:
153  const Bitset<Block>& bitset_;
154  }; // class TransformOp
155 
156  public:
158  typedef Block block_type;
159  typedef Block value_type;
160  typedef Block const_reference;
161  typedef std::size_t size_type;
164 
166 
170  size_(s),
171  blocks_((size_ / block_bits) + (size_ % block_bits ? 1 : 0)),
172  set_((size_ ? new block_type[blocks_] : NULL))
173  {
174  std::fill_n(set_, blocks_, zero);
175  }
176 
178 
183  template <typename InIter>
184  Bitset(InIter first, InIter last) :
185  size_(std::distance(first, last)),
186  blocks_((size_ / block_bits) + (size_ % block_bits ? 1 : 0)),
187  set_((size_ ? new block_type[blocks_] : NULL))
188  {
189  // Initialize to zero
190  std::fill_n(set_, blocks_, zero);
191 
192  for(size_type i = 0; first != last; ++i, ++first)
193  if(*first)
194  set(i);
195  }
196 
198 
201  Bitset(const Bitset<Block>& other) :
202  size_(other.size_),
203  blocks_(other.blocks_),
204  set_((size_ ? new block_type[blocks_] : NULL))
205  {
206  std::copy(other.set_, other.set_ + blocks_, set_);
207  }
208 
210  ~Bitset() { delete [] set_; }
211 
213 
219  if(blocks_ == other.blocks_) {
220  if(this != &other) {
221  size_ = other.size_;
222  std::copy(other.set_, other.set_ + blocks_, set_);
223  }
224  } else {
225  Bitset<Block>(other).swap(*this);
226  }
227 
228  return *this;
229  }
230 
232 
237  TA_ASSERT(size_ == other.size_);
238  for(size_type i = 0; i < blocks_; ++i)
239  set_[i] |= other.set_[i];
240 
241  return *this;
242  }
243 
245 
250  TA_ASSERT(size_ == other.size_);
251  for(size_type i = 0; i < blocks_; ++i)
252  set_[i] &= other.set_[i];
253 
254  return *this;
255  }
256 
257 
259 
264  TA_ASSERT(size_ == other.size_);
265  for(size_type i = 0; i < blocks_; ++i)
266  set_[i] ^= other.set_[i];
267 
268  return *this;
269  }
270 
271  private:
272 
273  static void left_shift(Bitset<Block>& dest, const Bitset<Block>& source, size_type n) {
274  // Compute shifts
275  const size_type block_shift = dest.block_index(n);
276  const size_type bit_shift = dest.bit_index(n);
277 
278  // Compute iteration ranges
279  block_type* last = dest.set_ + dest.blocks_ - 1;
280  const block_type* const first = dest.set_ + block_shift;
281  const block_type* base = source.set_ + source.blocks_ - 1 - block_shift;
282 
283  if(bit_shift == 0) {
284  // Shift by unit strides
285  while(last >= first)
286  *last-- = *base--;
287  } else {
288  // Shift by non-unit strides
289  const block_type* base1 = base - 1;
290  const size_type reverse_bit_shift = block_bits - bit_shift;
291  while(last > first) {
292  *last-- = (*base << bit_shift) | (*base1 >> reverse_bit_shift);
293  base = base1--;
294  }
295  *last-- = (*base << bit_shift);
296  }
297 
298  // Zero the head
299  while(last >= dest.set_)
300  *last-- = zero;
301 
302  // Zero the tail
303  const size_type extra_bits = dest.size_ % block_bits;
304  if (extra_bits != 0)
305  dest.set_[dest.blocks_ - 1] &= ~(xffff << extra_bits);
306  }
307 
308  static void right_shift(Bitset<Block>& dest, const Bitset<Block>& source, size_type n) {
309  // Compute shifts
310  size_type const block_shift = block_index(n);
311  size_type const bit_shift = bit_index(n);
312 
313  // Compute iterator ranges
314  const block_type* base = source.set_ + block_shift;
315  block_type* first = dest.set_;
316  const block_type* const end = dest.set_ + dest.blocks_;
317  const block_type* const last = end - 1 - block_shift;
318 
319  if (bit_shift == 0) {
320  // Shift by unit strides
321  while(first <= last)
322  *first++ = *base++;
323  } else {
324  // Shift by non-unit strides
325  size_type const reverse_bit_shift = block_bits - bit_shift;
326  const block_type* base1 = base + 1;
327 
328  while(first < last) {
329  *first++ = (*base >> bit_shift) | (*base1 << reverse_bit_shift);
330  base = base1++;
331  }
332  *first++ = *base >> bit_shift;
333  }
334 
335  // Zero the tail
336  while(first < end)
337  *first++ = zero;
338  }
339 
340 
341  public:
342 
344  if(n >= size_)
345  reset();
346  else if(n > 0ul)
347  left_shift(*this, *this, n);
348  return *this;
349  }
350 
352  Bitset<Block> temp = Bitset<Block>(size_);
353  if(n < size_)
354  left_shift(temp, *this, n);
355  return temp;
356  }
357 
359  if(n >= size_)
360  reset();
361  else if(n > 0ul)
362  right_shift(*this, *this, n);
363  return *this;
364  }
365 
367  Bitset<Block> temp = Bitset<Block>(size_);
368  if(n < size_)
369  right_shift(temp, *this, n);
370  return temp;
371  }
372 
374 
379  TA_ASSERT(i < size_);
380  return mask(i) & set_[block_index(i)];
381  }
382 
384  TA_ASSERT(i < size_);
385  return reference(set_[block_index(i)], mask(i));
386  }
387 
388  operator bool() const {
389  const block_type* const end = set_ + blocks_;
390  for(const block_type* first = set_; first != end; ++first)
391  if(*first)
392  return true;
393 
394  return false;
395  }
396 
397  bool operator!() const {
398  const block_type* const end = set_ + blocks_;
399  for(const block_type* first = set_; first != end; ++first)
400  if(*first)
401  return false;
402 
403  return true;
404  }
405 
407  return const_iterator(0, ConstTransformOp(*this));
408  }
409 
411  return iterator(0, TransformOp(*this));
412  }
413 
414  const_iterator end() const {
415  return const_iterator(size_, ConstTransformOp(*this));
416  }
417 
419  return iterator(size_, TransformOp(*this));
420  }
421 
423 
427  void set(size_type i, bool value = true) {
428  TA_ASSERT(i < size_);
429  if(value)
430  set_[block_index(i)] |= mask(i);
431  else
432  reset(i);
433  }
434 
436 
438  void set() {
439  std::fill_n(set_, blocks_, xffff);
440 
441  // Zero the tail
442  const size_type extra_bits = bit_index(size_);
443  if (extra_bits != 0)
444  set_[blocks_ - 1] &= ~(xffff << extra_bits);
445  }
446 
448 
451  void set_range(size_type first, size_type last) {
452  if(last >= size_)
453  last = size_ - 1;
454  TA_ASSERT(first < last);
455 
456  // Get iterator and shift values
457  block_type* first_block = set_ + block_index(first);
458  const size_type first_shift = bit_index(first);
459  block_type* const last_block = set_ + block_index(last);
460  const size_type last_shift = block_bits - bit_index(last) - 1;
461 
462  // Set the first and last bits
463  if(first_block == last_block) {
464  *first_block |= (xffff << first_shift) & (xffff >> last_shift);
465  } else {
466  *first_block++ |= (xffff << first_shift);
467  *last_block |= (xffff >> last_shift);
468  }
469 
470  // Set all blocks between the first and last blocks.
471  while(first_block < last_block)
472  *first_block++ = xffff;
473  }
474 
476 
479  void set_stride(size_type first, size_type stride) {
480  for(; first < size_; first += stride)
481  set_[block_index(first)] |= mask(first);
482  }
483 
485 
488  void reset(size_type i) {
489  TA_ASSERT(i < size_);
490  set_[block_index(i)] &= ~mask(i);
491  }
492 
494 
496  void reset() {
497  std::fill_n(set_, blocks_, zero);
498  }
499 
501 
504  void flip(size_type i) {
505  TA_ASSERT(i < size_);
506  set_[block_index(i)] ^= mask(i);
507  }
508 
510 
512  void flip() {
513  for(size_type i = 0; i < blocks_; ++i)
514  set_[i] = ~set_[i];
515  }
516 
518 
520  size_type count() const {
521  size_type c = 0ul;
522  for(size_type i = 0ul; i < blocks_; ++i) {
523  block_type v = set_[i]; // temp
524  v = v - ((v >> 1) & xffff / 3);
525  v = (v & xffff / 15 * 3) + ((v >> 2) & xffff / 15 * 3);
526  v = (v + (v >> 4)) & xffff / 255 * 15;
527  c += block_type(v * (xffff / 255)) >> (sizeof(block_type) - 1) * CHAR_BIT; // count
528  }
529  return c;
530  }
531 
533 
538  const block_type* get() const { return set_; }
539 
540 
542 
547  block_type* get() { return set_; }
548 
550 
553  size_type size() const { return size_; }
554 
556 
559  size_type num_blocks() const { return blocks_; }
560 
561  void swap(Bitset_& other) {
562  std::swap(size_, other.size_);
563  std::swap(blocks_, other.blocks_);
564  std::swap(set_, other.set_);
565  }
566 
567  private:
568 
570 
573  static size_type block_index(size_type i) { return i / block_bits; }
574 
576 
579  static size_type bit_index(size_type i) { return i % block_bits; }
580 
582 
585  static block_type mask(size_type i) { return one << bit_index(i); }
586 
587  size_type size_;
588  size_type blocks_;
589  block_type* set_;
590  }; // class Bitset
591 
592  template <typename B>
593  inline void swap(Bitset<B>& b0, Bitset<B>& b1) {
594  b0.swap(b1);
595  }
596 
597  // Bitset static constant data
598  template <typename Block>
599  const std::size_t Bitset<Block>::block_bits =
600  8ul * sizeof(typename Bitset<Block>::block_type);
601  template <typename Block>
602  const Block Bitset<Block>::zero = Block(0);
603  template <typename Block>
604  const Block Bitset<Block>::one = Block(1);
605  template <typename Block>
606  const Block Bitset<Block>::xffff = ~Block(0);
607 
609 
614  template <typename Block>
616  left &= right;
617  return left;
618  }
619 
621 
626  template <typename Block>
628  left |= right;
629  return left;
630  }
631 
632 
634 
639  template <typename Block>
641  left ^= right;
642  return left;
643  }
644 
645  template <typename Block>
646  std::ostream& operator<<(std::ostream& os, const Bitset<Block>& bitset) {
647  os << std::hex;
648  for(long i = bitset.num_blocks() - 1l; i >= 0l; --i)
649  os << std::setfill('0') << std::setw(sizeof(Block)*2) << bitset.get()[i] << " ";
650 
651  os << std::setbase(10) << std::setw(0);
652  return os;
653  }
654 
655 
656  } // namespace detail
657 } // namespace TiledArray
658 
659 #endif // TILEDARRAY_BITSET_H__INCLUDED
void set_range(size_type first, size_type last)
Set all bits from first to last.
Definition: bitset.h:451
void reset()
Set all bits.
Definition: bitset.h:496
Bitset< Block > & operator<<=(size_type n)
Definition: bitset.h:343
Bitset(InIter first, InIter last)
Construct a bitset that contains s bits.
Definition: bitset.h:184
Bitset< Block > & operator>>=(size_type n)
Definition: bitset.h:358
Bitset< Block > operator^(Bitset< Block > left, const Bitset< Block > &right)
Bitwise xor operator of bitset.
Definition: bitset.h:640
Bitset< Block > operator<<(size_type n)
Definition: bitset.h:351
void swap(Bitset< B > &b0, Bitset< B > &b1)
Definition: bitset.h:593
Bitset(const Bitset< Block > &other)
Copy constructor for bitset.
Definition: bitset.h:201
std::size_t size_type
indexing size type
Definition: bitset.h:161
STL namespace.
size_type size() const
Bitset size.
Definition: bitset.h:553
void swap(Bitset_ &other)
Definition: bitset.h:561
UnaryTransformIterator< Block, ConstTransformOp > const_iterator
Const iterator type.
Definition: bitset.h:162
Bitset< Block > operator &(Bitset< Block > left, const Bitset< Block > &right)
Bitwise and operator of bitset.
Definition: bitset.h:615
const_iterator begin() const
Definition: bitset.h:406
Bitset< Block > & operator|=(const Bitset< Block > &other)
Or-assignment operator.
Definition: bitset.h:236
UnaryTransformIterator< Block, TransformOp > iterator
Iterator type.
Definition: bitset.h:163
Bitset< Block > operator|(Bitset< Block > left, const Bitset< Block > &right)
Bitwise or operator of bitset.
Definition: bitset.h:627
Block value_type
The value type.
Definition: bitset.h:159
Bitset< Block > Bitset_
This object type.
Definition: bitset.h:157
reference & operator|=(bool value)
Definition: bitset.h:73
#define TA_ASSERT(a)
Definition: error.h:107
const_iterator end() const
Definition: bitset.h:414
Bitset< Block > operator>>(size_type n)
Definition: bitset.h:366
Bitset< Block > & operator=(const Bitset< Block > &other)
Assignment operator.
Definition: bitset.h:218
Fixed size bitset.
Definition: bitset.h:40
~Bitset()
Destructor.
Definition: bitset.h:210
void reset(size_type i)
Reset a bit.
Definition: bitset.h:488
reference & operator=(const reference &other)
Definition: bitset.h:68
reference & operator &=(bool value)
Definition: bitset.h:78
DistArray< Tile, Policy > copy(const DistArray< Tile, Policy > &a)
Definition: utils.h:58
void set_stride(size_type first, size_type stride)
Set elements separated by stride.
Definition: bitset.h:479
size_type count() const
Count the number of non-zero bits.
Definition: bitset.h:520
void flip(size_type i)
Flip a bit.
Definition: bitset.h:504
void zero(DistArray< Tile, Policy > &a)
Definition: utils.h:63
const_reference operator[](size_type i) const
Bit accessor operator.
Definition: bitset.h:378
Bitset(size_type s)
Construct a bitset that contains s bits.
Definition: bitset.h:169
Bitset< Block > & operator^=(const Bitset< Block > &other)
And-assignment operator.
Definition: bitset.h:263
bool operator!() const
Definition: bitset.h:397
void flip()
Flip all bits.
Definition: bitset.h:512
reference operator[](size_type i)
Definition: bitset.h:383
Block const_reference
Constant reference to a bit.
Definition: bitset.h:160
size_type num_blocks() const
Bitset block size.
Definition: bitset.h:559
Bitset< Block > & operator &=(const Bitset< Block > &other)
And-assignment operator.
Definition: bitset.h:249
reference & operator-=(bool value)
Definition: bitset.h:88
reference & operator^=(bool value)
Definition: bitset.h:83
reference & operator=(bool value)
Definition: bitset.h:63
Block block_type
The type used to store the data.
Definition: bitset.h:158
void assign(DistArray< Tile, Policy > &m1, const DistArray< Tile, Policy > &m2)
Definition: utils.h:123
const block_type * get() const
Data pointer accessor.
Definition: bitset.h:538