Honeycomb  0.1
Component-Model Framework
BitSet.h
Go to the documentation of this file.
1 // Honeycomb, Copyright (C) 2015 NewGamePlus Inc. Distributed under the Boost Software License v1.0.
2 #pragma once
3 
4 #include "Honey/Math/Numeral.h"
6 #include "Honey/String/Bytes.h"
7 
8 namespace honey
9 {
10 
12 template<class Block = uint64, class Alloc_ = std::allocator<Block>>
13 class BitSet_
14 {
15  typedef typename Alloc_::template rebind<Block>::other Alloc;
16 public:
17  static_assert(std::is_unsigned<Block>::value, "block type must be unsigned");
18 
20  BitSet_(szt size = 0, bool val = false, const Alloc& a = Alloc()) :
21  _alloc(a),
22  _size(0),
23  _blockCount(0),
24  _blocks(nullptr, finalize<Block,Alloc>(_alloc))
25  {
26  if (size) resize(size, val);
27  }
28 
30  BitSet_(const Bytes& bs, const Alloc& a = Alloc()) :
31  BitSet_(bs.size()*8, false, a)
32  {
33  szt i = 0;
34  for (auto b: bs) for (auto j: range(8)) set(i++, (b >> (7-j)) & 1);
35  }
36 
38  void resize(szt size, bool val = false)
39  {
40  assert(size >= 0);
41  if (size == _size) return;
42  //Allocate new blocks
43  szt blockCount = size / bitsPerBlock + (size % bitsPerBlock != 0);
44  Block* blocks = nullptr;
45  if (size)
46  {
47  blocks = new (_alloc.allocate(blockCount)) Block[blockCount];
48  //Copy old blocks
49  if (_blockCount) std::copy(_blocks.get(), _blocks.get() + (blockCount < _blockCount ? blockCount : _blockCount), blocks);
50  }
51  //Init new bits if new array is larger
52  sdt blockDif = blockCount - _blockCount;
53  if (blockDif >= 0)
54  {
55  //Init all new blocks
56  std::fill_n(blocks + _blockCount, blockDif, val ? ~Block(0) : 0);
57  //Init first new bits before new blocks
58  Block firstBits = unusedBitsMask();
59  if (firstBits) val ? blocks[_blockCount-1] |= firstBits : blocks[_blockCount-1] &= ~firstBits;
60  }
61  //Assign new array
62  _size = size;
63  _blockCount = blockCount;
64  _blocks.set(blocks);
65  //Zero out unused bits
66  trim();
67  }
68 
70  void set(szt index) { assert(index < size()); _blocks[blockIndex(index)] |= bitMask(index); }
72  void set(szt index, bool val) { val ? set(index) : reset(index); }
74  void set() { if (!_blockCount) return; std::fill_n(_blocks.get(), _blockCount, ~Block(0)); trim(); }
76  void reset(szt index) { assert(index < size()); _blocks[blockIndex(index)] &= ~bitMask(index); }
78  void reset() { if (!_blockCount) return; std::fill_n(_blocks.get(), _blockCount, 0); }
80  void flip(szt index) { assert(index < size()); _blocks[blockIndex(index)] ^= bitMask(index); }
82  void flip() { for (szt i = 0; i < _blockCount; ++i) _blocks[i] = ~_blocks[i]; trim(); }
84  bool test(szt index) const { assert(index < size()); return _blocks[blockIndex(index)] & bitMask(index); }
85 
87  bool all() const
88  {
89  if (!_blockCount) return false;
90  for (szt i = 0; i < _blockCount-1; ++i) if (~_blocks[i]) return false;
91  return _blocks[_blockCount-1] == ~unusedBitsMask();
92  }
93 
95  bool any() const { for (szt i = 0; i < _blockCount; ++i) { if (_blocks[i]) return true; } return false; }
97  bool none() const { return !any(); }
98 
100  szt count() const { szt count = 0; for (szt i = 0; i < _blockCount; ++i) count += BitOp::popCount(_blocks[i]); return count; }
101 
103  szt size() const { return _size; }
105  szt blockCount() const { return _blockCount; }
106 
107  static const szt bitsPerBlock = sizeof(Block)*8;
108 
110  const Block* blocks() const { return _blocks; }
111  Block* blocks() { return _blocks; }
112 
114  Bytes toBytes() const
115  {
116  Bytes bs;
117  bs.resize(size()/8 + (size()%8 != 0));
118  szt i = 0;
119  for (auto& b: bs) for (auto j: range(8)) if (i < size()) b |= test(i++) << (7-j);
120  return bs;
121  }
122 
123 private:
124  static const szt bitToBlockShift = mt::log2Floor<bitsPerBlock>::value;
125  static const szt bitOffsetMask = bitsPerBlock-1;
126 
127  static szt blockIndex(szt index) { return index >> bitToBlockShift; }
128  static Block bitMask(szt index) { return Block(1) << (index & bitOffsetMask); }
129 
131  Block unusedBitsMask() const { szt bits = _size % bitsPerBlock; return bits ? ~((Block(1) << bits) - 1) : 0; }
133  void trim() { if (!_blockCount) return; _blocks[_blockCount-1] &= ~unusedBitsMask(); }
134 
135  Alloc _alloc;
136  szt _size;
137  szt _blockCount;
138  UniquePtr<Block, finalize<Block,Alloc>> _blocks;
139 };
140 
142 
143 }
BitSet_(const Bytes &bs, const Alloc &a=Alloc())
Construct from bytes in big-endian bit order (the first index will contain the MSB) ...
Definition: BitSet.h:30
BitSet_ BitSet
Definition: BitSet.h:141
Bytes toBytes() const
Create Bytes from big-endian bits (the first index contains the MSB)
Definition: BitSet.h:114
ptrdiff_t sdt
Size difference type, shorthand for ptrdiff_t.
Definition: Core.h:92
A compact array of bits. Dynamic version of std::bitset.
Definition: BitSet.h:13
void reset()
Set all bits false.
Definition: BitSet.h:78
void set(szt index, bool val)
Set bit to value.
Definition: BitSet.h:72
szt size() const
Number of bits in the bit array.
Definition: BitSet.h:103
bool all() const
Test if all bits are true.
Definition: BitSet.h:87
void reset(szt index)
Set bit to false.
Definition: BitSet.h:76
std::enable_if< mt::isIterator< Iter1 >::value, Range_< Iter1, Iter2 > >::type range(Iter1 &&first, Iter2 &&last)
Range from iterators [first, last)
Definition: Range.h:116
void set(szt index)
Set bit to true.
Definition: BitSet.h:70
#define assert(...)
Forwards to assert_#args. See assert_1(), assert_2().
Definition: Debug.h:24
bool none() const
Test if no bits are true.
Definition: BitSet.h:97
void resize(szt size, bool val=false)
Resize array to contain size number of bits, with new bits initialized to val
Definition: BitSet.h:38
void set()
Set all bits to true.
Definition: BitSet.h:74
String of bytes.
Definition: Bytes.h:26
szt count() const
Count number of true values in bit array.
Definition: BitSet.h:100
size_t szt
Size type, shorthand for size_t.
Definition: Core.h:90
Block * blocks()
Definition: BitSet.h:111
Functor to delete a pointer.
Definition: Allocator.h:161
void flip()
Flip values of all bits.
Definition: BitSet.h:82
bool any() const
Test if any bits are true.
Definition: BitSet.h:95
Calc log base 2 of unsigned integer, rounded down to nearest integer. Returns -1 if x is zero...
Definition: Meta.h:312
static const szt bitsPerBlock
Definition: BitSet.h:107
void flip(szt index)
Flip value of bit.
Definition: BitSet.h:80
szt blockCount() const
Number of blocks that the bit array has been split up into.
Definition: BitSet.h:105
bool test(szt index) const
Get bit value.
Definition: BitSet.h:84
Global Honeycomb namespace.
const Block * blocks() const
Get access to raw blocks that hold the bits. Bit index 0 is the LSB of block 0.
Definition: BitSet.h:110
BitSet_(szt size=0, bool val=false, const Alloc &a=Alloc())
Construct array with size number of bits, each initialized to val
Definition: BitSet.h:20