strusBase  0.17
bitset.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Patrick P. Frey
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  */
10 #ifndef _STRUS_BITSET_HPP_INCLUDED
11 #define _STRUS_BITSET_HPP_INCLUDED
13 #include "strus/base/stdint.h"
14 #include <vector>
15 
16 namespace strus {
17 
18 template <int SIZE>
20 {
21  static uint64_t mask( uint64_t hi) {return hi & (((uint64_t)1 << (SIZE % 64)) -1);}
22 };
23 template <>
25 {
26  static uint64_t mask( uint64_t hi) {return hi;}
27 };
28 
29 
30 template <int SIZE>
31 class bitset
32 {
33 public:
35  {
36  int ii=0;
37  for (; ii<ArSize; ++ii)
38  {
39  m_ar[ ii] = 0;
40  }
41  }
42  bitset( const bitset& o)
43  {
44  int ii=0;
45  for (; ii<ArSize; ++ii)
46  {
47  m_ar[ ii] = o.m_ar[ ii];
48  }
49  }
50 
51  bool set( int pos, bool value)
52  {
53  if ((unsigned int)pos >= SIZE) return false;
54  int idx = (unsigned int)pos / 64;
55  int ofs = (unsigned int)pos % 64;
56  if (value)
57  {
58  m_ar[ idx] |= ((uint64_t)1 << ofs);
59  }
60  else
61  {
62  m_ar[ idx] &= ~((uint64_t)1 << ofs);
63  }
64  return true;
65  }
66 
67  bool test( int pos) const
68  {
69  if ((unsigned int)pos >= SIZE) return false;
70  int idx = (unsigned int)pos / 64;
71  int ofs = (unsigned int)pos % 64;
72  return (m_ar[ idx] & ((uint64_t)1 << ofs)) != 0;
73  }
74 
75  bool insert( int pos, bool value)
76  {
77  if ((unsigned int)pos >= SIZE) return false;
78  unsigned int idx = (unsigned int)pos / 64;
79  unsigned int ofs = (unsigned int)pos % 64;
80  unsigned int ii = ArSize-1;
81  for (; ii > idx; --ii)
82  {
83  if (ii < ArSize-1)
84  {
85  m_ar[ ii+1] |= (m_ar[ ii] & ((uint64_t)1UL << 63)) >> 63;
86  }
87  m_ar[ ii] <<= 1;
88  }
89  if (ii < ArSize-1)
90  {
91  m_ar[ ii+1] |= (m_ar[ ii] & ((uint64_t)1UL << 63)) >> 63;
92  }
93  uint64_t left( m_ar[ idx]);
94  uint64_t right( left);
95  uint64_t newbit = ((uint64_t)value << ofs);
96  left >>= ofs;
97  left <<= ofs;
98  right ^= left;
99  left <<= 1;
100  left |= newbit;
101  m_ar[ idx] = left | right;
102  if (idx == ArSize-1)
103  {
104  m_ar[ idx] = bitset_hi_bitmask<SIZE % 64>::mask( m_ar[ idx]);
105  }
106  return true;
107  }
108 
109  bool remove( int pos)
110  {
111  if ((unsigned int)pos >= SIZE) return false;
112  unsigned int idx = (unsigned int)pos / 64;
113  unsigned int ofs = (unsigned int)pos % 64;
114  uint64_t hibit = 0;
115  unsigned int ii = ArSize-1;
116  for (; ii > idx; --ii)
117  {
118  uint64_t lobit = m_ar[ ii] & 1;
119  m_ar[ ii] >>= 1;
120  m_ar[ ii] |= hibit;
121  hibit = lobit << 63;
122  }
123  if (ofs == 63)
124  {
125  //... this case has to be handled specially, because behavior of >> 64 undefined
126  m_ar[ idx] &= ~((uint64_t)1 << 63);
127  m_ar[ idx] |= hibit;
128  }
129  else
130  {
131  uint64_t left( m_ar[ idx]);
132  uint64_t delbit = left & ((uint64_t)1 << ofs);
133  uint64_t right( left ^ delbit);
134  left >>= (ofs+1);
135  left <<= (ofs+1);
136  right ^= left;
137  left >>= 1;
138  left |= hibit;
139  m_ar[ ii] = left | right;
140  }
141  return true;
142  }
143 
144  void reset()
145  {
146  int ai = 0;
147  for (; ai < ArSize; ++ai) m_ar[ai] = 0;
148  }
149 
150  int next( int pos) const
151  {
152  ++pos;
153  int idx = (unsigned int)pos / 64;
154  int ofs = (unsigned int)pos % 64;
155  if (idx >= ArSize) return -1;
156  uint64_t start = m_ar[ idx];
157  start &= ~((((uint64_t)1) << ofs) - 1);
158  if (start)
159  {
160  int pi = BitOperations::bitScanForward( start);
161  return idx * 64 + pi - 1;
162  }
163  for (++idx; idx < ArSize; ++idx)
164  {
165  if (m_ar[ idx])
166  {
167  int pi = BitOperations::bitScanForward( m_ar[ idx]);
168  return idx * 64 + pi - 1;
169  }
170  }
171  return -1;
172  }
173  int first() const
174  {
175  return next( -1);
176  }
177 
178  std::vector<int> elements() const
179  {
180  std::vector<int> rt;
181  int pi = first();
182  for (; pi >= 0; pi = next(pi))
183  {
184  rt.push_back( pi);
185  }
186  return rt;
187  }
188 
189  bool empty() const
190  {
191  for (int ai=0; ai<ArSize; ++ai)
192  {
193  if (m_ar[ai]) return false;
194  }
195  return true;
196  }
197 
198 private:
199  enum {ArSize=(SIZE+63)/64};
200  uint64_t m_ar[ ArSize];
201 };
202 
203 }//namespace
204 #endif
205 
206 
bool test(int pos) const
Definition: bitset.hpp:67
bool set(int pos, bool value)
Definition: bitset.hpp:51
bitset(const bitset &o)
Definition: bitset.hpp:42
bitset()
Definition: bitset.hpp:34
Definition: bitset.hpp:19
static uint64_t mask(uint64_t hi)
Definition: bitset.hpp:21
void reset()
Definition: bitset.hpp:144
bool empty() const
Definition: bitset.hpp:189
int next(int pos) const
Definition: bitset.hpp:150
Definition: bitset.hpp:31
static unsigned int bitScanForward(const uint32_t &idx)
Definition: bitOperations.hpp:107
static uint64_t mask(uint64_t hi)
Definition: bitset.hpp:26
bool insert(int pos, bool value)
Definition: bitset.hpp:75
int first() const
Definition: bitset.hpp:173
std::vector< int > elements() const
Definition: bitset.hpp:178