mirror of
https://github.com/xenia-project/xenia.git
synced 2026-04-20 22:13:40 +00:00
Adding Crunch at r319.
This commit is contained in:
parent
c660b5e4d1
commit
1f3e06e60c
215 changed files with 99367 additions and 0 deletions
538
third_party/crunch/crnlib/crn_sparse_bit_array.cpp
vendored
Normal file
538
third_party/crunch/crnlib/crn_sparse_bit_array.cpp
vendored
Normal file
|
|
@ -0,0 +1,538 @@
|
|||
// File: crn_sparse_bit_array.h
|
||||
// See Copyright Notice and license at the end of inc/crnlib.h
|
||||
#include "crn_core.h"
|
||||
#include "crn_sparse_bit_array.h"
|
||||
|
||||
namespace crnlib
|
||||
{
|
||||
sparse_bit_array::sparse_bit_array() :
|
||||
m_num_groups(0), m_ppGroups(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
sparse_bit_array::sparse_bit_array(uint size) :
|
||||
m_num_groups(0), m_ppGroups(NULL)
|
||||
{
|
||||
resize(size);
|
||||
}
|
||||
|
||||
sparse_bit_array::sparse_bit_array(sparse_bit_array& other)
|
||||
{
|
||||
m_num_groups = other.m_num_groups;
|
||||
m_ppGroups = (uint32**)crnlib_malloc(m_num_groups * sizeof(uint32*));
|
||||
CRNLIB_VERIFY(m_ppGroups);
|
||||
|
||||
for (uint i = 0; i < m_num_groups; i++)
|
||||
{
|
||||
if (other.m_ppGroups[i])
|
||||
{
|
||||
m_ppGroups[i] = alloc_group(false);
|
||||
memcpy(m_ppGroups[i], other.m_ppGroups[i], cBytesPerGroup);
|
||||
}
|
||||
else
|
||||
m_ppGroups[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
sparse_bit_array::~sparse_bit_array()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
sparse_bit_array& sparse_bit_array::operator= (sparse_bit_array& other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
if (m_num_groups != other.m_num_groups)
|
||||
{
|
||||
clear();
|
||||
|
||||
m_num_groups = other.m_num_groups;
|
||||
m_ppGroups = (uint32**)crnlib_calloc(m_num_groups, sizeof(uint32*));
|
||||
CRNLIB_VERIFY(m_ppGroups);
|
||||
}
|
||||
|
||||
for (uint i = 0; i < m_num_groups; i++)
|
||||
{
|
||||
if (other.m_ppGroups[i])
|
||||
{
|
||||
if (!m_ppGroups[i])
|
||||
m_ppGroups[i] = alloc_group(false);
|
||||
memcpy(m_ppGroups[i], other.m_ppGroups[i], cBytesPerGroup);
|
||||
}
|
||||
else if (m_ppGroups[i])
|
||||
{
|
||||
free_group(m_ppGroups[i]);
|
||||
m_ppGroups[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void sparse_bit_array::clear()
|
||||
{
|
||||
if (!m_num_groups)
|
||||
return;
|
||||
|
||||
for (uint i = 0; i < m_num_groups; i++)
|
||||
free_group(m_ppGroups[i]);
|
||||
|
||||
crnlib_free(m_ppGroups);
|
||||
m_ppGroups = NULL;
|
||||
|
||||
m_num_groups = 0;
|
||||
}
|
||||
|
||||
void sparse_bit_array::swap(sparse_bit_array& other)
|
||||
{
|
||||
utils::swap(m_ppGroups, other.m_ppGroups);
|
||||
utils::swap(m_num_groups, other.m_num_groups);
|
||||
}
|
||||
|
||||
void sparse_bit_array::optimize()
|
||||
{
|
||||
for (uint i = 0; i < m_num_groups; i++)
|
||||
{
|
||||
uint32* s = m_ppGroups[i];
|
||||
if (s)
|
||||
{
|
||||
uint j;
|
||||
for (j = 0; j < cDWORDsPerGroup; j++)
|
||||
if (s[j])
|
||||
break;
|
||||
if (j == cDWORDsPerGroup)
|
||||
{
|
||||
free_group(s);
|
||||
m_ppGroups[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sparse_bit_array::set_bit_range(uint index, uint num)
|
||||
{
|
||||
CRNLIB_ASSERT((index + num) <= (m_num_groups << cBitsPerGroupShift));
|
||||
|
||||
if (!num)
|
||||
return;
|
||||
else if (num == 1)
|
||||
{
|
||||
set_bit(index);
|
||||
return;
|
||||
}
|
||||
|
||||
while ((index & cBitsPerGroupMask) || (num <= cBitsPerGroup))
|
||||
{
|
||||
uint group_index = index >> cBitsPerGroupShift;
|
||||
CRNLIB_ASSERT(group_index < m_num_groups);
|
||||
|
||||
uint32* pGroup = m_ppGroups[group_index];
|
||||
if (!pGroup)
|
||||
{
|
||||
pGroup = alloc_group(true);
|
||||
m_ppGroups[group_index] = pGroup;
|
||||
}
|
||||
|
||||
const uint group_bit_ofs = index & cBitsPerGroupMask;
|
||||
|
||||
const uint dword_bit_ofs = group_bit_ofs & 31;
|
||||
const uint max_bits_to_set = 32 - dword_bit_ofs;
|
||||
|
||||
const uint bits_to_set = math::minimum(max_bits_to_set, num);
|
||||
const uint32 msk = (0xFFFFFFFFU >> (32 - bits_to_set));
|
||||
|
||||
pGroup[group_bit_ofs >> 5] |= (msk << dword_bit_ofs);
|
||||
|
||||
num -= bits_to_set;
|
||||
if (!num)
|
||||
return;
|
||||
|
||||
index += bits_to_set;
|
||||
}
|
||||
|
||||
while (num >= cBitsPerGroup)
|
||||
{
|
||||
uint group_index = index >> cBitsPerGroupShift;
|
||||
CRNLIB_ASSERT(group_index < m_num_groups);
|
||||
|
||||
uint32* pGroup = m_ppGroups[group_index];
|
||||
if (!pGroup)
|
||||
{
|
||||
pGroup = alloc_group(true);
|
||||
m_ppGroups[group_index] = pGroup;
|
||||
}
|
||||
|
||||
memset(pGroup, 0xFF, sizeof(uint32) * cDWORDsPerGroup);
|
||||
|
||||
num -= cBitsPerGroup;
|
||||
index += cBitsPerGroup;
|
||||
}
|
||||
|
||||
while (num)
|
||||
{
|
||||
uint group_index = index >> cBitsPerGroupShift;
|
||||
CRNLIB_ASSERT(group_index < m_num_groups);
|
||||
|
||||
uint32* pGroup = m_ppGroups[group_index];
|
||||
if (!pGroup)
|
||||
{
|
||||
pGroup = alloc_group(true);
|
||||
m_ppGroups[group_index] = pGroup;
|
||||
}
|
||||
|
||||
uint group_bit_ofs = index & cBitsPerGroupMask;
|
||||
|
||||
uint bits_to_set = math::minimum(32U, num);
|
||||
uint32 msk = (0xFFFFFFFFU >> (32 - bits_to_set));
|
||||
|
||||
pGroup[group_bit_ofs >> 5] |= (msk << (group_bit_ofs & 31));
|
||||
|
||||
num -= bits_to_set;
|
||||
index += bits_to_set;
|
||||
}
|
||||
}
|
||||
|
||||
void sparse_bit_array::clear_all_bits()
|
||||
{
|
||||
for (uint i = 0; i < m_num_groups; i++)
|
||||
{
|
||||
uint32* pGroup = m_ppGroups[i];
|
||||
if (pGroup)
|
||||
memset(pGroup, 0, sizeof(uint32) * cDWORDsPerGroup);
|
||||
}
|
||||
}
|
||||
|
||||
void sparse_bit_array::clear_bit_range(uint index, uint num)
|
||||
{
|
||||
CRNLIB_ASSERT((index + num) <= (m_num_groups << cBitsPerGroupShift));
|
||||
|
||||
if (!num)
|
||||
return;
|
||||
else if (num == 1)
|
||||
{
|
||||
clear_bit(index);
|
||||
return;
|
||||
}
|
||||
|
||||
while ((index & cBitsPerGroupMask) || (num <= cBitsPerGroup))
|
||||
{
|
||||
uint group_index = index >> cBitsPerGroupShift;
|
||||
CRNLIB_ASSERT(group_index < m_num_groups);
|
||||
|
||||
const uint group_bit_ofs = index & cBitsPerGroupMask;
|
||||
|
||||
const uint dword_bit_ofs = group_bit_ofs & 31;
|
||||
const uint max_bits_to_set = 32 - dword_bit_ofs;
|
||||
|
||||
const uint bits_to_set = math::minimum(max_bits_to_set, num);
|
||||
|
||||
uint32* pGroup = m_ppGroups[group_index];
|
||||
if (pGroup)
|
||||
{
|
||||
const uint32 msk = (0xFFFFFFFFU >> (32 - bits_to_set));
|
||||
|
||||
pGroup[group_bit_ofs >> 5] &= (~(msk << dword_bit_ofs));
|
||||
}
|
||||
|
||||
num -= bits_to_set;
|
||||
if (!num)
|
||||
return;
|
||||
|
||||
index += bits_to_set;
|
||||
}
|
||||
|
||||
while (num >= cBitsPerGroup)
|
||||
{
|
||||
uint group_index = index >> cBitsPerGroupShift;
|
||||
CRNLIB_ASSERT(group_index < m_num_groups);
|
||||
|
||||
uint32* pGroup = m_ppGroups[group_index];
|
||||
if (pGroup)
|
||||
{
|
||||
free_group(pGroup);
|
||||
m_ppGroups[group_index] = NULL;
|
||||
}
|
||||
|
||||
num -= cBitsPerGroup;
|
||||
index += cBitsPerGroup;
|
||||
}
|
||||
|
||||
while (num)
|
||||
{
|
||||
uint group_index = index >> cBitsPerGroupShift;
|
||||
CRNLIB_ASSERT(group_index < m_num_groups);
|
||||
|
||||
uint bits_to_set = math::minimum(32u, num);
|
||||
|
||||
uint32* pGroup = m_ppGroups[group_index];
|
||||
if (pGroup)
|
||||
{
|
||||
uint group_bit_ofs = index & cBitsPerGroupMask;
|
||||
|
||||
uint32 msk = (0xFFFFFFFFU >> (32 - bits_to_set));
|
||||
|
||||
pGroup[group_bit_ofs >> 5] &= (~(msk << (group_bit_ofs & 31)));
|
||||
}
|
||||
|
||||
num -= bits_to_set;
|
||||
index += bits_to_set;
|
||||
}
|
||||
}
|
||||
|
||||
void sparse_bit_array::resize(uint size)
|
||||
{
|
||||
uint num_groups = (size + cBitsPerGroup - 1) >> cBitsPerGroupShift;
|
||||
if (num_groups == m_num_groups)
|
||||
return;
|
||||
|
||||
if (!num_groups)
|
||||
{
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
|
||||
sparse_bit_array temp;
|
||||
temp.swap(*this);
|
||||
|
||||
m_num_groups = num_groups;
|
||||
m_ppGroups = (uint32**)crnlib_calloc(m_num_groups, sizeof(uint32*));
|
||||
CRNLIB_VERIFY(m_ppGroups);
|
||||
|
||||
uint n = math::minimum(temp.m_num_groups, m_num_groups);
|
||||
for (uint i = 0; i < n; i++)
|
||||
{
|
||||
uint32* p = temp.m_ppGroups[i];
|
||||
if (p)
|
||||
{
|
||||
m_ppGroups[i] = temp.m_ppGroups[i];
|
||||
temp.m_ppGroups[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sparse_bit_array& sparse_bit_array::operator&= (const sparse_bit_array& other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
CRNLIB_VERIFY(other.m_num_groups == m_num_groups);
|
||||
|
||||
for (uint i = 0; i < m_num_groups; i++)
|
||||
{
|
||||
uint32* d = m_ppGroups[i];
|
||||
if (!d)
|
||||
continue;
|
||||
uint32* s = other.m_ppGroups[i];
|
||||
|
||||
if (!s)
|
||||
{
|
||||
free_group(d);
|
||||
m_ppGroups[i] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 oc = 0;
|
||||
for (uint j = 0; j < cDWORDsPerGroup; j++)
|
||||
{
|
||||
uint32 c = d[j] & s[j];
|
||||
d[j] = c;
|
||||
oc |= c;
|
||||
}
|
||||
if (!oc)
|
||||
{
|
||||
free_group(d);
|
||||
m_ppGroups[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
sparse_bit_array& sparse_bit_array::operator|= (const sparse_bit_array& other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
CRNLIB_VERIFY(other.m_num_groups == m_num_groups);
|
||||
|
||||
for (uint i = 0; i < m_num_groups; i++)
|
||||
{
|
||||
uint32* s = other.m_ppGroups[i];
|
||||
if (!s)
|
||||
continue;
|
||||
|
||||
uint32* d = m_ppGroups[i];
|
||||
if (!d)
|
||||
{
|
||||
d = alloc_group(true);
|
||||
m_ppGroups[i] = d;
|
||||
memcpy(d, s, cBytesPerGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 oc = 0;
|
||||
for (uint j = 0; j < cDWORDsPerGroup; j++)
|
||||
{
|
||||
uint32 c = d[j] | s[j];
|
||||
d[j] = c;
|
||||
oc |= c;
|
||||
}
|
||||
if (!oc)
|
||||
{
|
||||
free_group(d);
|
||||
m_ppGroups[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
sparse_bit_array& sparse_bit_array::and_not(const sparse_bit_array& other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
CRNLIB_VERIFY(other.m_num_groups == m_num_groups);
|
||||
|
||||
for (uint i = 0; i < m_num_groups; i++)
|
||||
{
|
||||
uint32* d = m_ppGroups[i];
|
||||
if (!d)
|
||||
continue;
|
||||
uint32* s = other.m_ppGroups[i];
|
||||
if (!s)
|
||||
continue;
|
||||
|
||||
uint32 oc = 0;
|
||||
for (uint j = 0; j < cDWORDsPerGroup; j++)
|
||||
{
|
||||
uint32 c = d[j] & (~s[j]);
|
||||
d[j] = c;
|
||||
oc |= c;
|
||||
}
|
||||
if (!oc)
|
||||
{
|
||||
free_group(d);
|
||||
m_ppGroups[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
int sparse_bit_array::find_first_set_bit(uint index, uint num) const
|
||||
{
|
||||
CRNLIB_ASSERT((index + num) <= (m_num_groups << cBitsPerGroupShift));
|
||||
|
||||
if (!num)
|
||||
return -1;
|
||||
|
||||
while ((index & cBitsPerGroupMask) || (num <= cBitsPerGroup))
|
||||
{
|
||||
uint group_index = index >> cBitsPerGroupShift;
|
||||
CRNLIB_ASSERT(group_index < m_num_groups);
|
||||
|
||||
const uint group_bit_ofs = index & cBitsPerGroupMask;
|
||||
const uint dword_bit_ofs = group_bit_ofs & 31;
|
||||
|
||||
const uint max_bits_to_examine = 32 - dword_bit_ofs;
|
||||
const uint bits_to_examine = math::minimum(max_bits_to_examine, num);
|
||||
|
||||
uint32* pGroup = m_ppGroups[group_index];
|
||||
if (pGroup)
|
||||
{
|
||||
const uint32 msk = (0xFFFFFFFFU >> (32 - bits_to_examine));
|
||||
|
||||
uint bits = pGroup[group_bit_ofs >> 5] & (msk << dword_bit_ofs);
|
||||
if (bits)
|
||||
{
|
||||
uint num_trailing_zeros = math::count_trailing_zero_bits(bits);
|
||||
int set_index = num_trailing_zeros + (index & ~31);
|
||||
CRNLIB_ASSERT(get_bit(set_index));
|
||||
return set_index;
|
||||
}
|
||||
}
|
||||
|
||||
num -= bits_to_examine;
|
||||
if (!num)
|
||||
return -1;
|
||||
|
||||
index += bits_to_examine;
|
||||
}
|
||||
|
||||
while (num >= cBitsPerGroup)
|
||||
{
|
||||
uint group_index = index >> cBitsPerGroupShift;
|
||||
CRNLIB_ASSERT(group_index < m_num_groups);
|
||||
|
||||
uint32* pGroup = m_ppGroups[group_index];
|
||||
if (pGroup)
|
||||
{
|
||||
for (uint i = 0; i < cDWORDsPerGroup; i++)
|
||||
{
|
||||
uint32 bits = pGroup[i];
|
||||
if (bits)
|
||||
{
|
||||
uint num_trailing_zeros = math::count_trailing_zero_bits(bits);
|
||||
|
||||
int set_index = num_trailing_zeros + index + (i << 5);
|
||||
CRNLIB_ASSERT(get_bit(set_index));
|
||||
return set_index;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
num -= cBitsPerGroup;
|
||||
index += cBitsPerGroup;
|
||||
}
|
||||
|
||||
while (num)
|
||||
{
|
||||
uint group_index = index >> cBitsPerGroupShift;
|
||||
CRNLIB_ASSERT(group_index < m_num_groups);
|
||||
|
||||
uint bits_to_examine = math::minimum(32U, num);
|
||||
|
||||
uint32* pGroup = m_ppGroups[group_index];
|
||||
if (pGroup)
|
||||
{
|
||||
uint group_bit_ofs = index & cBitsPerGroupMask;
|
||||
|
||||
uint32 msk = (0xFFFFFFFFU >> (32 - bits_to_examine));
|
||||
|
||||
uint32 bits = pGroup[group_bit_ofs >> 5] & (msk << (group_bit_ofs & 31));
|
||||
if (bits)
|
||||
{
|
||||
uint num_trailing_zeros = math::count_trailing_zero_bits(bits);
|
||||
|
||||
int set_index = num_trailing_zeros + (index & ~31);
|
||||
CRNLIB_ASSERT(get_bit(set_index));
|
||||
return set_index;
|
||||
}
|
||||
}
|
||||
|
||||
num -= bits_to_examine;
|
||||
index += bits_to_examine;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace crnlib
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue