ASTC optimizations (#845)
* ASTC optimizations * Move code to Ryujinx.Common * Support 3D textures * Address feedback * Remove ASTC logging * Use stackalloc instead of a Buffer20 struct * Code style and cleanup * Respond to feedback * Rearrange public/private property ordering
This commit is contained in:
parent
947e14d3be
commit
d1ab9fb42c
12 changed files with 1009 additions and 599 deletions
|
@ -1,11 +1,14 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.Graphics.Texture.Astc
|
||||
{
|
||||
public struct IntegerEncoded
|
||||
internal struct IntegerEncoded
|
||||
{
|
||||
public enum EIntegerEncoding
|
||||
internal const int StructSize = 8;
|
||||
private static readonly IntegerEncoded[] Encodings;
|
||||
|
||||
public enum EIntegerEncoding : byte
|
||||
{
|
||||
JustBits,
|
||||
Quint,
|
||||
|
@ -13,17 +16,27 @@ namespace Ryujinx.Graphics.Texture.Astc
|
|||
}
|
||||
|
||||
EIntegerEncoding _encoding;
|
||||
public int NumberBits { get; private set; }
|
||||
public int BitValue { get; private set; }
|
||||
public int TritValue { get; private set; }
|
||||
public int QuintValue { get; private set; }
|
||||
public byte NumberBits { get; private set; }
|
||||
public byte TritValue { get; private set; }
|
||||
public byte QuintValue { get; private set; }
|
||||
public int BitValue { get; private set; }
|
||||
|
||||
static IntegerEncoded()
|
||||
{
|
||||
Encodings = new IntegerEncoded[0x100];
|
||||
|
||||
for (int i = 0; i < Encodings.Length; i++)
|
||||
{
|
||||
Encodings[i] = CreateEncodingCalc(i);
|
||||
}
|
||||
}
|
||||
|
||||
public IntegerEncoded(EIntegerEncoding encoding, int numBits)
|
||||
{
|
||||
_encoding = encoding;
|
||||
NumberBits = numBits;
|
||||
BitValue = 0;
|
||||
TritValue = 0;
|
||||
_encoding = encoding;
|
||||
NumberBits = (byte)numBits;
|
||||
BitValue = 0;
|
||||
TritValue = 0;
|
||||
QuintValue = 0;
|
||||
}
|
||||
|
||||
|
@ -52,6 +65,11 @@ namespace Ryujinx.Graphics.Texture.Astc
|
|||
}
|
||||
|
||||
public static IntegerEncoded CreateEncoding(int maxVal)
|
||||
{
|
||||
return Encodings[maxVal];
|
||||
}
|
||||
|
||||
private static IntegerEncoded CreateEncodingCalc(int maxVal)
|
||||
{
|
||||
while (maxVal > 0)
|
||||
{
|
||||
|
@ -60,19 +78,19 @@ namespace Ryujinx.Graphics.Texture.Astc
|
|||
// Is maxVal a power of two?
|
||||
if ((check & (check - 1)) == 0)
|
||||
{
|
||||
return new IntegerEncoded(EIntegerEncoding.JustBits, BitArrayStream.PopCnt(maxVal));
|
||||
return new IntegerEncoded(EIntegerEncoding.JustBits, BitOperations.PopCount((uint)maxVal));
|
||||
}
|
||||
|
||||
// Is maxVal of the type 3*2^n - 1?
|
||||
if ((check % 3 == 0) && ((check / 3) & ((check / 3) - 1)) == 0)
|
||||
{
|
||||
return new IntegerEncoded(EIntegerEncoding.Trit, BitArrayStream.PopCnt(check / 3 - 1));
|
||||
return new IntegerEncoded(EIntegerEncoding.Trit, BitOperations.PopCount((uint)(check / 3 - 1)));
|
||||
}
|
||||
|
||||
// Is maxVal of the type 5*2^n - 1?
|
||||
if ((check % 5 == 0) && ((check / 5) & ((check / 5) - 1)) == 0)
|
||||
{
|
||||
return new IntegerEncoded(EIntegerEncoding.Quint, BitArrayStream.PopCnt(check / 5 - 1));
|
||||
return new IntegerEncoded(EIntegerEncoding.Quint, BitOperations.PopCount((uint)(check / 5 - 1)));
|
||||
}
|
||||
|
||||
// Apparently it can't be represented with a bounded integer sequence...
|
||||
|
@ -84,150 +102,78 @@ namespace Ryujinx.Graphics.Texture.Astc
|
|||
}
|
||||
|
||||
public static void DecodeTritBlock(
|
||||
BitArrayStream bitStream,
|
||||
List<IntegerEncoded> listIntegerEncoded,
|
||||
int numberBitsPerValue)
|
||||
ref BitStream128 bitStream,
|
||||
ref IntegerSequence listIntegerEncoded,
|
||||
int numberBitsPerValue)
|
||||
{
|
||||
// Implement the algorithm in section C.2.12
|
||||
int[] m = new int[5];
|
||||
int[] t = new int[5];
|
||||
int T;
|
||||
Span<int> m = stackalloc int[5];
|
||||
|
||||
// Read the trit encoded block according to
|
||||
// table C.2.14
|
||||
m[0] = bitStream.ReadBits(numberBitsPerValue);
|
||||
T = bitStream.ReadBits(2);
|
||||
int encoded = bitStream.ReadBits(2);
|
||||
m[1] = bitStream.ReadBits(numberBitsPerValue);
|
||||
T |= bitStream.ReadBits(2) << 2;
|
||||
encoded |= bitStream.ReadBits(2) << 2;
|
||||
m[2] = bitStream.ReadBits(numberBitsPerValue);
|
||||
T |= bitStream.ReadBits(1) << 4;
|
||||
encoded |= bitStream.ReadBits(1) << 4;
|
||||
m[3] = bitStream.ReadBits(numberBitsPerValue);
|
||||
T |= bitStream.ReadBits(2) << 5;
|
||||
encoded |= bitStream.ReadBits(2) << 5;
|
||||
m[4] = bitStream.ReadBits(numberBitsPerValue);
|
||||
T |= bitStream.ReadBits(1) << 7;
|
||||
encoded |= bitStream.ReadBits(1) << 7;
|
||||
|
||||
int c = 0;
|
||||
ReadOnlySpan<byte> encodings = GetTritEncoding(encoded);
|
||||
|
||||
BitArrayStream tb = new BitArrayStream(new BitArray(new int[] { T }));
|
||||
if (tb.ReadBits(2, 4) == 7)
|
||||
{
|
||||
c = (tb.ReadBits(5, 7) << 2) | tb.ReadBits(0, 1);
|
||||
t[4] = t[3] = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = tb.ReadBits(0, 4);
|
||||
if (tb.ReadBits(5, 6) == 3)
|
||||
{
|
||||
t[4] = 2;
|
||||
t[3] = tb.ReadBit(7);
|
||||
}
|
||||
else
|
||||
{
|
||||
t[4] = tb.ReadBit(7);
|
||||
t[3] = tb.ReadBits(5, 6);
|
||||
}
|
||||
}
|
||||
|
||||
BitArrayStream cb = new BitArrayStream(new BitArray(new int[] { c }));
|
||||
if (cb.ReadBits(0, 1) == 3)
|
||||
{
|
||||
t[2] = 2;
|
||||
t[1] = cb.ReadBit(4);
|
||||
t[0] = (cb.ReadBit(3) << 1) | (cb.ReadBit(2) & ~cb.ReadBit(3));
|
||||
}
|
||||
else if (cb.ReadBits(2, 3) == 3)
|
||||
{
|
||||
t[2] = 2;
|
||||
t[1] = 2;
|
||||
t[0] = cb.ReadBits(0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
t[2] = cb.ReadBit(4);
|
||||
t[1] = cb.ReadBits(2, 3);
|
||||
t[0] = (cb.ReadBit(1) << 1) | (cb.ReadBit(0) & ~cb.ReadBit(1));
|
||||
}
|
||||
IntegerEncoded intEncoded = new IntegerEncoded(EIntegerEncoding.Trit, numberBitsPerValue);
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
IntegerEncoded intEncoded = new IntegerEncoded(EIntegerEncoding.Trit, numberBitsPerValue)
|
||||
{
|
||||
BitValue = m[i],
|
||||
TritValue = t[i]
|
||||
};
|
||||
listIntegerEncoded.Add(intEncoded);
|
||||
intEncoded.BitValue = m[i];
|
||||
intEncoded.TritValue = encodings[i];
|
||||
|
||||
listIntegerEncoded.Add(ref intEncoded);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DecodeQuintBlock(
|
||||
BitArrayStream bitStream,
|
||||
List<IntegerEncoded> listIntegerEncoded,
|
||||
int numberBitsPerValue)
|
||||
ref BitStream128 bitStream,
|
||||
ref IntegerSequence listIntegerEncoded,
|
||||
int numberBitsPerValue)
|
||||
{
|
||||
ReadOnlySpan<byte> interleavedBits = new byte[] { 3, 2, 2 };
|
||||
|
||||
// Implement the algorithm in section C.2.12
|
||||
int[] m = new int[3];
|
||||
int[] qa = new int[3];
|
||||
int q;
|
||||
Span<int> m = stackalloc int[3];
|
||||
ulong encoded = 0;
|
||||
int encodedBitsRead = 0;
|
||||
|
||||
// Read the trit encoded block according to
|
||||
// table C.2.15
|
||||
m[0] = bitStream.ReadBits(numberBitsPerValue);
|
||||
q = bitStream.ReadBits(3);
|
||||
m[1] = bitStream.ReadBits(numberBitsPerValue);
|
||||
q |= bitStream.ReadBits(2) << 3;
|
||||
m[2] = bitStream.ReadBits(numberBitsPerValue);
|
||||
q |= bitStream.ReadBits(2) << 5;
|
||||
|
||||
BitArrayStream qb = new BitArrayStream(new BitArray(new int[] { q }));
|
||||
if (qb.ReadBits(1, 2) == 3 && qb.ReadBits(5, 6) == 0)
|
||||
for (int i = 0; i < m.Length; i++)
|
||||
{
|
||||
qa[0] = qa[1] = 4;
|
||||
qa[2] = (qb.ReadBit(0) << 2) | ((qb.ReadBit(4) & ~qb.ReadBit(0)) << 1) | (qb.ReadBit(3) & ~qb.ReadBit(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
int c = 0;
|
||||
if (qb.ReadBits(1, 2) == 3)
|
||||
{
|
||||
qa[2] = 4;
|
||||
c = (qb.ReadBits(3, 4) << 3) | ((~qb.ReadBits(5, 6) & 3) << 1) | qb.ReadBit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
qa[2] = qb.ReadBits(5, 6);
|
||||
c = qb.ReadBits(0, 4);
|
||||
}
|
||||
m[i] = bitStream.ReadBits(numberBitsPerValue);
|
||||
|
||||
BitArrayStream cb = new BitArrayStream(new BitArray(new int[] { c }));
|
||||
if (cb.ReadBits(0, 2) == 5)
|
||||
{
|
||||
qa[1] = 4;
|
||||
qa[0] = cb.ReadBits(3, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
qa[1] = cb.ReadBits(3, 4);
|
||||
qa[0] = cb.ReadBits(0, 2);
|
||||
}
|
||||
uint encodedBits = (uint)bitStream.ReadBits(interleavedBits[i]);
|
||||
|
||||
encoded |= encodedBits << encodedBitsRead;
|
||||
encodedBitsRead += interleavedBits[i];
|
||||
}
|
||||
|
||||
ReadOnlySpan<byte> encodings = GetQuintEncoding((int)encoded);
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
IntegerEncoded intEncoded = new IntegerEncoded(EIntegerEncoding.Quint, numberBitsPerValue)
|
||||
{
|
||||
BitValue = m[i],
|
||||
QuintValue = qa[i]
|
||||
BitValue = m[i],
|
||||
QuintValue = encodings[i]
|
||||
};
|
||||
listIntegerEncoded.Add(intEncoded);
|
||||
|
||||
listIntegerEncoded.Add(ref intEncoded);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DecodeIntegerSequence(
|
||||
List<IntegerEncoded> decodeIntegerSequence,
|
||||
BitArrayStream bitStream,
|
||||
int maxRange,
|
||||
int numberValues)
|
||||
ref IntegerSequence decodeIntegerSequence,
|
||||
ref BitStream128 bitStream,
|
||||
int maxRange,
|
||||
int numberValues)
|
||||
{
|
||||
// Determine encoding parameters
|
||||
IntegerEncoded intEncoded = CreateEncoding(maxRange);
|
||||
|
@ -240,7 +186,7 @@ namespace Ryujinx.Graphics.Texture.Astc
|
|||
{
|
||||
case EIntegerEncoding.Quint:
|
||||
{
|
||||
DecodeQuintBlock(bitStream, decodeIntegerSequence, intEncoded.NumberBits);
|
||||
DecodeQuintBlock(ref bitStream, ref decodeIntegerSequence, intEncoded.NumberBits);
|
||||
numberValuesDecoded += 3;
|
||||
|
||||
break;
|
||||
|
@ -248,7 +194,7 @@ namespace Ryujinx.Graphics.Texture.Astc
|
|||
|
||||
case EIntegerEncoding.Trit:
|
||||
{
|
||||
DecodeTritBlock(bitStream, decodeIntegerSequence, intEncoded.NumberBits);
|
||||
DecodeTritBlock(ref bitStream, ref decodeIntegerSequence, intEncoded.NumberBits);
|
||||
numberValuesDecoded += 5;
|
||||
|
||||
break;
|
||||
|
@ -257,7 +203,7 @@ namespace Ryujinx.Graphics.Texture.Astc
|
|||
case EIntegerEncoding.JustBits:
|
||||
{
|
||||
intEncoded.BitValue = bitStream.ReadBits(intEncoded.NumberBits);
|
||||
decodeIntegerSequence.Add(intEncoded);
|
||||
decodeIntegerSequence.Add(ref intEncoded);
|
||||
numberValuesDecoded++;
|
||||
|
||||
break;
|
||||
|
@ -265,5 +211,135 @@ namespace Ryujinx.Graphics.Texture.Astc
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> GetTritEncoding(int index)
|
||||
{
|
||||
return TritEncodings.Slice(index * 5, 5);
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> GetQuintEncoding(int index)
|
||||
{
|
||||
return QuintEncodings.Slice(index * 3, 3);
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> TritEncodings => new byte[]
|
||||
{
|
||||
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0,
|
||||
0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0,
|
||||
2, 1, 0, 0, 0, 1, 0, 2, 0, 0, 0, 2, 0, 0, 0,
|
||||
1, 2, 0, 0, 0, 2, 2, 0, 0, 0, 2, 0, 2, 0, 0,
|
||||
0, 2, 2, 0, 0, 1, 2, 2, 0, 0, 2, 2, 2, 0, 0,
|
||||
2, 0, 2, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0,
|
||||
2, 0, 1, 0, 0, 0, 1, 2, 0, 0, 0, 1, 1, 0, 0,
|
||||
1, 1, 1, 0, 0, 2, 1, 1, 0, 0, 1, 1, 2, 0, 0,
|
||||
0, 2, 1, 0, 0, 1, 2, 1, 0, 0, 2, 2, 1, 0, 0,
|
||||
2, 1, 2, 0, 0, 0, 0, 0, 2, 2, 1, 0, 0, 2, 2,
|
||||
2, 0, 0, 2, 2, 0, 0, 2, 2, 2, 0, 0, 0, 1, 0,
|
||||
1, 0, 0, 1, 0, 2, 0, 0, 1, 0, 0, 0, 2, 1, 0,
|
||||
0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 2, 1, 0, 1, 0,
|
||||
1, 0, 2, 1, 0, 0, 2, 0, 1, 0, 1, 2, 0, 1, 0,
|
||||
2, 2, 0, 1, 0, 2, 0, 2, 1, 0, 0, 2, 2, 1, 0,
|
||||
1, 2, 2, 1, 0, 2, 2, 2, 1, 0, 2, 0, 2, 1, 0,
|
||||
0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 2, 0, 1, 1, 0,
|
||||
0, 1, 2, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0,
|
||||
2, 1, 1, 1, 0, 1, 1, 2, 1, 0, 0, 2, 1, 1, 0,
|
||||
1, 2, 1, 1, 0, 2, 2, 1, 1, 0, 2, 1, 2, 1, 0,
|
||||
0, 1, 0, 2, 2, 1, 1, 0, 2, 2, 2, 1, 0, 2, 2,
|
||||
1, 0, 2, 2, 2, 0, 0, 0, 2, 0, 1, 0, 0, 2, 0,
|
||||
2, 0, 0, 2, 0, 0, 0, 2, 2, 0, 0, 1, 0, 2, 0,
|
||||
1, 1, 0, 2, 0, 2, 1, 0, 2, 0, 1, 0, 2, 2, 0,
|
||||
0, 2, 0, 2, 0, 1, 2, 0, 2, 0, 2, 2, 0, 2, 0,
|
||||
2, 0, 2, 2, 0, 0, 2, 2, 2, 0, 1, 2, 2, 2, 0,
|
||||
2, 2, 2, 2, 0, 2, 0, 2, 2, 0, 0, 0, 1, 2, 0,
|
||||
1, 0, 1, 2, 0, 2, 0, 1, 2, 0, 0, 1, 2, 2, 0,
|
||||
0, 1, 1, 2, 0, 1, 1, 1, 2, 0, 2, 1, 1, 2, 0,
|
||||
1, 1, 2, 2, 0, 0, 2, 1, 2, 0, 1, 2, 1, 2, 0,
|
||||
2, 2, 1, 2, 0, 2, 1, 2, 2, 0, 0, 2, 0, 2, 2,
|
||||
1, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2,
|
||||
0, 0, 0, 0, 2, 1, 0, 0, 0, 2, 2, 0, 0, 0, 2,
|
||||
0, 0, 2, 0, 2, 0, 1, 0, 0, 2, 1, 1, 0, 0, 2,
|
||||
2, 1, 0, 0, 2, 1, 0, 2, 0, 2, 0, 2, 0, 0, 2,
|
||||
1, 2, 0, 0, 2, 2, 2, 0, 0, 2, 2, 0, 2, 0, 2,
|
||||
0, 2, 2, 0, 2, 1, 2, 2, 0, 2, 2, 2, 2, 0, 2,
|
||||
2, 0, 2, 0, 2, 0, 0, 1, 0, 2, 1, 0, 1, 0, 2,
|
||||
2, 0, 1, 0, 2, 0, 1, 2, 0, 2, 0, 1, 1, 0, 2,
|
||||
1, 1, 1, 0, 2, 2, 1, 1, 0, 2, 1, 1, 2, 0, 2,
|
||||
0, 2, 1, 0, 2, 1, 2, 1, 0, 2, 2, 2, 1, 0, 2,
|
||||
2, 1, 2, 0, 2, 0, 2, 2, 2, 2, 1, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1,
|
||||
1, 0, 0, 0, 1, 2, 0, 0, 0, 1, 0, 0, 2, 0, 1,
|
||||
0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 2, 1, 0, 0, 1,
|
||||
1, 0, 2, 0, 1, 0, 2, 0, 0, 1, 1, 2, 0, 0, 1,
|
||||
2, 2, 0, 0, 1, 2, 0, 2, 0, 1, 0, 2, 2, 0, 1,
|
||||
1, 2, 2, 0, 1, 2, 2, 2, 0, 1, 2, 0, 2, 0, 1,
|
||||
0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 2, 0, 1, 0, 1,
|
||||
0, 1, 2, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1,
|
||||
2, 1, 1, 0, 1, 1, 1, 2, 0, 1, 0, 2, 1, 0, 1,
|
||||
1, 2, 1, 0, 1, 2, 2, 1, 0, 1, 2, 1, 2, 0, 1,
|
||||
0, 0, 1, 2, 2, 1, 0, 1, 2, 2, 2, 0, 1, 2, 2,
|
||||
0, 1, 2, 2, 2, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1,
|
||||
2, 0, 0, 1, 1, 0, 0, 2, 1, 1, 0, 1, 0, 1, 1,
|
||||
1, 1, 0, 1, 1, 2, 1, 0, 1, 1, 1, 0, 2, 1, 1,
|
||||
0, 2, 0, 1, 1, 1, 2, 0, 1, 1, 2, 2, 0, 1, 1,
|
||||
2, 0, 2, 1, 1, 0, 2, 2, 1, 1, 1, 2, 2, 1, 1,
|
||||
2, 2, 2, 1, 1, 2, 0, 2, 1, 1, 0, 0, 1, 1, 1,
|
||||
1, 0, 1, 1, 1, 2, 0, 1, 1, 1, 0, 1, 2, 1, 1,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1,
|
||||
1, 1, 2, 1, 1, 0, 2, 1, 1, 1, 1, 2, 1, 1, 1,
|
||||
2, 2, 1, 1, 1, 2, 1, 2, 1, 1, 0, 1, 1, 2, 2,
|
||||
1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2,
|
||||
0, 0, 0, 2, 1, 1, 0, 0, 2, 1, 2, 0, 0, 2, 1,
|
||||
0, 0, 2, 2, 1, 0, 1, 0, 2, 1, 1, 1, 0, 2, 1,
|
||||
2, 1, 0, 2, 1, 1, 0, 2, 2, 1, 0, 2, 0, 2, 1,
|
||||
1, 2, 0, 2, 1, 2, 2, 0, 2, 1, 2, 0, 2, 2, 1,
|
||||
0, 2, 2, 2, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 1,
|
||||
2, 0, 2, 2, 1, 0, 0, 1, 2, 1, 1, 0, 1, 2, 1,
|
||||
2, 0, 1, 2, 1, 0, 1, 2, 2, 1, 0, 1, 1, 2, 1,
|
||||
1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 1, 2, 2, 1,
|
||||
0, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1,
|
||||
2, 1, 2, 2, 1, 0, 2, 1, 2, 2, 1, 2, 1, 2, 2,
|
||||
2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 0, 0, 0, 1, 2,
|
||||
1, 0, 0, 1, 2, 2, 0, 0, 1, 2, 0, 0, 2, 1, 2,
|
||||
0, 1, 0, 1, 2, 1, 1, 0, 1, 2, 2, 1, 0, 1, 2,
|
||||
1, 0, 2, 1, 2, 0, 2, 0, 1, 2, 1, 2, 0, 1, 2,
|
||||
2, 2, 0, 1, 2, 2, 0, 2, 1, 2, 0, 2, 2, 1, 2,
|
||||
1, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 0, 2, 1, 2,
|
||||
0, 0, 1, 1, 2, 1, 0, 1, 1, 2, 2, 0, 1, 1, 2,
|
||||
0, 1, 2, 1, 2, 0, 1, 1, 1, 2, 1, 1, 1, 1, 2,
|
||||
2, 1, 1, 1, 2, 1, 1, 2, 1, 2, 0, 2, 1, 1, 2,
|
||||
1, 2, 1, 1, 2, 2, 2, 1, 1, 2, 2, 1, 2, 1, 2,
|
||||
0, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 1, 2, 2, 2
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> QuintEncodings => new byte[]
|
||||
{
|
||||
0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0,
|
||||
0, 4, 0, 4, 4, 0, 4, 4, 4, 0, 1, 0, 1, 1, 0,
|
||||
2, 1, 0, 3, 1, 0, 4, 1, 0, 1, 4, 0, 4, 4, 1,
|
||||
4, 4, 4, 0, 2, 0, 1, 2, 0, 2, 2, 0, 3, 2, 0,
|
||||
4, 2, 0, 2, 4, 0, 4, 4, 2, 4, 4, 4, 0, 3, 0,
|
||||
1, 3, 0, 2, 3, 0, 3, 3, 0, 4, 3, 0, 3, 4, 0,
|
||||
4, 4, 3, 4, 4, 4, 0, 0, 1, 1, 0, 1, 2, 0, 1,
|
||||
3, 0, 1, 4, 0, 1, 0, 4, 1, 4, 0, 4, 0, 4, 4,
|
||||
0, 1, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1, 4, 1, 1,
|
||||
1, 4, 1, 4, 1, 4, 1, 4, 4, 0, 2, 1, 1, 2, 1,
|
||||
2, 2, 1, 3, 2, 1, 4, 2, 1, 2, 4, 1, 4, 2, 4,
|
||||
2, 4, 4, 0, 3, 1, 1, 3, 1, 2, 3, 1, 3, 3, 1,
|
||||
4, 3, 1, 3, 4, 1, 4, 3, 4, 3, 4, 4, 0, 0, 2,
|
||||
1, 0, 2, 2, 0, 2, 3, 0, 2, 4, 0, 2, 0, 4, 2,
|
||||
2, 0, 4, 3, 0, 4, 0, 1, 2, 1, 1, 2, 2, 1, 2,
|
||||
3, 1, 2, 4, 1, 2, 1, 4, 2, 2, 1, 4, 3, 1, 4,
|
||||
0, 2, 2, 1, 2, 2, 2, 2, 2, 3, 2, 2, 4, 2, 2,
|
||||
2, 4, 2, 2, 2, 4, 3, 2, 4, 0, 3, 2, 1, 3, 2,
|
||||
2, 3, 2, 3, 3, 2, 4, 3, 2, 3, 4, 2, 2, 3, 4,
|
||||
3, 3, 4, 0, 0, 3, 1, 0, 3, 2, 0, 3, 3, 0, 3,
|
||||
4, 0, 3, 0, 4, 3, 0, 0, 4, 1, 0, 4, 0, 1, 3,
|
||||
1, 1, 3, 2, 1, 3, 3, 1, 3, 4, 1, 3, 1, 4, 3,
|
||||
0, 1, 4, 1, 1, 4, 0, 2, 3, 1, 2, 3, 2, 2, 3,
|
||||
3, 2, 3, 4, 2, 3, 2, 4, 3, 0, 2, 4, 1, 2, 4,
|
||||
0, 3, 3, 1, 3, 3, 2, 3, 3, 3, 3, 3, 4, 3, 3,
|
||||
3, 4, 3, 0, 3, 4, 1, 3, 4
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue