mirror of
https://github.com/ryujinx-mirror/ryujinx.git
synced 2025-09-17 16:07:54 -05:00
Implement NGC service (#5681)
* Implement NGC service * Use raw byte arrays instead of string for _wordSeparators * Silence IDE0230 for _wordSeparators * Try to silence warning about _rangeValuesCount not being read on SparseSet * Make AcType enum private * Add abstract methods and one TODO that I forgot * PR feedback * More PR feedback * More PR feedback
This commit is contained in:
162
src/Ryujinx.Horizon/Sdk/Ngc/Detail/SbvRank.cs
Normal file
162
src/Ryujinx.Horizon/Sdk/Ngc/Detail/SbvRank.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.Horizon.Sdk.Ngc.Detail
|
||||
{
|
||||
class SbvRank
|
||||
{
|
||||
private const int BitsPerWord = Set.BitsPerWord;
|
||||
private const int Rank1Entries = 8;
|
||||
private const int BitsPerRank0Entry = BitsPerWord * Rank1Entries;
|
||||
|
||||
private uint[] _rank0;
|
||||
private byte[] _rank1;
|
||||
|
||||
public SbvRank()
|
||||
{
|
||||
}
|
||||
|
||||
public SbvRank(ReadOnlySpan<uint> bitmap, int setCapacity)
|
||||
{
|
||||
Build(bitmap, setCapacity);
|
||||
}
|
||||
|
||||
public void Build(ReadOnlySpan<uint> bitmap, int setCapacity)
|
||||
{
|
||||
_rank0 = new uint[CalculateRank0Length(setCapacity)];
|
||||
_rank1 = new byte[CalculateRank1Length(setCapacity)];
|
||||
|
||||
BuildRankDictionary(_rank0, _rank1, (setCapacity + BitsPerWord - 1) / BitsPerWord, bitmap);
|
||||
}
|
||||
|
||||
private static void BuildRankDictionary(Span<uint> rank0, Span<byte> rank1, int length, ReadOnlySpan<uint> bitmap)
|
||||
{
|
||||
uint rank0Count;
|
||||
uint rank1Count = 0;
|
||||
|
||||
for (int index = 0; index < length; index++)
|
||||
{
|
||||
if ((index % Rank1Entries) != 0)
|
||||
{
|
||||
rank0Count = rank0[index / Rank1Entries];
|
||||
}
|
||||
else
|
||||
{
|
||||
rank0[index / Rank1Entries] = rank1Count;
|
||||
rank0Count = rank1Count;
|
||||
}
|
||||
|
||||
rank1[index] = (byte)(rank1Count - rank0Count);
|
||||
|
||||
rank1Count += (uint)BitOperations.PopCount(bitmap[index]);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Import(ref BinaryReader reader, int setCapacity)
|
||||
{
|
||||
if (setCapacity == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int rank0Length = CalculateRank0Length(setCapacity);
|
||||
int rank1Length = CalculateRank1Length(setCapacity);
|
||||
|
||||
return reader.AllocateAndReadArray(ref _rank0, rank0Length) == rank0Length &&
|
||||
reader.AllocateAndReadArray(ref _rank1, rank1Length) == rank1Length;
|
||||
}
|
||||
|
||||
public int CalcRank1(int index, uint[] membershipBitmap)
|
||||
{
|
||||
int rank0Index = index / BitsPerRank0Entry;
|
||||
int rank1Index = index / BitsPerWord;
|
||||
|
||||
uint membershipBits = membershipBitmap[rank1Index] & (uint.MaxValue >> (BitsPerWord - 1 - (index % BitsPerWord)));
|
||||
|
||||
return (int)_rank0[rank0Index] + _rank1[rank1Index] + BitOperations.PopCount(membershipBits);
|
||||
}
|
||||
|
||||
public int CalcSelect0(int index, int length, uint[] membershipBitmap)
|
||||
{
|
||||
int rank0Index;
|
||||
|
||||
if (length > BitsPerRank0Entry)
|
||||
{
|
||||
int left = 0;
|
||||
int right = (length + BitsPerRank0Entry - 1) / BitsPerRank0Entry;
|
||||
|
||||
while (true)
|
||||
{
|
||||
int range = right - left;
|
||||
if (range < 0)
|
||||
{
|
||||
range++;
|
||||
}
|
||||
|
||||
int middle = left + (range / 2);
|
||||
|
||||
int foundIndex = middle * BitsPerRank0Entry - (int)_rank0[middle];
|
||||
|
||||
if ((uint)foundIndex <= (uint)index)
|
||||
{
|
||||
left = middle;
|
||||
}
|
||||
else
|
||||
{
|
||||
right = middle;
|
||||
}
|
||||
|
||||
if (right <= left + 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rank0Index = left;
|
||||
}
|
||||
else
|
||||
{
|
||||
rank0Index = 0;
|
||||
}
|
||||
|
||||
int lengthInWords = (length + BitsPerWord - 1) / BitsPerWord;
|
||||
int rank1WordsCount = rank0Index == (length / BitsPerRank0Entry) && (lengthInWords % Rank1Entries) != 0
|
||||
? lengthInWords % Rank1Entries
|
||||
: Rank1Entries;
|
||||
|
||||
int baseIndex = (int)_rank0[rank0Index] + rank0Index * -BitsPerRank0Entry + index;
|
||||
int plainIndex;
|
||||
int count;
|
||||
int remainingBits;
|
||||
uint membershipBits;
|
||||
|
||||
for (plainIndex = rank0Index * Rank1Entries - 1, count = 0; count < rank1WordsCount; plainIndex++, count++)
|
||||
{
|
||||
int currentIndex = baseIndex + count * -BitsPerWord;
|
||||
|
||||
if (_rank1[plainIndex + 1] + currentIndex < 0)
|
||||
{
|
||||
remainingBits = _rank1[plainIndex] + currentIndex + BitsPerWord;
|
||||
membershipBits = ~membershipBitmap[plainIndex];
|
||||
|
||||
return plainIndex * BitsPerWord + SbvSelect.SelectPos(membershipBits, remainingBits);
|
||||
}
|
||||
}
|
||||
|
||||
remainingBits = _rank1[plainIndex] + baseIndex + (rank1WordsCount - 1) * -BitsPerWord;
|
||||
membershipBits = ~membershipBitmap[plainIndex];
|
||||
|
||||
return plainIndex * BitsPerWord + SbvSelect.SelectPos(membershipBits, remainingBits);
|
||||
}
|
||||
|
||||
private static int CalculateRank0Length(int setCapacity)
|
||||
{
|
||||
return (setCapacity / (BitsPerWord * Rank1Entries)) + 1;
|
||||
}
|
||||
|
||||
private static int CalculateRank1Length(int setCapacity)
|
||||
{
|
||||
return (setCapacity / BitsPerWord) + 1;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user