mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 18:14:37 +08:00
1079 lines
35 KiB
C#
1079 lines
35 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Text.RegularExpressions;
|
|
using static DCFApixels.BitsUtility;
|
|
|
|
namespace DCFApixels
|
|
{
|
|
public unsafe static class BitsUtility
|
|
{
|
|
private const char DEFAULT_SEPARATOR = '_';
|
|
private const int BYTE_BITS = 8;
|
|
|
|
#region CountBits
|
|
public static unsafe int CountBits8<T>(T bits) where T : unmanaged
|
|
{
|
|
return CountBits((uint)*(byte*)&bits);
|
|
}
|
|
public static unsafe int CountBits16<T>(T bits) where T : unmanaged
|
|
{
|
|
return CountBits((uint)*(ushort*)&bits);
|
|
}
|
|
|
|
public static unsafe int CountBits32<T>(T bits) where T : unmanaged
|
|
{
|
|
return CountBits(*(uint*)&bits);
|
|
}
|
|
public static unsafe int CountBits(float bits)
|
|
{
|
|
return CountBits32(bits);
|
|
}
|
|
public static unsafe int CountBits(int bits)
|
|
{
|
|
return CountBits((uint)bits);
|
|
}
|
|
public static unsafe int CountBits(uint bits)
|
|
{
|
|
bits = bits - ((bits >> 1) & 0x55555555);
|
|
bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
|
|
return (int)(((bits + (bits >> 4) & 0xF0F0F0F) * 0x1010101) >> 24);
|
|
}
|
|
|
|
public static unsafe int CountBits64<T>(T bits) where T : unmanaged
|
|
{
|
|
return CountBits(*(ulong*)&bits);
|
|
}
|
|
public static unsafe int CountBits(double bits)
|
|
{
|
|
return CountBits64(bits);
|
|
}
|
|
public static unsafe int CountBits(long bits)
|
|
{
|
|
return CountBits((ulong)bits);
|
|
}
|
|
public static unsafe int CountBits(ulong bits)
|
|
{
|
|
bits = bits - ((bits >> 1) & 0x55555555_55555555);
|
|
bits = (bits & 0x33333333_33333333) + ((bits >> 2) & 0x33333333_33333333);
|
|
return (int)(((bits + (bits >> 4) & 0x0F0F0F0F_0F0F0F0F) * 0x01010101_01010101) >> (24 + 32));
|
|
}
|
|
#endregion
|
|
|
|
#region GetHighBitNumber
|
|
public static unsafe int GetHighBitNumber8<T>(T bits) where T : unmanaged
|
|
{
|
|
return GetHighBitNumber(*(byte*)&bits);
|
|
}
|
|
public static int GetHighBitNumber(sbyte bits)
|
|
{
|
|
return GetHighBitNumber((byte)bits);
|
|
}
|
|
public static int GetHighBitNumber(byte bits)
|
|
{
|
|
if (bits == 0)
|
|
{
|
|
return -1;
|
|
}
|
|
int bit = 0;
|
|
if ((bits & 0xF0) != 0)
|
|
{
|
|
bits >>= 4;
|
|
bit |= 4;
|
|
}
|
|
if ((bits & 0xC) != 0)
|
|
{
|
|
bits >>= 2;
|
|
bit |= 2;
|
|
}
|
|
if ((bits & 0x2) != 0)
|
|
{
|
|
bit |= 1;
|
|
}
|
|
return bit;
|
|
}
|
|
|
|
public static unsafe int GetHighBitNumber16<T>(T bits) where T : unmanaged
|
|
{
|
|
return GetHighBitNumber(*(ushort*)&bits);
|
|
}
|
|
public static int GetHighBitNumber(short bits)
|
|
{
|
|
return GetHighBitNumber((ushort)bits);
|
|
}
|
|
public static int GetHighBitNumber(ushort bits)
|
|
{
|
|
if (bits == 0)
|
|
{
|
|
return -1;
|
|
}
|
|
int bit = 0;
|
|
if ((bits & 0xFF00) != 0)
|
|
{
|
|
bits >>= 8;
|
|
bit |= 8;
|
|
}
|
|
if ((bits & 0xF0) != 0)
|
|
{
|
|
bits >>= 4;
|
|
bit |= 4;
|
|
}
|
|
if ((bits & 0xC) != 0)
|
|
{
|
|
bits >>= 2;
|
|
bit |= 2;
|
|
}
|
|
if ((bits & 0x2) != 0)
|
|
{
|
|
bit |= 1;
|
|
}
|
|
return bit;
|
|
}
|
|
|
|
public static unsafe int GetHighBitNumber32<T>(T bits) where T : unmanaged
|
|
{
|
|
return GetHighBitNumber(*(uint*)&bits);
|
|
}
|
|
public static int GetHighBitNumber(float bits)
|
|
{
|
|
return GetHighBitNumber(*(uint*)&bits);
|
|
}
|
|
public static int GetHighBitNumber(int bits)
|
|
{
|
|
return GetHighBitNumber((uint)bits);
|
|
}
|
|
public static int GetHighBitNumber(uint bits)
|
|
{
|
|
if (bits == 0)
|
|
{
|
|
return -1;
|
|
}
|
|
int bit = 0;
|
|
if ((bits & 0xFFFF0000) != 0)
|
|
{
|
|
bits >>= 16;
|
|
bit |= 16;
|
|
}
|
|
if ((bits & 0xFF00) != 0)
|
|
{
|
|
bits >>= 8;
|
|
bit |= 8;
|
|
}
|
|
if ((bits & 0xF0) != 0)
|
|
{
|
|
bits >>= 4;
|
|
bit |= 4;
|
|
}
|
|
if ((bits & 0xC) != 0)
|
|
{
|
|
bits >>= 2;
|
|
bit |= 2;
|
|
}
|
|
if ((bits & 0x2) != 0)
|
|
{
|
|
bit |= 1;
|
|
}
|
|
return bit;
|
|
}
|
|
|
|
public static unsafe int GetHighBitNumber64<T>(T bits) where T : unmanaged
|
|
{
|
|
return GetHighBitNumber(*(ulong*)&bits);
|
|
}
|
|
public static int GetHighBitNumber(double bits)
|
|
{
|
|
return GetHighBitNumber(*(ulong*)&bits);
|
|
}
|
|
public static int GetHighBitNumber(long bits)
|
|
{
|
|
return GetHighBitNumber((ulong)bits);
|
|
}
|
|
public static int GetHighBitNumber(ulong bits)
|
|
{
|
|
if (bits == 0)
|
|
{
|
|
return -1;
|
|
}
|
|
int bit = 0;
|
|
if ((bits & 0xFFFFFFFF00000000) != 0)
|
|
{
|
|
bits >>= 32;
|
|
bit |= 32;
|
|
}
|
|
if ((bits & 0xFFFF0000) != 0)
|
|
{
|
|
bits >>= 16;
|
|
bit |= 16;
|
|
}
|
|
if ((bits & 0xFF00) != 0)
|
|
{
|
|
bits >>= 8;
|
|
bit |= 8;
|
|
}
|
|
if ((bits & 0xF0) != 0)
|
|
{
|
|
bits >>= 4;
|
|
bit |= 4;
|
|
}
|
|
if ((bits & 0xC) != 0)
|
|
{
|
|
bits >>= 2;
|
|
bit |= 2;
|
|
}
|
|
if ((bits & 0x2) != 0)
|
|
{
|
|
bit |= 1;
|
|
}
|
|
return bit;
|
|
}
|
|
#endregion
|
|
|
|
#region GetBitNumbers
|
|
public static unsafe int[] GetBitNumbers32<T>(T bits) where T : unmanaged
|
|
{
|
|
return GetBitNumbers(*(uint*)&bits);
|
|
}
|
|
public static unsafe int[] GetBitNumbers(float bits)
|
|
{
|
|
return GetBitNumbers(*(uint*)&bits);
|
|
}
|
|
public static int[] GetBitNumbers(int bits)
|
|
{
|
|
return GetBitNumbers((uint)bits);
|
|
}
|
|
public static int[] GetBitNumbers(uint bits)
|
|
{
|
|
int[] result = new int[CountBits(bits)];
|
|
for (int i = 0; i < result.Length; i++)
|
|
{
|
|
int number = GetHighBitNumber(bits);
|
|
result[i] = number;
|
|
bits ^= 1u << number;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static unsafe int GetBitNumbersNoAlloc32<T>(T bits, ref int[] numbers) where T : unmanaged
|
|
{
|
|
return GetBitNumbersNoAlloc(*(uint*)&bits, ref numbers);
|
|
}
|
|
public static unsafe int GetBitNumbersNoAlloc(float bits, ref int[] numbers)
|
|
{
|
|
return GetBitNumbersNoAlloc(*(uint*)&bits, ref numbers);
|
|
}
|
|
public static int GetBitNumbersNoAlloc(int bits, ref int[] numbers)
|
|
{
|
|
return GetBitNumbersNoAlloc((uint)bits, ref numbers);
|
|
}
|
|
public static int GetBitNumbersNoAlloc(uint bits, ref int[] numbers)
|
|
{
|
|
int iMax = CountBits(bits);
|
|
if (iMax >= numbers.Length)
|
|
Array.Resize(ref numbers, iMax);
|
|
for (int i = 0; i < iMax; i++)
|
|
{
|
|
int number = GetHighBitNumber(bits);
|
|
numbers[i] = number;
|
|
bits ^= 1u << number;
|
|
}
|
|
return iMax;
|
|
}
|
|
public static unsafe void GetBitNumbersNoAlloc32<T>(T bits, List<int> numbers) where T : unmanaged
|
|
{
|
|
GetBitNumbersNoAlloc(*(uint*)&bits, numbers);
|
|
}
|
|
public static unsafe void GetBitNumbersNoAlloc(float bits, List<int> numbers)
|
|
{
|
|
GetBitNumbersNoAlloc(*(uint*)&bits, numbers);
|
|
}
|
|
public static void GetBitNumbersNoAlloc(int bits, List<int> numbers)
|
|
{
|
|
GetBitNumbersNoAlloc((uint)bits, numbers);
|
|
}
|
|
public static void GetBitNumbersNoAlloc(uint bits, List<int> numbers)
|
|
{
|
|
numbers.Clear();
|
|
int iMax = CountBits(bits);
|
|
for (int i = 0; i < iMax; i++)
|
|
{
|
|
int number = GetHighBitNumber(bits);
|
|
numbers[i] = number;
|
|
bits ^= 1u << number;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public static unsafe int[] GetBitNumbers64<T>(T bits) where T : unmanaged
|
|
{
|
|
return GetBitNumbers(*(ulong*)&bits);
|
|
}
|
|
public static unsafe int[] GetBitNumbers(double bits)
|
|
{
|
|
return GetBitNumbers(*(ulong*)&bits);
|
|
}
|
|
public static int[] GetBitNumbers(long bits)
|
|
{
|
|
return GetBitNumbers((ulong)bits);
|
|
}
|
|
public static int[] GetBitNumbers(ulong bits)
|
|
{
|
|
int[] result = new int[CountBits(bits)];
|
|
for (int i = 0; i < result.Length; i++)
|
|
{
|
|
int number = GetHighBitNumber(bits);
|
|
result[i] = number;
|
|
bits ^= 1LU << number;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static unsafe int GetBitNumbersNoAlloc64<T>(T bits, ref int[] numbers) where T : unmanaged
|
|
{
|
|
return GetBitNumbersNoAlloc(*(ulong*)&bits, ref numbers);
|
|
}
|
|
public static unsafe int GetBitNumbersNoAlloc(double bits, ref int[] numbers)
|
|
{
|
|
return GetBitNumbersNoAlloc(*(ulong*)&bits, ref numbers);
|
|
}
|
|
public static int GetBitNumbersNoAlloc(long bits, ref int[] numbers)
|
|
{
|
|
return GetBitNumbersNoAlloc((ulong)bits, ref numbers);
|
|
}
|
|
public static int GetBitNumbersNoAlloc(ulong bits, ref int[] numbers)
|
|
{
|
|
int iMax = CountBits(bits);
|
|
if (iMax >= numbers.Length)
|
|
Array.Resize(ref numbers, iMax);
|
|
for (int i = 0; i < iMax; i++)
|
|
{
|
|
int number = GetHighBitNumber(bits);
|
|
numbers[i] = number;
|
|
bits ^= 1u << number;
|
|
}
|
|
return iMax;
|
|
}
|
|
public static unsafe void GetBitNumbersNoAlloc64<T>(T bits, List<int> numbers) where T : unmanaged
|
|
{
|
|
GetBitNumbersNoAlloc(*(ulong*)&bits, numbers);
|
|
}
|
|
public static unsafe void GetBitNumbersNoAlloc(double bits, List<int> numbers)
|
|
{
|
|
GetBitNumbersNoAlloc(*(ulong*)&bits, numbers);
|
|
}
|
|
public static void GetBitNumbersNoAlloc(long bits, List<int> numbers)
|
|
{
|
|
GetBitNumbersNoAlloc((ulong)bits, numbers);
|
|
}
|
|
public static void GetBitNumbersNoAlloc(ulong bits, List<int> numbers)
|
|
{
|
|
numbers.Clear();
|
|
int iMax = CountBits(bits);
|
|
for (int i = 0; i < iMax; i++)
|
|
{
|
|
int number = GetHighBitNumber(bits);
|
|
numbers[i] = number;
|
|
bits ^= 1u << number;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region ToBitsString
|
|
public static string ToBitsString<T>(T value, bool withSeparator) where T : unmanaged
|
|
{
|
|
return ToBitsStringInaternal(value, withSeparator ? BYTE_BITS : 0, DEFAULT_SEPARATOR);
|
|
}
|
|
public static string ToBitsString<T>(T value, int separateRange) where T : unmanaged
|
|
{
|
|
return ToBitsStringInaternal(value, separateRange, DEFAULT_SEPARATOR);
|
|
}
|
|
public static string ToBitsString<T>(T value, char separator = DEFAULT_SEPARATOR, int separateRange = BYTE_BITS) where T : unmanaged
|
|
{
|
|
return ToBitsStringInaternal(value, separateRange, separator);
|
|
}
|
|
private static unsafe string ToBitsStringInaternal<T>(T value, int separateRange, char separator) where T : unmanaged
|
|
{
|
|
int size = sizeof(T);
|
|
int length = size * BYTE_BITS;
|
|
//byte* bytes = stackalloc byte[size / BYTE_BITS];
|
|
byte* bytes = (byte*)&value;
|
|
char* str = stackalloc char[length];
|
|
|
|
for (int i = 0; i < length; i++)
|
|
str[length - i - 1] = (bytes[i / BYTE_BITS] & 1 << (i % BYTE_BITS)) > 0 ? '1' : '0';
|
|
|
|
if (separateRange > 0)
|
|
return Regex.Replace(new string(str, 0, length), ".{" + separateRange + "}", "$0" + separator + "");
|
|
else
|
|
return new string(str, 0, length);
|
|
}
|
|
#endregion
|
|
|
|
#region ParceBitString
|
|
public static ulong ToULong(string bitsString)
|
|
{
|
|
const int BIT_SIZE = 64;
|
|
ulong result = 0;
|
|
int stringMouse = 0;
|
|
for (int i = 0; i < BIT_SIZE && stringMouse < bitsString.Length; i++, stringMouse++)
|
|
{
|
|
char chr = bitsString[stringMouse];
|
|
|
|
if (chr == '1')
|
|
{
|
|
result |= (ulong)1 << (BIT_SIZE - i - 1);
|
|
continue;
|
|
}
|
|
|
|
if (chr != '0')
|
|
{
|
|
i--;
|
|
continue;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static uint ToUInt(string bitsString)
|
|
{
|
|
const int BIT_SIZE = 32;
|
|
uint result = 0;
|
|
int stringMouse = 0;
|
|
for (int i = 0; i < BIT_SIZE && stringMouse < bitsString.Length; i++, stringMouse++)
|
|
{
|
|
char chr = bitsString[stringMouse];
|
|
|
|
if (chr == '1')
|
|
{
|
|
result |= (uint)1 << (BIT_SIZE - i - 1);
|
|
continue;
|
|
}
|
|
|
|
if (chr != '0')
|
|
{
|
|
i--;
|
|
continue;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static ushort ToUShort(string bitsString)
|
|
{
|
|
const int BIT_SIZE = 16;
|
|
ushort result = 0;
|
|
int stringMouse = 0;
|
|
for (int i = 0; i < BIT_SIZE && stringMouse < bitsString.Length; i++, stringMouse++)
|
|
{
|
|
char chr = bitsString[stringMouse];
|
|
|
|
if (chr == '1')
|
|
{
|
|
result |= (ushort)(1 << (BIT_SIZE - i - 1));
|
|
continue;
|
|
}
|
|
|
|
if (chr != '0')
|
|
{
|
|
i--;
|
|
continue;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static byte ToByte(string bitsString)
|
|
{
|
|
const int BIT_SIZE = 8;
|
|
byte result = 0;
|
|
int stringMouse = 0;
|
|
for (int i = 0; i < BIT_SIZE && stringMouse < bitsString.Length; i++, stringMouse++)
|
|
{
|
|
char chr = bitsString[stringMouse];
|
|
|
|
if (chr == '1')
|
|
{
|
|
result |= (byte)(1 << (BIT_SIZE - i - 1));
|
|
continue;
|
|
}
|
|
|
|
if (chr != '0')
|
|
{
|
|
i--;
|
|
continue;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static bool ToBool(string bitsString)
|
|
{
|
|
byte result = ToByte(bitsString);
|
|
return *(bool*)&result;
|
|
}
|
|
public static short ToShort(string bitsString) => (short)ToUShort(bitsString);
|
|
public static int ToInt(string bitsString) => (int)ToUInt(bitsString);
|
|
public static long ToLong(string bitsString) => (long)ToULong(bitsString);
|
|
#endregion
|
|
|
|
#region XorShift
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static int NextXorShiftState(int state)
|
|
{
|
|
unchecked { return (state << 13) ^ (state >> 17) ^ (state << 5); };
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static uint NextXorShiftState(uint state)
|
|
{
|
|
unchecked { return (state << 13) ^ (state >> 17) ^ (state << 5); };
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static long NextXorShiftState(long state)
|
|
{
|
|
const long m = 0x2545F491_4F6CDD1D;
|
|
unchecked { return ((state >> 13) ^ (state << 25) ^ (state >> 27)) * m; };
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static ulong NextXorShiftState(ulong state)
|
|
{
|
|
const ulong m = 0x2545F491_4F6CDD1D;
|
|
unchecked { return ((state >> 13) ^ (state << 25) ^ (state >> 27)) * m; };
|
|
}
|
|
#endregion
|
|
|
|
#region Q32/64/s31/s63 To Float/Double
|
|
///<summary>Fast operation: float result = (float)value / int.MaxValue.</summary>
|
|
///<returns>-1.0f < x < 1.0f</returns>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static unsafe float Qs31ToFloat(int value)
|
|
{
|
|
unchecked
|
|
{
|
|
if (value < 0)
|
|
{
|
|
uint bits = (((uint)value ^ uint.MaxValue) >> 8) | 0xBF80_0000;
|
|
return (*(float*)&bits) + 1f;
|
|
}
|
|
else
|
|
{
|
|
uint bits = (((uint)value) >> 8) | 0x3F80_0000;
|
|
return (*(float*)&bits) - 1f;
|
|
}
|
|
}
|
|
}
|
|
///<summary>Fast operation: float result = (float)value / uint.MaxValue.</summary>
|
|
///<returns>0.0f <= x < 1.0f</returns>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static unsafe float Q32ToFloat(uint value)
|
|
{
|
|
unchecked
|
|
{
|
|
uint bits = (value >> 9) | 0x3F80_0000;
|
|
return (*(float*)&bits) - 1f;
|
|
}
|
|
}
|
|
///<summary>Fast operation: double result = (double)value / long.MaxValue.</summary>
|
|
///<returns>-1.0d < x < 1.0d</returns>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static unsafe double Qs63ToDouble(long value)
|
|
{
|
|
unchecked
|
|
{
|
|
if (value < 0)
|
|
{
|
|
ulong bits = (((ulong)value ^ long.MaxValue) >> 11) | 0xBFF0_0000_0000_0000;
|
|
return (*(double*)&bits) + 1d;
|
|
}
|
|
else
|
|
{
|
|
ulong bits = (((ulong)value) >> 11) | 0x3FF0_0000_0000_0000;
|
|
return (*(double*)&bits) - 1d;
|
|
}
|
|
}
|
|
}
|
|
|
|
///<summary>Fast operation: double result = (double)value / ulong.MaxValue.</summary>
|
|
///<returns>0.0d <= x < 1.0d</returns>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static unsafe double Q64ToDouble(ulong value)
|
|
{
|
|
unchecked
|
|
{
|
|
ulong bits = (value >> 12) | 0x3FF0_0000_0000_0000;
|
|
return (*(double*)&bits) - 1d;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Other
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static TEnum AllFlags<TEnum>() where TEnum : unmanaged, Enum
|
|
{
|
|
return EnumCache<TEnum>.allFlags;
|
|
}
|
|
|
|
private static class EnumCache<TEnum> where TEnum : unmanaged, Enum
|
|
{
|
|
public readonly static TEnum empty;
|
|
public readonly static TEnum allFlags;
|
|
public readonly static int valuesCount;
|
|
public readonly static int size;
|
|
|
|
static EnumCache()
|
|
{
|
|
Array values = Enum.GetValues(typeof(TEnum));
|
|
size = sizeof(TEnum);
|
|
|
|
long result = 0;
|
|
valuesCount = values.Length;
|
|
for (int i = 0; i < valuesCount; i++)
|
|
{
|
|
result |= (long)values.GetValue(i);
|
|
}
|
|
ulong emptyBits = 0;
|
|
|
|
allFlags = *(TEnum*)&result;
|
|
empty = *(TEnum*)&emptyBits;
|
|
return;
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
#region FindBitsResult removed
|
|
/*
|
|
public unsafe struct FindBitsResult8 : IEnumerable<byte>
|
|
{
|
|
private fixed byte _numbers[8];
|
|
public readonly byte Count;
|
|
public int this[int index]
|
|
{
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
get => _numbers[index];
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public FindBitsResult8(uint bits)
|
|
{
|
|
unchecked
|
|
{
|
|
Count = (byte)CountBits(bits);
|
|
for (int i = 0; i < Count; i++)
|
|
{
|
|
int number = GetHighBitNumber(bits);
|
|
_numbers[i] = (byte)number;
|
|
bits ^= 1u << number;
|
|
}
|
|
}
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static ReadOnlySpan<byte> CreateSpanInternal(FindBitsResult8 a)
|
|
{
|
|
return new ReadOnlySpan<byte>(a._numbers, a.Count);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public ReadOnlySpan<byte> ToSpan()
|
|
{
|
|
return CreateSpanInternal(this);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static FindBitsResultEnumerator GetEnumeratorInternal(FindBitsResult8 a)
|
|
{
|
|
return new FindBitsResultEnumerator(a._numbers, a.Count);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public FindBitsResultEnumerator GetEnumerator()
|
|
{
|
|
return GetEnumeratorInternal(this);
|
|
}
|
|
IEnumerator<byte> IEnumerable<byte>.GetEnumerator() => GetEnumerator();
|
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
}
|
|
|
|
public unsafe struct FindBitsResult16 : IEnumerable<byte>
|
|
{
|
|
private fixed byte _numbers[16];
|
|
public readonly byte Count;
|
|
public int this[int index]
|
|
{
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
get => _numbers[index];
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public FindBitsResult16(uint bits)
|
|
{
|
|
unchecked
|
|
{
|
|
Count = (byte)CountBits(bits);
|
|
for (int i = 0; i < Count; i++)
|
|
{
|
|
int number = GetHighBitNumber(bits);
|
|
_numbers[i] = (byte)number;
|
|
bits ^= 1u << number;
|
|
}
|
|
}
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static ReadOnlySpan<byte> CreateSpanInternal(FindBitsResult16 a)
|
|
{
|
|
return new ReadOnlySpan<byte>(a._numbers, a.Count);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public ReadOnlySpan<byte> ToSpan()
|
|
{
|
|
return CreateSpanInternal(this);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static FindBitsResultEnumerator GetEnumeratorInternal(FindBitsResult16 a)
|
|
{
|
|
return new FindBitsResultEnumerator(a._numbers, a.Count);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public FindBitsResultEnumerator GetEnumerator()
|
|
{
|
|
return GetEnumeratorInternal(this);
|
|
}
|
|
IEnumerator<byte> IEnumerable<byte>.GetEnumerator() => GetEnumerator();
|
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
}
|
|
|
|
public unsafe struct FindBitsResult32 : IEnumerable<byte>
|
|
{
|
|
public fixed byte _numbers[32];
|
|
public readonly byte Count;
|
|
public int this[int index]
|
|
{
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
get => _numbers[index];
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public FindBitsResult32(uint bits)
|
|
{
|
|
unchecked
|
|
{
|
|
Count = (byte)CountBits(bits);
|
|
for (int i = 0; i < Count; i++)
|
|
{
|
|
int number = GetHighBitNumber(bits);
|
|
_numbers[i] = (byte)number;
|
|
bits ^= 1u << number;
|
|
}
|
|
}
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static ReadOnlySpan<byte> CreateSpanInternal(FindBitsResult32 a)
|
|
{
|
|
return new ReadOnlySpan<byte>(a._numbers, a.Count);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public ReadOnlySpan<byte> ToSpan()
|
|
{
|
|
return CreateSpanInternal(this);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static FindBitsResultEnumerator GetEnumeratorInternal(FindBitsResult32 a)
|
|
{
|
|
return new FindBitsResultEnumerator(a._numbers, a.Count);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public FindBitsResultEnumerator GetEnumerator()
|
|
{
|
|
return GetEnumeratorInternal(this);
|
|
}
|
|
IEnumerator<byte> IEnumerable<byte>.GetEnumerator() => GetEnumerator();
|
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
}
|
|
|
|
public unsafe struct FindBitsResult64 : IEnumerable<byte>
|
|
{
|
|
private fixed byte _numbers[64];
|
|
public readonly byte Count;
|
|
public int this[int index]
|
|
{
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
get => _numbers[index];
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public FindBitsResult64(ulong bits)
|
|
{
|
|
unchecked
|
|
{
|
|
Count = (byte)CountBits(bits);
|
|
for (int i = 0; i < Count; i++)
|
|
{
|
|
int number = GetHighBitNumber(bits);
|
|
_numbers[i] = (byte)number;
|
|
bits ^= 1u << number;
|
|
}
|
|
}
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static ReadOnlySpan<byte> CreateSpanInternal(FindBitsResult64 a)
|
|
{
|
|
return new ReadOnlySpan<byte>(a._numbers, a.Count);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public ReadOnlySpan<byte> ToSpan()
|
|
{
|
|
return CreateSpanInternal(this);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static FindBitsResultEnumerator GetEnumeratorInternal(FindBitsResult64 a)
|
|
{
|
|
return new FindBitsResultEnumerator(a._numbers, a.Count);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public FindBitsResultEnumerator GetEnumerator()
|
|
{
|
|
return GetEnumeratorInternal(this);
|
|
}
|
|
IEnumerator<byte> IEnumerable<byte>.GetEnumerator() => GetEnumerator();
|
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
}
|
|
|
|
public unsafe struct FindBitsResultEnumerator : IEnumerator<byte>
|
|
{
|
|
private byte* _numbers;
|
|
private byte _count;
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public FindBitsResultEnumerator(byte* numbers, byte count)
|
|
{
|
|
_numbers = numbers;
|
|
_count = count;
|
|
}
|
|
public byte Current
|
|
{
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
get
|
|
{
|
|
return *_numbers;
|
|
}
|
|
}
|
|
object IEnumerator.Current => Current;
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public bool MoveNext()
|
|
{
|
|
return _count-- > 0;
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public void Dispose() { }
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public void Reset() { }
|
|
}
|
|
*/
|
|
#endregion
|
|
|
|
#region FindBitsIterator
|
|
public struct FindBitsIterator8 : IEnumerable<int>
|
|
{
|
|
private Enumerator _enumerator;
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public FindBitsIterator8(sbyte bits)
|
|
{
|
|
_enumerator = new Enumerator((byte)bits);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public FindBitsIterator8(byte bits)
|
|
{
|
|
_enumerator = new Enumerator(bits);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public Enumerator GetEnumerator()
|
|
{
|
|
return _enumerator;
|
|
}
|
|
IEnumerator<int> IEnumerable<int>.GetEnumerator() => GetEnumerator();
|
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
public struct Enumerator : IEnumerator<int>
|
|
{
|
|
private uint _bits;
|
|
private int _count;
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public Enumerator(byte bits)
|
|
{
|
|
_count = CountBits(bits);
|
|
_bits = bits;
|
|
}
|
|
public int Current
|
|
{
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
get
|
|
{
|
|
int number = GetHighBitNumber((byte)_bits);
|
|
_bits ^= 1u << number;
|
|
return number;
|
|
}
|
|
}
|
|
object IEnumerator.Current => Current;
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public bool MoveNext()
|
|
{
|
|
return _count-- > 0;
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
void IDisposable.Dispose() { }
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
void IEnumerator.Reset() { }
|
|
}
|
|
}
|
|
|
|
public struct FindBitsIterator16 : IEnumerable<int>
|
|
{
|
|
private Enumerator _enumerator;
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public FindBitsIterator16(short bits)
|
|
{
|
|
_enumerator = new Enumerator((ushort)bits);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public FindBitsIterator16(ushort bits)
|
|
{
|
|
_enumerator = new Enumerator(bits);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public Enumerator GetEnumerator()
|
|
{
|
|
return _enumerator;
|
|
}
|
|
IEnumerator<int> IEnumerable<int>.GetEnumerator() => GetEnumerator();
|
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
public struct Enumerator : IEnumerator<int>
|
|
{
|
|
private uint _bits;
|
|
private int _count;
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public Enumerator(ushort bits)
|
|
{
|
|
_count = CountBits(bits);
|
|
_bits = bits;
|
|
}
|
|
public int Current
|
|
{
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
get
|
|
{
|
|
int number = GetHighBitNumber((ushort)_bits);
|
|
_bits ^= 1u << number;
|
|
return number;
|
|
}
|
|
}
|
|
object IEnumerator.Current => Current;
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public bool MoveNext()
|
|
{
|
|
return _count-- > 0;
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
void IDisposable.Dispose() { }
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
void IEnumerator.Reset() { }
|
|
}
|
|
}
|
|
|
|
public struct FindBitsIterator32 : IEnumerable<int>
|
|
{
|
|
private Enumerator _enumerator;
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public FindBitsIterator32(int bits)
|
|
{
|
|
_enumerator = new Enumerator((uint)bits);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public FindBitsIterator32(uint bits)
|
|
{
|
|
_enumerator = new Enumerator(bits);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public Enumerator GetEnumerator()
|
|
{
|
|
return _enumerator;
|
|
}
|
|
IEnumerator<int> IEnumerable<int>.GetEnumerator() => GetEnumerator();
|
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
public struct Enumerator : IEnumerator<int>
|
|
{
|
|
private uint _bits;
|
|
private int _count;
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public Enumerator(uint bits)
|
|
{
|
|
_count = CountBits(bits);
|
|
_bits = bits;
|
|
}
|
|
public int Current
|
|
{
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
get
|
|
{
|
|
int number = GetHighBitNumber(_bits);
|
|
_bits ^= 1u << number;
|
|
return number;
|
|
}
|
|
}
|
|
object IEnumerator.Current => Current;
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public bool MoveNext()
|
|
{
|
|
return _count-- > 0;
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
void IDisposable.Dispose() { }
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
void IEnumerator.Reset() { }
|
|
}
|
|
}
|
|
|
|
public struct FindBitsIterator64 : IEnumerable<int>
|
|
{
|
|
private Enumerator _enumerator;
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public FindBitsIterator64(long bits)
|
|
{
|
|
_enumerator = new Enumerator((ulong)bits);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public FindBitsIterator64(ulong bits)
|
|
{
|
|
_enumerator = new Enumerator(bits);
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public Enumerator GetEnumerator()
|
|
{
|
|
return _enumerator;
|
|
}
|
|
IEnumerator<int> IEnumerable<int>.GetEnumerator() => GetEnumerator();
|
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
public struct Enumerator : IEnumerator<int>
|
|
{
|
|
private ulong _bits;
|
|
private int _count;
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public Enumerator(ulong bits)
|
|
{
|
|
_count = CountBits(bits);
|
|
_bits = bits;
|
|
}
|
|
public int Current
|
|
{
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
get
|
|
{
|
|
int number = GetHighBitNumber(_bits);
|
|
_bits ^= 1u << number;
|
|
return number;
|
|
}
|
|
}
|
|
object IEnumerator.Current => Current;
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public bool MoveNext()
|
|
{
|
|
return _count-- > 0;
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
void IDisposable.Dispose() { }
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
void IEnumerator.Reset() { }
|
|
}
|
|
}
|
|
#endregion
|
|
} |