CFugue
BitVector.h
1 #ifndef __BITVECTOR_H__D40A115A_BC2F_4125_A068_D151EFFA2677
2 #define __BITVECTOR_H__D40A115A_BC2F_4125_A068_D151EFFA2677
3 
4 //#ifdef _DEBUG
5 #include "StrUtils.h"
6 //#endif
7 
8 #include <vector>
9 
11 {
12  typedef unsigned long BASEUNIT;
13 
14  typedef std::vector<BASEUNIT> BASEUNITVECTOR;
15 
16  BASEUNITVECTOR m_vecBaseUnits;
17 
18  enum { BitsPerUnit = sizeof(BASEUNIT) * 8 };
19 
20 public:
21  CBitVector(){}
22 
23  ~CBitVector(){}
24 
25  CBitVector(CBitVector&& that) : m_vecBaseUnits(std::move(that.m_vecBaseUnits))
26  {
27  }
28 
29  CBitVector(const CBitVector& that)
30  {
31  *this = that;
32  }
33 
34  inline CBitVector& operator=(const CBitVector& that)
35  {
36  this->m_vecBaseUnits = that.m_vecBaseUnits ;
37  return *this;
38  }
39 
40  inline CBitVector& operator=(CBitVector&& that)
41  {
42  m_vecBaseUnits = std::move(that.m_vecBaseUnits);
43  return *this;
44  }
45 
46  // IsBitSet() is same as operator[], but returns 0 for out-of-bound values
47  inline bool IsBitSet(const int nBitIndex) const
48  {
49  return nBitIndex >=0 &&
50  nBitIndex < BitsPerUnit *(int)this->m_vecBaseUnits.size() &&
51  (this->m_vecBaseUnits[nBitIndex/BitsPerUnit] & ((BASEUNIT)1 << (nBitIndex % BitsPerUnit)));
52  }
53 
54  inline bool operator[](int nBitIndex) const
55  {
56  _ASSERTE(nBitIndex >=0 && nBitIndex < BitsPerUnit *(int)this->m_vecBaseUnits.size());
57  // This is a faster version of IsBitSet(),
58  // but should be used with care in Release mode since it doesn't validate the boundaries.
59  return (this->m_vecBaseUnits[nBitIndex/BitsPerUnit] & ((BASEUNIT)1 << (nBitIndex % BitsPerUnit))) ? true : false;
60  }
61 
62  inline void SetTrue(int nBitIndex)
63  {
64  *this += nBitIndex;
65  }
66 
67  inline void SetFalse(int nBitIndex)
68  {
69  *this -= nBitIndex;
70  }
71 
72  // Sets all the true bit positions from the given vector to true in this vector.
73  // If a bit is not set in the given vector it would not be altered in this vector.
74  inline void SetTrue(const CBitVector& other)
75  {
76  size_t nMax = other.m_vecBaseUnits.size();
77 
78  // This operation results in a larger vector when sizes are not equal.
79  // So Add Space for any Extra Units.
80  while(m_vecBaseUnits.size() < nMax)
81  m_vecBaseUnits.push_back(0);
82 
83  for(size_t nBaseUnitIndex=0 ; nBaseUnitIndex < nMax ; ++nBaseUnitIndex)
84  m_vecBaseUnits[nBaseUnitIndex] |= other.m_vecBaseUnits[nBaseUnitIndex];
85  }
86 
87  // Sets all the true bit positions from the given vector to false in this vector.
88  // If a bit is not set in the given vector it would not be altered in this vector
89  inline void SetFalse(const CBitVector& other)
90  {
91  size_t nMax = min(m_vecBaseUnits.size(), other.m_vecBaseUnits.size());
92 
93  for(size_t nBaseUnitIndex=0; nBaseUnitIndex < nMax; ++nBaseUnitIndex)
94  {
95  m_vecBaseUnits[nBaseUnitIndex] &= (~other.m_vecBaseUnits[nBaseUnitIndex]);
96  }
97  }
98 
99  //Returns a BitVector with the Given BitIndex set to True along with existing ones
100  inline CBitVector operator+(int nBitIndex) const
101  {
102  CBitVector tempVector(*this);
103  return tempVector += nBitIndex;
104  }
105 
106  //Modifies the BitVector by setting the Given BitIndex to True
107  inline CBitVector& operator+=(int nBitIndex)
108  {
109  while(nBitIndex >= BitsPerUnit * (int)this->m_vecBaseUnits.size())
110  this->m_vecBaseUnits.push_back(0);
111 
112  this->m_vecBaseUnits[nBitIndex/BitsPerUnit] |= ((BASEUNIT)1 << (nBitIndex % BitsPerUnit));
113  return *this;
114  }
115 
116  //Returns a BitVector with the Given BitIndex set to False along with existing ones
117  inline CBitVector operator-(int nBitIndex) const
118  {
119  CBitVector tempVector(*this);
120  return tempVector -= nBitIndex;
121  }
122 
123  //Modifies the BitVector by setting the Given BitIndex to False
124  inline CBitVector& operator-=(int nBitIndex)
125  {
126  while(nBitIndex >= BitsPerUnit * (int)this->m_vecBaseUnits.size())
127  this->m_vecBaseUnits.push_back(0);
128 
129  this->m_vecBaseUnits[nBitIndex/BitsPerUnit] &= ~(((BASEUNIT)1 << (nBitIndex % BitsPerUnit)));
130  return *this;
131  }
132 
133  //Returns the First Index Whose Bit Value is Set to True;
134  // Else returns -1 if none found
135  inline int GetFirstTrueIndex() const
136  {
137  return GetNextIndex(0, true);
138  }
139 
140  //Returns any Index after nCurrentIndex Whose Bit Value is Set to True;
141  // Else returns -1 if none found
142  inline int GetNextTrueIndex(int nCurrentIndex) const
143  {
144  return GetNextIndex(nCurrentIndex, true);
145  }
146 
147  inline int GetFirstFalseIndex() const
148  {
149  return GetNextIndex(0, false);
150  }
151 
152  inline int GetNextFalseIndex(int nCurrentIndex) const
153  {
154  return GetNextIndex(nCurrentIndex, false);
155  }
156 
157  inline CBitVector operator|(const CBitVector& that) const
158  {
159  CBitVector tempVector(*this);
160  return tempVector |= that;
161  }
162 
163  // Perform Boolean OR of bitVectors
164  CBitVector& operator|=(const CBitVector& that)
165  {
166  // Boolean OR results in a larger vector when sizes are not equal.
167  // So Add Space for any Extra Units.
168  while(m_vecBaseUnits.size() < that.m_vecBaseUnits.size())
169  m_vecBaseUnits.push_back(0);
170 
171  BASEUNITVECTOR::const_iterator iterBegin = that.m_vecBaseUnits.begin();
172  BASEUNITVECTOR::const_iterator iterEnd = that.m_vecBaseUnits.end();
173  BASEUNITVECTOR::const_iterator iter = iterBegin;
174 
175  for(int nBaseUnitIndex=0 ; iter != iterEnd; ++iter, ++nBaseUnitIndex)
176  m_vecBaseUnits[nBaseUnitIndex] |= *iter;
177 
178  return *this;
179  }
180 
181  inline CBitVector operator&(const CBitVector& that) const
182  {
183  CBitVector tempVector(*this);
184  return tempVector &= that;
185  }
186 
187  // Perform Boolean AND of bitVectors
188  CBitVector& operator&=(const CBitVector& that)
189  {
190  // Boolean AND results in smaller vector when sizes are not equal.
191  // So we can just remove any Extra Units we have without bothering to compare the sizes.
192  while(m_vecBaseUnits.size() > that.m_vecBaseUnits.size())
193  m_vecBaseUnits.pop_back();
194 
195  BASEUNITVECTOR::iterator iterBegin = m_vecBaseUnits.begin();
196  BASEUNITVECTOR::iterator iterEnd = m_vecBaseUnits.end();
197  BASEUNITVECTOR::iterator iter = iterBegin;
198 
199  for(int nBaseUnitIndex=0 ; iter != iterEnd; ++iter, ++nBaseUnitIndex)
200  *iter &= that.m_vecBaseUnits[nBaseUnitIndex];
201 
202  return *this;
203  }
204 
205  //Returns True if Any bit is Set to True
206  inline bool Any() const
207  {
208  for(int i=0, nMax = (int) this->m_vecBaseUnits.size(); i < nMax; ++i)
209  if(this->m_vecBaseUnits[i])
210  return true;
211  return false;
212  }
213 
214  // Returns True if all bits are Set to False
215  inline bool None() const
216  {
217  return !Any();
218  }
219 
220  // Clears all the bits to False
221  inline void Clear()
222  {
223  for(int i=0, nMax = (int) this->m_vecBaseUnits.size(); i < nMax; ++i)
224  this->m_vecBaseUnits[i] = 0;
225  }
226 
227  // Returns the number of bits set
228  inline int BitCount() const
229  {
230  BASEUNITVECTOR::const_iterator iter = m_vecBaseUnits.begin();
231  BASEUNITVECTOR::const_iterator iterEnd = m_vecBaseUnits.end();
232 
233  int nBitCount = 0;
234 
235  for(int nBaseUnitIndex=0 ; iter != iterEnd; ++iter, ++nBaseUnitIndex)
236  {
237  BASEUNIT nUnit = m_vecBaseUnits[nBaseUnitIndex]; //TODO: Improve performance using char lookup for bitcount
238  while(nUnit)
239  {
240  if(nUnit & 1) // if bit set
241  nBitCount ++;
242  nUnit = nUnit >> 1;
243  }
244  }
245 
246  return nBitCount;
247  }
248 
249  // Compares the bitVectors bit by bit
250  inline bool operator==(const CBitVector& other) const
251  {
252  int nMyTrueIndex = GetFirstTrueIndex();
253  int nOtherTrueIndex = other.GetFirstTrueIndex();
254 
255  while((nMyTrueIndex == nOtherTrueIndex) && (nMyTrueIndex!=-1) && (nOtherTrueIndex!=-1))
256  {
257  nMyTrueIndex = GetNextTrueIndex(nMyTrueIndex);
258  nOtherTrueIndex = other.GetNextTrueIndex(nOtherTrueIndex);
259  }
260 
261  return nMyTrueIndex == nOtherTrueIndex;
262  }
263 
264  inline bool operator!=(const CBitVector& other) const
265  {
266  return !(*this == other);
267  }
268 
269 protected:
270  int GetNextIndex(int nCurrentIndex, bool bVal) const
271  {
272  ++nCurrentIndex; //Run Past the Current Index (Start Searching From Next Index Onwards)
273 
274  if(nCurrentIndex <0 || nCurrentIndex >= BitsPerUnit * (int) m_vecBaseUnits.size()) return -1;
275 
276  unsigned int nBaseUnitIndex = (nCurrentIndex / BitsPerUnit);
277  unsigned int nBaseUnitOffset = (nCurrentIndex % BitsPerUnit);
278 
279  BASEUNITVECTOR::const_iterator iterEnd = m_vecBaseUnits.end();
280  BASEUNITVECTOR::const_iterator iter = m_vecBaseUnits.begin() + nBaseUnitIndex;
281 
282  for( ;iter != iterEnd; ++iter, ++nBaseUnitIndex, nBaseUnitOffset = 0)
283  {
284  BASEUNIT nVal = *iter;
285 
286  unsigned int nOffset = nBaseUnitOffset;
287 
288  nVal >>= nOffset;
289 
290  while(nVal)
291  {
292  if((nVal & 1) == bVal)
293  return nBaseUnitIndex * BitsPerUnit + nOffset;
294  nVal >>= 1;
295  nOffset++;
296  }
297  }
298 
299  return -1;
300  }
301 
302 //#ifdef _DEBUG
303 public:
304  OIL::StrUtils_Return_Type ToString() const
305  {
306  OIL::StrUtils_Return_Type str(_T("{"));
307 
308  for(int i=0, nMax = BitsPerUnit * (int) this->m_vecBaseUnits.size(); i < nMax; ++i)
309  if(this->IsBitSet(i))
310  str += OIL::ToString(i) + _T(",");
311 
312  return str + "}";
313  }
314 //#endif //End of operator LPCTSTR() Debug Only Version
315 };
316 
317 #endif

CFugue, the C++ Music Programming Library © Copyright 2009 Cenacle Research India Private Limited Gopalakrishna Palem