| 1 | // tBitArray.cpp  | 
| 2 | //  | 
| 3 | // A tBitArray is a holder for an arbitrary number of bits and allows individual access to each bit, the ability to  | 
| 4 | // clear or set all bits, and some simple binary bitwise operators such as 'and', 'xor', and 'or'. It currently does  | 
| 5 | // not support dynamic growing or shrinking. If the number of bits you need is known at compile time, consider using a  | 
| 6 | // tBitField instead as it is more feature-complete.  | 
| 7 | //  | 
| 8 | // Copyright (c) 2004-2006, 2015, 2017, 2019 Tristan Grimmer.  | 
| 9 | // Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby  | 
| 10 | // granted, provided that the above copyright notice and this permission notice appear in all copies.  | 
| 11 | //  | 
| 12 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL  | 
| 13 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,  | 
| 14 | // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN  | 
| 15 | // AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR  | 
| 16 | // PERFORMANCE OF THIS SOFTWARE.  | 
| 17 |   | 
| 18 | #include "Foundation/tBitArray.h"  | 
| 19 | #include "Foundation/tStandard.h"  | 
| 20 |   | 
| 21 |   | 
| 22 | void tBitArray::Set(int numBits)  | 
| 23 | {  | 
| 24 | 	Clear();  | 
| 25 | 	tAssert(numBits > 0);  | 
| 26 |   | 
| 27 | 	NumBits = numBits;  | 
| 28 | 	int numFields = GetNumFields();  | 
| 29 | 	BitFields = new uint32[numFields];  | 
| 30 | 	tStd::tMemset(BitFields, 0, numFields*sizeof(uint32));  | 
| 31 | }  | 
| 32 |   | 
| 33 |   | 
| 34 | void tBitArray::Set(const uint32* data, int numBits)  | 
| 35 | {  | 
| 36 | 	Clear();  | 
| 37 | 	tAssert(data && numBits);  | 
| 38 |   | 
| 39 | 	NumBits = numBits;  | 
| 40 | 	int n = GetNumFields();  | 
| 41 | 	BitFields = new uint32[n];  | 
| 42 | 	tStd::tMemcpy(BitFields, data, n*sizeof(uint32));  | 
| 43 | 	ClearPadBits();  | 
| 44 | }  | 
| 45 |   | 
| 46 |   | 
| 47 | void tBitArray::Set(const tBitArray& src)  | 
| 48 | {  | 
| 49 | 	if (&src == this)  | 
| 50 | 		return;  | 
| 51 |   | 
| 52 | 	Clear();  | 
| 53 | 	if (!src.IsValid())  | 
| 54 | 		return;  | 
| 55 |   | 
| 56 | 	NumBits = src.NumBits;  | 
| 57 | 	int n = src.GetNumFields();  | 
| 58 | 	BitFields = new uint32[n];  | 
| 59 | 	tStd::tMemcpy(BitFields, src.BitFields, n*sizeof(uint32));  | 
| 60 | }  | 
| 61 |   | 
| 62 |   | 
| 63 | void tBitArray::InvertAll()  | 
| 64 | {  | 
| 65 | 	int n = GetNumFields();  | 
| 66 | 	for (int i = 0; i < n; i++)  | 
| 67 | 		BitFields[i] = ~BitFields[i];  | 
| 68 |   | 
| 69 | 	ClearPadBits();  | 
| 70 | }  | 
| 71 |   | 
| 72 |   | 
| 73 | bool tBitArray::AreAll(bool v) const  | 
| 74 | {  | 
| 75 | 	tAssert(BitFields);  | 
| 76 | 	int n = GetNumFields();  | 
| 77 | 	uint32 fullField = v ? 0xFFFFFFFF : 0x00000000;  | 
| 78 | 	for (int i = 0; i < n-1; i++)  | 
| 79 | 	{  | 
| 80 | 		if (BitFields[i] != fullField)  | 
| 81 | 			return false;  | 
| 82 | 	}  | 
| 83 |   | 
| 84 | 	// Deal with the bits in the last field.  | 
| 85 | 	int last = NumBits & 0x1F;  | 
| 86 | 	uint32 maxFull = (last ? (1 << last) : 0) - 1;  | 
| 87 | 	fullField = v ? maxFull : 0x00000000;  | 
| 88 | 	return (BitFields[n-1] & maxFull) == fullField;  | 
| 89 | }  | 
| 90 |   | 
| 91 |   | 
| 92 | int tBitArray::CountBits(bool val) const  | 
| 93 | {  | 
| 94 | 	// Uses technique described here "http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan".  | 
| 95 | 	// This is one reason the pad bits must always be cleared.  | 
| 96 | 	tAssert(BitFields);  | 
| 97 | 	int numFields = GetNumFields();  | 
| 98 |   | 
| 99 | 	int count = 0;  | 
| 100 | 	for (int n = 0; n < numFields; n++)  | 
| 101 | 	{  | 
| 102 | 		uint32 v = BitFields[n];		// Count the number of bits set in v.  | 
| 103 | 		uint32 c;						// c accumulates the total bits set in v.  | 
| 104 | 		for (c = 0; v; c++)  | 
| 105 | 			v &= v - 1;					// Clear the least significant bit set.  | 
| 106 | 		count += c;  | 
| 107 | 	}  | 
| 108 | 	  | 
| 109 | 	return val ? count : (NumBits - count);  | 
| 110 | }  | 
| 111 |   | 
| 112 |   | 
| 113 | int tBitArray::GetClearedBit(int index) const  | 
| 114 | {  | 
| 115 | 	tAssert(BitFields);  | 
| 116 |   | 
| 117 | 	// Find the first zero bit. The operation we do is log2((a xor (a+1)) +1)  | 
| 118 | 	uint32 field = BitFields[index];  | 
| 119 |   | 
| 120 | 	// This is guaranteed to be a power of two.  | 
| 121 | 	uint32 freeBit = (field ^ (field+1)) + 1;  | 
| 122 |   | 
| 123 | 	// Wraps around on the last bit.  | 
| 124 | 	if (!freeBit)  | 
| 125 | 		return 31;  | 
| 126 |   | 
| 127 | 	// Now get the log in base 2 of freeBit. See "http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog".  | 
| 128 | 	const uint32 b[] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };  | 
| 129 | 	uint32 c = (freeBit & b[0]) != 0;  | 
| 130 |   | 
| 131 | 	c |= ((freeBit & b[4]) != 0) << 4;  | 
| 132 | 	c |= ((freeBit & b[3]) != 0) << 3;  | 
| 133 | 	c |= ((freeBit & b[2]) != 0) << 2;  | 
| 134 | 	c |= ((freeBit & b[1]) != 0) << 1;  | 
| 135 |   | 
| 136 | 	// This is the first cleared index in the bit array.  | 
| 137 | 	return c-1;  | 
| 138 | }  | 
| 139 |   | 
| 140 |   | 
| 141 | int tBitArray::GetClearedBitPos() const  | 
| 142 | {  | 
| 143 | 	int n = GetNumFields();  | 
| 144 |   | 
| 145 | 	for (int i = 0; i < n-1; i++)  | 
| 146 | 	{  | 
| 147 | 		if (BitFields[i] < 0xFFFFFFFF)  | 
| 148 | 			return 32*i + GetClearedBit(i);  | 
| 149 | 	}  | 
| 150 |   | 
| 151 | 	int last = NumBits & 0x1F;  | 
| 152 | 	uint32 maxFull = (last ? (1 << last) : 0) - 1;  | 
| 153 |   | 
| 154 | 	if (BitFields[n-1] < maxFull)  | 
| 155 | 		return 32*(n-1) + GetClearedBit(n-1);  | 
| 156 |   | 
| 157 | 	// There are no free bits available.  | 
| 158 | 	return -1;  | 
| 159 | }  | 
| 160 |   | 
| 161 |   | 
| 162 | tBitArray& tBitArray::operator&=(const tBitArray& s)  | 
| 163 | {  | 
| 164 | 	tAssert(NumBits == s.NumBits);  | 
| 165 | 	int n = GetNumFields();  | 
| 166 | 	for (int i = 0; i < n; i++)  | 
| 167 | 		BitFields[i] &= s.BitFields[i];  | 
| 168 |   | 
| 169 | 	return *this;	// No need to ensure pad bits are cleared because 0 & 0 = 0.  | 
| 170 | }  | 
| 171 |   | 
| 172 |   | 
| 173 | tBitArray& tBitArray::operator|=(const tBitArray& s)  | 
| 174 | {  | 
| 175 | 	tAssert(NumBits == s.NumBits);  | 
| 176 | 	int n = GetNumFields();  | 
| 177 | 	for (int i = 0; i < n; i++)  | 
| 178 | 		BitFields[i] |= s.BitFields[i];  | 
| 179 |   | 
| 180 | 	return *this;	// No need to ensure pad bits are cleared because 0 | 0 = 0.  | 
| 181 | }  | 
| 182 |   | 
| 183 |   | 
| 184 | tBitArray& tBitArray::operator^=(const tBitArray& s)  | 
| 185 | {  | 
| 186 | 	tAssert(NumBits == s.NumBits);  | 
| 187 | 	int n = GetNumFields();  | 
| 188 | 	for (int i = 0; i < n; i++)  | 
| 189 | 		BitFields[i] ^= s.BitFields[i];  | 
| 190 |   | 
| 191 | 	return *this;	// No need to ensure pad bits are cleared because 0 ^ 0 = 0.  | 
| 192 | }  | 
| 193 |  |