175 lines
4.2 KiB
C
175 lines
4.2 KiB
C
struct Bit_Array { // we need to keep track of our allocator separately.
|
|
u64* data;
|
|
s32 count;
|
|
s32 data_count; // do we even need this??
|
|
|
|
bool operator[](s64 index) {
|
|
#if ARRAY_ENABLE_BOUNDS_CHECKING
|
|
if (index < 0 || index >= count) { debug_break(); } // index out of bounds
|
|
#endif
|
|
return (bool)(data[index >> 6] & (1ull << (index & 63)));
|
|
}
|
|
}; // 16 B.
|
|
|
|
// bool contains (Bit_Array* src, Bit_Array* query) {
|
|
// Assert(src && query);
|
|
// Assert(src->data_count == query->data_count);
|
|
// for (s32 i = 0; i < src->data_count; i += 1) {
|
|
// if (src->data[i] & query->data[i] != query->data[i]) {
|
|
// return false;
|
|
// }
|
|
// }
|
|
|
|
// return true;
|
|
// }
|
|
|
|
bool contains_single_ascii (Bit_Array* src, Bit_Array* query) {
|
|
Assert(src && query);
|
|
Assert(src->data_count == query->data_count);
|
|
|
|
for (s32 i = 0; i < src->data_count; i += 1) {
|
|
// if query u64 is non-zero, we should get a non-zero result:
|
|
if (query->data[i] && (src->data[i] & query->data[i]) == 0) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void bit_array_initialize (Bit_Array* ba, s64 count) {
|
|
s64 u64_count = (count + 63) >> 6;
|
|
|
|
ba->data = NewArray<u64>(u64_count);
|
|
ba->data_count = u64_count;
|
|
ba->count = count;
|
|
}
|
|
|
|
// Returns a bit array of the given size:
|
|
Bit_Array new_bit_array (s64 count) {
|
|
Bit_Array ba;
|
|
bit_array_initialize(&ba, count);
|
|
return ba;
|
|
}
|
|
|
|
void bit_array_delete (Bit_Array* ba) {
|
|
internal_free(ba->data);
|
|
ba->count = 0;
|
|
ba->data_count = 0;
|
|
}
|
|
|
|
void set_bit (Bit_Array* ba, s64 i) {
|
|
Assert(i < ba->count);
|
|
ba->data[i >> 6] |= (1ull << (i & 63));
|
|
}
|
|
|
|
void clear_bit (Bit_Array* ba, s64 i) {
|
|
Assert(i < ba->count);
|
|
ba->data[i >> 6] &= ~(1ull << (i & 63));
|
|
}
|
|
|
|
void toggle_bit (Bit_Array* ba, s64 i) {
|
|
Assert(i < ba->count);
|
|
ba->data[i >> 6] ^= ~(1ull << (i & 63));
|
|
}
|
|
|
|
// See "Conditionally set or clear bits without branching" at http://graphics.stanford.edu/~seander/bithacks.html
|
|
force_inline s64 set_bits (s64 w, s64 m, bool b) {
|
|
return (w & ~m) | ((-(s64)b) & m);
|
|
}
|
|
|
|
void set_bit_to (Bit_Array* ba, s64 i, bool value) {
|
|
Assert(i < ba->count);
|
|
ba->data[i >> 6] = set_bits(ba->data[i >> 6], 1ull << (i & 63), value);
|
|
Assert((*ba)[i] == value);
|
|
}
|
|
|
|
void clear_all_bits (Bit_Array* ba) {
|
|
memset(ba->data, 0, ba->data_count * sizeof(u64));
|
|
}
|
|
|
|
void set_all_bits (Bit_Array* ba) {
|
|
memset(ba->data, 0xFF, ba->data_count * sizeof(u64));
|
|
}
|
|
|
|
void toggle_all_bits (Bit_Array* ba) {
|
|
for (s64 s = 0; s < ba->data_count; s += 1) {
|
|
ba->data[s] ^= U64_MAX;
|
|
}
|
|
}
|
|
|
|
// Using Bit_Array.jai as a reference:
|
|
/*
|
|
struct Bit_Array { // 40 B
|
|
ArrayView<u64> slots;
|
|
s64 count; // bit count;
|
|
Allocator allocator;
|
|
|
|
bool operator[](s64 index) {
|
|
#if ARRAY_ENABLE_BOUNDS_CHECKING
|
|
if (index < 0 || index >= count) { debug_break(); } // index out of bounds
|
|
#endif
|
|
return (bool)(slots[index >> 6] & (1ull << (index & 63)));
|
|
}
|
|
};
|
|
|
|
void bit_array_initialize (Bit_Array* ba, s64 count) {
|
|
if (ba->allocator.proc == nullptr) ba->allocator = context_allocator();
|
|
|
|
s64 u64_count = (count + 63) >> 6;
|
|
|
|
ba->slots = ArrayView<u64>(ba->allocator, u64_count);
|
|
ba->count = count;
|
|
}
|
|
|
|
// Returns a bit array of the given size:
|
|
Bit_Array new_bit_array (s64 count) {
|
|
Bit_Array ba;
|
|
bit_array_initialize(&ba, count);
|
|
return ba;
|
|
}
|
|
|
|
void bit_array_delete (Bit_Array* ba) {
|
|
push_allocator(ba->allocator);
|
|
array_free(ba->slots);
|
|
ba->slots = {};
|
|
ba->count = 0;
|
|
}
|
|
|
|
// #TODO: set_bit, clear_bit, toggle_bit, etc.
|
|
void set_bit (Bit_Array* ba, s64 i) {
|
|
Assert(i < ba->count);
|
|
ba->slots[i >> 6] |= (1ull << (i & 63));
|
|
}
|
|
|
|
void clear_bit (Bit_Array* ba, s64 i) {
|
|
Assert(i < ba->count);
|
|
ba->slots[i >> 6] &= ~(1ull << (i & 63));
|
|
}
|
|
|
|
void toggle_bit (Bit_Array* ba, s64 i) {
|
|
Assert(i < ba->count);
|
|
ba->slots[i >> 6] ^= ~(1ull << (i & 63));
|
|
}
|
|
|
|
|
|
void set_bit_to (Bit_Array* ba, s64 i, bool value) {
|
|
Assert(i < ba->count);
|
|
ba->slots[i >> 6] = set_bits(ba->slots[i >> 6], 1ull << (i & 63), value);
|
|
Assert((*ba)[i] == value);
|
|
}
|
|
|
|
void clear_all_bits (Bit_Array* ba) {
|
|
array_zero(ba->slots);
|
|
}
|
|
|
|
void set_all_bits (Bit_Array* ba) {
|
|
memset(ba->slots.data, 0xFF, ba->slots.count * sizeof(u64));
|
|
}
|
|
|
|
void toggle_all_bits (Bit_Array* ba) {
|
|
for_each(s, ba->slots) {
|
|
ba->slots[s] ^= U64_MAX;
|
|
}
|
|
}
|
|
*/ |