1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 /***************************************************************************/
7 /***************************************************************************/
8 // Routines to support a growable bitvector
9 /***************************************************************************/
16 #include "bitvector.h"
20 int BitVector::NumBits() const
33 unsigned maxNonZero = 0;
34 for (unsigned i=1; (i < m_vals.GetLength()); i++)
36 if (m_vals.m_chunks[i] != 0)
41 count = (maxNonZero * CHUNK_BITS) - 1;
42 hiChunk = m_vals.m_chunks[maxNonZero];
59 void BitVector::doBigInit(ChunkType arg)
64 m_vals.m_chunks[0] = arg;
68 void BitVector::doBigInit(const BitVector& arg)
75 memcpy(m_vals.m_chunks, arg.m_vals.m_chunks, (sizeof(ChunkType) * arg.m_vals.GetLength()));
76 m_vals.SetLength(arg.m_vals.GetLength());
84 void BitVector::doBigLeftShiftAssign(unsigned shift)
92 if ((m_val == 0) || (shift == 0)) // Zero is a special case, don't need to do anything
95 unsigned numWords = shift / CHUNK_BITS;
96 unsigned numBits = shift % CHUNK_BITS;
99 // Change to Big representation
103 int from = m_vals.GetLength()-1;
104 int to = from + numWords;
105 unsigned newlen = to + 1;
107 ChunkType topBits = 0;
110 topBits = m_vals.m_chunks[from] >> (CHUNK_BITS - numBits);
113 if (topBits != 0 || numWords != 0)
117 m_vals.m_chunks[newlen] = topBits;
120 m_vals.SetLength(newlen);
125 m_vals.m_chunks[to] = (from >= 0) ? (m_vals.m_chunks[from] << numBits) : 0;
128 if ((from >= 0) && (numBits > 0))
130 m_vals.m_chunks[to] |= m_vals.m_chunks[from] >> (CHUNK_BITS - numBits);
135 // Convert back to small format if necessary
136 if ((newlen == 1) && (m_vals.m_chunks[0] <= MaxVal))
138 m_val = ChunkType(m_vals.m_chunks[0] << 1);
142 void BitVector::doBigRightShiftAssign(unsigned shift)
150 if ((m_val == 0) || (shift == 0)) // Zero is a special case, don't need to do anything
153 unsigned numWords = shift / CHUNK_BITS;
154 unsigned numBits = shift % CHUNK_BITS;
157 // Change to Big representation
161 unsigned from = numWords;
163 unsigned len = m_vals.GetLength();
164 unsigned newlen = len - numWords;
168 // we always encode zero in short form
173 m_vals.m_chunks[to] = (m_vals.m_chunks[from] >> numBits);
180 m_vals.m_chunks[to] |= m_vals.m_chunks[from] << (CHUNK_BITS - numBits);
184 m_vals.m_chunks[to] = (m_vals.m_chunks[from] >> numBits);
188 if ((newlen > 1) && (m_vals.m_chunks[newlen-1] == 0))
193 m_vals.SetLength(newlen);
195 // Convert back to small format if necessary
196 if ((newlen == 1) && (m_vals.m_chunks[0] <= MaxVal))
198 m_val = ChunkType(m_vals.m_chunks[0] << 1);
203 void BitVector::doBigAndAssign(const BitVector& arg)
212 // Change to Big representation
218 bool isZero = true; // until proven otherwise
219 unsigned myLen = m_vals.GetLength();
220 unsigned argLen = arg.m_vals.GetLength();
224 // shrink our length to match argLen
225 m_vals.SetLength(argLen);
229 for (unsigned i = 0; (i < myLen); i++)
231 ChunkType curChunk = m_vals.m_chunks[i] & arg.m_vals.m_chunks[i];
232 m_vals.m_chunks[i] = curChunk;
239 // we always encode zero in short form
245 m_val = (m_vals.m_chunks[0] << 1) & arg.m_val;
249 void BitVector::doBigOrAssign(const BitVector& arg)
258 // Change to Big representation
264 unsigned myLen = m_vals.GetLength();
265 unsigned argLen = arg.m_vals.GetLength();
269 // expand our length to match argLen and zero init
270 memset(m_vals.m_chunks + myLen, 0, sizeof(ChunkType) * (argLen - myLen));
271 m_vals.SetLength(argLen);
275 for(unsigned i = 0; ((i < myLen) && (i < argLen)); i++)
277 m_vals.m_chunks[i] |= arg.m_vals.m_chunks[i];
282 m_vals.m_chunks[0] |= arg.smallBits();
286 void BitVector::doBigDiffAssign(const BitVector& arg)
295 // Change to Big representation
299 unsigned myLen = m_vals.GetLength();
300 unsigned argLen = arg.m_vals.GetLength();
301 bool isZero = true; // until proven otherwise
303 for (unsigned i = 0; (i < myLen); i++)
305 ChunkType nextChunk = m_vals.m_chunks[i];
308 nextChunk &= ~arg.m_vals.m_chunks[i];
309 m_vals.m_chunks[i] = nextChunk;
313 nextChunk &= ~arg.smallBits();
314 m_vals.m_chunks[i] = nextChunk;
323 // we always encode zero in short form
328 BOOL BitVector::doBigEquals(const BitVector& arg) const
338 unsigned myLen = m_vals.GetLength();
339 unsigned argLen = arg.m_vals.GetLength();
340 unsigned maxLen = (myLen >= argLen) ? myLen : argLen;
342 for (unsigned i=0; (i < maxLen); i++)
345 ChunkType argVal = 0;
348 myVal = m_vals.m_chunks[i];
351 argVal = arg.m_vals.m_chunks[i];
358 argVal = arg.smallBits();
367 BOOL BitVector::doBigIntersect(const BitVector& arg) const
377 unsigned myLen = m_vals.GetLength();
378 unsigned argLen = arg.m_vals.GetLength();
379 unsigned minLen = (myLen <= argLen) ? myLen : argLen;
381 for (unsigned i=0; (i <= minLen); i++)
384 ChunkType argVal = 0;
387 myVal = m_vals.m_chunks[i];
390 argVal = arg.m_vals.m_chunks[i];
397 argVal = arg.smallBits();
400 if ((myVal & argVal) != 0)
406 #endif // USE_BITVECTOR