Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion include/container/seadObjArray.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,11 @@ class ObjArray : public PtrArrayImpl
return PtrArrayImpl::compare(other, cmp);
}

s32 binarySearch(const T* ptr) const { return PtrArrayImpl::binarySearch(ptr, compareT); }
__attribute__((noinline)) s32 binarySearch(const T* ptr) const
{
return PtrArrayImpl::binarySearch(ptr, compareT);
}

s32 binarySearch(const T* ptr, CompareCallback cmp) const
{
return PtrArrayImpl::binarySearch(ptr, cmp);
Expand Down
29 changes: 3 additions & 26 deletions include/container/seadPtrArray.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,12 @@ class PtrArrayImpl
if (mPtrNum <= pos)
return;

MemUtil::copyOverlap(mPtrs + pos + count, mPtrs + pos,
MemUtil::copyOverlap(&mPtrs[pos + count], &mPtrs[pos],
s32(sizeof(void*)) * (mPtrNum - pos));
}

void insert(s32 idx, void* ptr);
void insertArray(s32 idx, void* array, s32 array_length, s32 elem_size);
void insertArray(s32 idx, void* array, s32 arrayLength, s32 elementSize);
bool checkInsert(s32 idx, s32 num);

template <typename T>
Expand Down Expand Up @@ -188,30 +188,7 @@ class PtrArrayImpl
s32 compare(const PtrArrayImpl& other, CompareCallbackImpl cmp) const;
void uniq(CompareCallbackImpl cmp);

s32 binarySearch(const void* ptr, CompareCallbackImpl cmp) const
{
if (mPtrNum == 0)
return -1;

s32 a = 0;
s32 b = mPtrNum - 1;
while (a < b)
{
const s32 m = (a + b) / 2;
const s32 c = cmp(mPtrs[m], ptr);
if (c == 0)
return m;
if (c < 0)
a = m + 1;
else
b = m;
}

if (cmp(mPtrs[a], ptr) == 0)
return a;

return -1;
}
s32 binarySearch(const void* ptr, CompareCallbackImpl cmp) const;

s32 mPtrNum = 0;
s32 mPtrNumMax = 0;
Expand Down
167 changes: 157 additions & 10 deletions modules/src/container/seadPtrArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,18 +93,18 @@ void PtrArrayImpl::erase(s32 pos, s32 count)
mPtrNum -= count;
}

// NON_MATCHING: semantically equivalent
void PtrArrayImpl::reverse()
{
for (s32 i = 0; i < mPtrNum / 2; ++i)
s32 size = mPtrNum / 2;
for (s32 i = 0; i < size; i++)
swap(mPtrNum - i - 1, i);
}

// Fisher–Yates shuffle.
void PtrArrayImpl::shuffle(Random* random)
{
SEAD_ASSERT(random);
for (s32 i = mPtrNum - 1; i > 0; --i)
for (s32 i = mPtrNum - 1; i > 0; i--)
swap(i, random->getS32Range(0, i + 1));
}

Expand Down Expand Up @@ -141,20 +141,167 @@ bool PtrArrayImpl::checkInsert(s32 pos, s32 num)
return true;
}

// TODO: PtrArrayImpl::insertArray
// NON-MATCHING: Inverted registers https://decomp.me/scratch/fBexb
void PtrArrayImpl::insertArray(s32 idx, void* array, s32 arrayLength, s32 elementSize)
{
if (!checkInsert(idx, arrayLength))
return;

createVacancy(idx, arrayLength);

for (s32 i = 0; i < arrayLength; i++)
mPtrs[idx + i] = (u8*)array + (elementSize * i);

mPtrNum += arrayLength;
}

// Bidirectional bubble sort
void PtrArrayImpl::sort(CompareCallbackImpl cmp)
{
// Note: Nintendo did not use <algorithm>
std::sort(mPtrs, mPtrs + size(), [&](const void* a, const void* b) { return cmp(a, b) < 0; });
if (mPtrNum < 2)
return;

void** ptrs = mPtrs;
s32 left = 0;
s32 right = mPtrNum - 1;

do
{
s32 lastSwapForward = left;
for (s32 i = left; i < right; i++)
{
if (cmp(ptrs[i], ptrs[i + 1]) > 0)
{
void* temp = ptrs[i + 1];
ptrs[i + 1] = ptrs[i];
ptrs[i] = temp;
lastSwapForward = i;
}
}
right = lastSwapForward;

if (left == right)
break;

s32 lastSwapBackward = right;
for (s32 i = right; i > left; i--)
{
if (cmp(ptrs[i], ptrs[i - 1]) < 0)
{
void* temp = ptrs[i - 1];
ptrs[i - 1] = ptrs[i];
ptrs[i] = temp;
lastSwapBackward = i;
}
}
left = lastSwapBackward;
} while (left != right);
}

// TODO: PtrArrayImpl::heapSort
void PtrArrayImpl::heapSort(CompareCallbackImpl cmp)
{
if (mPtrNum < 2)
return;

void** ptrs = mPtrs;
s32 i = mPtrNum / 2;
s32 n = mPtrNum;

do
{
s32 parent = i--;
void* val = ptrs[parent - 1];

while (parent * 2 <= n)
{
s32 child = parent * 2;
if (child < n && cmp(ptrs[child - 1], ptrs[child]) < 0)
child++;

if (cmp(val, ptrs[child - 1]) >= 0)
break;

ptrs[parent - 1] = ptrs[child - 1];
parent = child;
}

ptrs[parent - 1] = val;
} while (i > 0);

while (n > 1)
{
void* val = ptrs[n - 1];
ptrs[--n] = ptrs[0];

// TODO: PtrArrayImpl::compare
s32 parent = 1;
while (parent * 2 <= n)
{
s32 child = parent * 2;
if (child < n && cmp(ptrs[child - 1], ptrs[child]) < 0)
child++;

// TODO: PtrArrayImpl::uniq
if (cmp(val, ptrs[child - 1]) >= 0)
break;

// TODO: PtrArrayImpl::binarySearch
ptrs[parent - 1] = ptrs[child - 1];
parent = child;
}
ptrs[parent - 1] = val;
}
}

s32 PtrArrayImpl::compare(const PtrArrayImpl& other, CompareCallbackImpl cmp) const
{
for (s32 i = 0; i < size(); i++)
{
if (i >= other.size())
return 1;

const s32 c = cmp(mPtrs[i], other.unsafeAt(i));
if (c != 0)
return c;
}

return size() != other.size() ? -1 : 0;
}

void PtrArrayImpl::uniq(CompareCallbackImpl cmp)
{
for (s32 i = 0; i < size() - 1; i++)
{
for (s32 e = i + 1; e < size();)
{
if (cmp(mPtrs[i], mPtrs[e]) == 0)
erase(e, 1);
else
e++;
}
}
}

s32 PtrArrayImpl::binarySearch(const void* ptr, CompareCallbackImpl cmp) const
{
if (mPtrNum == 0)
return -1;

s32 low = 0;
s32 high = size() - 1;
while (low < high)
{
const s32 mid = (low + high) / 2;
const s32 c = cmp(mPtrs[mid], ptr);
if (c == 0)
return mid;
if (c < 0)
low = mid + 1;
else
high = mid;
}

if (cmp(mPtrs[low], ptr) == 0)
return low;

return -1;
}

} // namespace sead
Loading