diff --git a/src/EcsGraphExtensions.cs b/src/EntityGraphExtensions.cs similarity index 98% rename from src/EcsGraphExtensions.cs rename to src/EntityGraphExtensions.cs index 3ea2e6a..31dbc33 100644 --- a/src/EcsGraphExtensions.cs +++ b/src/EntityGraphExtensions.cs @@ -3,7 +3,7 @@ using System; namespace DCFApixels.DragonECS { - public static class EcsGraphExtensions + public static class EntityGraphExtensions { private static EntityGraph[] _worldGraphs = new EntityGraph[4]; diff --git a/src/EcsGraphExtensions.cs.meta b/src/EntityGraphExtensions.meta similarity index 100% rename from src/EcsGraphExtensions.cs.meta rename to src/EntityGraphExtensions.meta diff --git a/src/Executors/EcsJoinToSubGraphExecutor.cs b/src/Executors/EcsJoinToSubGraphExecutor.cs index 1dc9789..407bb65 100644 --- a/src/Executors/EcsJoinToSubGraphExecutor.cs +++ b/src/Executors/EcsJoinToSubGraphExecutor.cs @@ -27,12 +27,15 @@ namespace DCFApixels.DragonECS private LinkedList _linkedList; private LinkedListHead[] _linkedListSourceHeads; - private int[] _startEntities; - private int _startEntitiesCount; + private int[] _sourceEntities; + private int _sourceEntitiesCount; private int _targetWorldCapacity = -1; private EcsProfilerMarker _executeMarker = new EcsProfilerMarker("Join"); + public bool _isDestroyed = false; + + #region Properties public sealed override long Version { @@ -62,13 +65,17 @@ namespace DCFApixels.DragonECS _versionsChecker = new WorldStateVersionsChecker(Mask); _linkedList = new OnlyAppendHeadLinkedList(World.Capacity); _linkedListSourceHeads = new LinkedListHead[World.Capacity]; + _sourceEntities = new int[World.Capacity * 2]; World.AddListener(this); _graph = World.GetGraph(); _iterator = Mask.GetIterator(); } protected override void OnDestroy() { + if (_isDestroyed) { return; } + _isDestroyed = true; World.RemoveListener(this); + _versionsChecker.Dispose(); } #endregion @@ -79,24 +86,16 @@ namespace DCFApixels.DragonECS World.ReleaseDelEntityBufferAllAuto(); - if (Mask.IsEmpty) + if (Mask.IsEmpty || _versionsChecker.CheckAndNext() == false) { - _filteredAllEntitiesCount = World.Entities.ToArray(ref _filteredAllEntities); - } - else - { - if (_versionsChecker.CheckAndNext() == false) + _filteredAllEntitiesCount = _iterator.IterateTo(World.Entities, ref _filteredAllEntities); + //Подготовка массивов + if (_sourceEntities.Length < _filteredAllEntitiesCount * 2) { - _filteredAllEntitiesCount = _iterator.IterateTo(World.Entities, ref _filteredAllEntities); - ////Подготовка массивов - //if (_startEntities.Length < _filteredAllEntitiesCount * 2) - //{ - // _startEntities = new int[_filteredAllEntitiesCount * 2]; - //} + _sourceEntities = new int[_filteredAllEntitiesCount * 2]; } } - //установка текущего массива _currentFilteredEntities = _filteredAllEntities; _currentFilteredEntitiesCount = _filteredAllEntitiesCount; @@ -106,13 +105,17 @@ namespace DCFApixels.DragonECS { _targetWorldCapacity = World.Capacity; _linkedListSourceHeads = new LinkedListHead[_targetWorldCapacity]; - _startEntities = new int[_targetWorldCapacity]; + //_startEntities = new int[_targetWorldCapacity]; } else { - ArrayUtility.Fill(_linkedListSourceHeads, default); //TODO оптимизировать, сделав не полную отчистку а только по элементов с прошлого раза + //ArrayUtility.Fill(_linkedListSourceHeads, default); //TODO оптимизировать, сделав не полную отчистку а только по элементов с прошлого раза + for (int i = 0; i < _sourceEntitiesCount; i++) + { + _linkedListSourceHeads[_sourceEntities[i]] = default; + } } - _startEntitiesCount = 0; + _sourceEntitiesCount = 0; _linkedList.Clear(); //Заполнение массивов @@ -249,7 +252,7 @@ namespace DCFApixels.DragonECS ref var basket = ref _linkedListSourceHeads[sourceEntityID]; if (basket.head == 0) { - _startEntities[_startEntitiesCount++] = sourceEntityID; + _sourceEntities[_sourceEntitiesCount++] = sourceEntityID; basket.head = _linkedList.NewHead(relationEntityID); } else @@ -309,7 +312,7 @@ namespace DCFApixels.DragonECS #region GetEntites internal EcsSpan GetSourceEntities() { - return UncheckedCoreUtility.CreateSpan(WorldID, _startEntities, _startEntitiesCount); + return UncheckedCoreUtility.CreateSpan(WorldID, _sourceEntities, _sourceEntitiesCount); } internal EcsSpan GetRelEntities() { diff --git a/src/Internal/ArrayUtility.cs b/src/Internal/ArrayUtility.cs index cf3771c..40ae2eb 100644 --- a/src/Internal/ArrayUtility.cs +++ b/src/Internal/ArrayUtility.cs @@ -1,7 +1,4 @@ using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -46,64 +43,18 @@ namespace DCFApixels.DragonECS.Graphs.Internal { return 1 << (GetHighBitNumber((uint)minSize - 1u) + 1); } - public static void Fill(T[] array, T value, int startIndex = 0, int length = -1) - { - if (length < 0) - { - length = array.Length; - } - else - { - length = startIndex + length; - } - for (int i = startIndex; i < length; i++) - { - array[i] = value; - } - } - } - internal readonly struct EnumerableInt : IEnumerable - { - public readonly int start; - public readonly int length; - private EnumerableInt(int start, int length) - { - this.start = start; - this.length = length; - } - public static EnumerableInt Range(int start, int length) => new EnumerableInt(start, length); - public static EnumerableInt StartEnd(int start, int end) => new EnumerableInt(start, end - start); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Enumerator GetEnumerator() => new Enumerator(start, start + length); - public struct Enumerator : IEnumerator - { - private readonly int _max; - private int _current; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Enumerator(int max, int current) - { - _max = max; - _current = current - 1; - } - public int Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _current; - } - object IEnumerator.Current => Current; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() => ++_current < _max; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Reset() { } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Dispose() { } - } } internal static unsafe class UnmanagedArrayUtility { + private static class MetaCache + { + public readonly static int Size; + static MetaCache() + { + T def = default; + Size = Marshal.SizeOf(def); + } + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T* New(int capacity) where T : unmanaged { @@ -112,28 +63,32 @@ namespace DCFApixels.DragonECS.Graphs.Internal [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void New(out T* ptr, int capacity) where T : unmanaged { - ptr = (T*)Marshal.AllocHGlobal(Marshal.SizeOf(default) * capacity).ToPointer(); + ptr = (T*)Marshal.AllocHGlobal(Marshal.SizeOf() * capacity).ToPointer(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T* NewAndInit(int capacity) where T : unmanaged { - int newSize = Marshal.SizeOf(typeof(T)) * capacity; + int newSize = MetaCache.Size * capacity; byte* newPointer = (byte*)Marshal.AllocHGlobal(newSize).ToPointer(); for (int i = 0; i < newSize; i++) + { *(newPointer + i) = 0; + } return (T*)newPointer; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void NewAndInit(out T* ptr, int capacity) where T : unmanaged { - int newSize = Marshal.SizeOf(typeof(T)) * capacity; + int newSize = MetaCache.Size * capacity; byte* newPointer = (byte*)Marshal.AllocHGlobal(newSize).ToPointer(); for (int i = 0; i < newSize; i++) + { *(newPointer + i) = 0; + } ptr = (T*)newPointer; } @@ -167,12 +122,12 @@ namespace DCFApixels.DragonECS.Graphs.Internal { return (T*)Marshal.ReAllocHGlobal( new IntPtr(oldPointer), - new IntPtr(Marshal.SizeOf(default) * newCount)).ToPointer(); + new IntPtr(MetaCache.Size * newCount)).ToPointer(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T* ResizeAndInit(void* oldPointer, int oldSize, int newSize) where T : unmanaged { - int sizeT = Marshal.SizeOf(default); + int sizeT = MetaCache.Size; T* result = (T*)Marshal.ReAllocHGlobal( new IntPtr(oldPointer), new IntPtr(sizeT * newSize)).ToPointer(); @@ -189,16 +144,4 @@ namespace DCFApixels.DragonECS.Graphs.Internal } } } - - public static class CollectionUtility - { - public static string EntitiesToString(IEnumerable range, string name) - { - return $"{name}({range.Count()}) {{{string.Join(", ", range.OrderBy(o => o))}}})"; - } - public static string AutoToString(IEnumerable range, string name) - { - return $"{name}({range.Count()}) {{{string.Join(", ", range.Select(o => o.ToString()))}}})"; - } - } } \ No newline at end of file diff --git a/src/Internal/BitsUtility.cs b/src/Internal/BitsUtility.cs deleted file mode 100644 index 29dcf08..0000000 --- a/src/Internal/BitsUtility.cs +++ /dev/null @@ -1,1063 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Text.RegularExpressions; -using static DCFApixels.DragonECS.Graphs.Internal.BitsUtility; - -namespace DCFApixels.DragonECS.Graphs.Internal -{ - internal unsafe static class BitsUtility - { - private const char DEFAULT_SEPARATOR = '_'; - private const int BYTE_BITS = 8; - - #region CountBits - public static unsafe int CountBits8(T bits) where T : unmanaged - { - return CountBits((uint)*(byte*)&bits); - } - public static unsafe int CountBits16(T bits) where T : unmanaged - { - return CountBits((uint)*(ushort*)&bits); - } - - public static unsafe int CountBits32(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 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 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 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 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 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 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 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 bits, List numbers) where T : unmanaged - { - GetBitNumbersNoAlloc(*(uint*)&bits, numbers); - } - public static unsafe void GetBitNumbersNoAlloc(float bits, List numbers) - { - GetBitNumbersNoAlloc(*(uint*)&bits, numbers); - } - public static void GetBitNumbersNoAlloc(int bits, List numbers) - { - GetBitNumbersNoAlloc((uint)bits, numbers); - } - public static void GetBitNumbersNoAlloc(uint bits, List 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 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 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 bits, List numbers) where T : unmanaged - { - GetBitNumbersNoAlloc(*(ulong*)&bits, numbers); - } - public static unsafe void GetBitNumbersNoAlloc(double bits, List numbers) - { - GetBitNumbersNoAlloc(*(ulong*)&bits, numbers); - } - public static void GetBitNumbersNoAlloc(long bits, List numbers) - { - GetBitNumbersNoAlloc((ulong)bits, numbers); - } - public static void GetBitNumbersNoAlloc(ulong bits, List 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 value, bool withSeparator) where T : unmanaged - { - return ToBitsStringInaternal(value, withSeparator ? BYTE_BITS : 0, DEFAULT_SEPARATOR); - } - public static string ToBitsString(T value, int separateRange) where T : unmanaged - { - return ToBitsStringInaternal(value, separateRange, DEFAULT_SEPARATOR); - } - public static string ToBitsString(T value, char separator = DEFAULT_SEPARATOR, int separateRange = BYTE_BITS) where T : unmanaged - { - return ToBitsStringInaternal(value, separateRange, separator); - } - private static unsafe string ToBitsStringInaternal(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 (int)NextXorShiftState((uint)state); - } - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint NextXorShiftState(uint state) - { - unchecked - { - state ^= state << 13; - state ^= state >> 17; - state ^= state << 5; - return state; - }; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long NextXorShiftState(long state) - { - unchecked - { - return (long)NextXorShiftState((ulong)state); - } - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ulong NextXorShiftState(ulong state) - { - unchecked - { - const ulong m = 0x2545F491_4F6CDD1D; - state ^= state >> 13; - state ^= state << 25; - state ^= state >> 27; - state *= m; - return state; - } - } - #endregion - - #region Q32/64/s31/s63 To Float/Double - ///Fast operation: float result = (float)value / int.MaxValue. - ///-1.0f < x < 1.0f - [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; - } - } - } - ///Fast operation: float result = (float)value / uint.MaxValue. - ///0.0f <= x < 1.0f - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe float Q32ToFloat(uint value) - { - unchecked - { - uint bits = (value >> 9) | 0x3F80_0000; - return (*(float*)&bits) - 1f; - } - } - ///Fast operation: double result = (double)value / long.MaxValue. - ///-1.0d < x < 1.0d - [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; - } - } - } - - ///Fast operation: double result = (double)value / ulong.MaxValue. - ///0.0d <= x < 1.0d - [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 FindBitsResult removed - /* - public unsafe struct FindBitsResult8 : IEnumerable - { - 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 CreateSpanInternal(FindBitsResult8 a) - { - return new ReadOnlySpan(a._numbers, a.Count); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlySpan 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 IEnumerable.GetEnumerator() => GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - public unsafe struct FindBitsResult16 : IEnumerable - { - 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 CreateSpanInternal(FindBitsResult16 a) - { - return new ReadOnlySpan(a._numbers, a.Count); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlySpan 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 IEnumerable.GetEnumerator() => GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - public unsafe struct FindBitsResult32 : IEnumerable - { - 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 CreateSpanInternal(FindBitsResult32 a) - { - return new ReadOnlySpan(a._numbers, a.Count); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlySpan 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 IEnumerable.GetEnumerator() => GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - public unsafe struct FindBitsResult64 : IEnumerable - { - 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 CreateSpanInternal(FindBitsResult64 a) - { - return new ReadOnlySpan(a._numbers, a.Count); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlySpan 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 IEnumerable.GetEnumerator() => GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - public unsafe struct FindBitsResultEnumerator : IEnumerator - { - 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 - { - 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 IEnumerable.GetEnumerator() => GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - public struct Enumerator : IEnumerator - { - 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 - { - 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 IEnumerable.GetEnumerator() => GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - public struct Enumerator : IEnumerator - { - 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 - { - 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 IEnumerable.GetEnumerator() => GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - public struct Enumerator : IEnumerator - { - 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 - { - 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 IEnumerable.GetEnumerator() => GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - public struct Enumerator : IEnumerator - { - 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 -} \ No newline at end of file diff --git a/src/Internal/BitsUtility.cs.meta b/src/Internal/BitsUtility.cs.meta deleted file mode 100644 index 0fc14f3..0000000 --- a/src/Internal/BitsUtility.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 20978cdfe73c32d49952cb225e32a5b8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/src/Internal/RelationInfo.cs b/src/Internal/RelationInfo.cs index 05d5160..4d3a9f9 100644 --- a/src/Internal/RelationInfo.cs +++ b/src/Internal/RelationInfo.cs @@ -55,7 +55,17 @@ namespace DCFApixels.DragonECS.Graphs.Internal [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(RelationInfo other) { return this == other; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override int GetHashCode() { return start ^ BitsUtility.NextXorShiftState(end); } + public override int GetHashCode() + { + unchecked + { + uint endHash = (uint)end; + endHash ^= endHash << 13; + endHash ^= endHash >> 17; + endHash ^= endHash << 5; + return start ^ (int)endHash; + } + } public override string ToString() { return $"arc({start} -> {end})"; } #endregion } diff --git a/src/Internal/SparseArray.cs b/src/Internal/SparseArray.cs deleted file mode 100644 index b50bd74..0000000 --- a/src/Internal/SparseArray.cs +++ /dev/null @@ -1,217 +0,0 @@ -//SparseArray. Analogous to Dictionary, but faster. -//Benchmark result of indexer.get speed test with 300 elements: -//[Dictinary: 5.786us] [SparseArray: 2.047us]. -using System; -using System.Diagnostics.Contracts; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace DCFApixels.DragonECS.Graphs.Internal -{ - internal class SparseArray - { - public const int MIN_CAPACITY_BITS_OFFSET = 4; - public const int MIN_CAPACITY = 1 << MIN_CAPACITY_BITS_OFFSET; - private const int EMPTY = -1; - - private int[] _buckets = Array.Empty(); - private Entry[] _entries = Array.Empty(); - - private int _count; - - private int _freeList; - private int _freeCount; - - private int _modBitMask; - - #region Properties - public TValue this[int keyX, int keyY] - { - get => _entries[FindEntry((keyX << 32) | keyY)].value; - set => Insert(keyX + (keyY << 32), value); - } - public TValue this[int key] - { - get => _entries[FindEntry(key)].value; - set => Insert(key, value); - } - public int Count => _count; - #endregion - - #region Constructors - public SparseArray(int minCapacity = MIN_CAPACITY) - { - minCapacity = NormalizeCapacity(minCapacity); - _buckets = new int[minCapacity]; - for (int i = 0; i < minCapacity; i++) - _buckets[i] = EMPTY; - _entries = new Entry[minCapacity]; - _modBitMask = (minCapacity - 1) & 0x7FFFFFFF; - } - #endregion - - #region Add/Contains/Remove - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Add(int keyX, int keyY, TValue value) => Add((keyX << 32) | keyY, value); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Add(int key, TValue value) - { -#if DEBUG - if (Contains(key)) - throw new ArgumentException("Contains(hashKey) is true"); -#endif - Insert(key, value); - } - - public bool Contains(int keyX, int keyY) => FindEntry((keyX << 32) | keyY) >= 0; - public bool Contains(int key) => FindEntry(key) >= 0; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Remove(int keyX, int keyY) => Remove((keyX << 32) | keyY); - public bool Remove(int key) - { - int bucket = key & _modBitMask; - int last = -1; - for (int i = _buckets[bucket]; i >= 0; last = i, i = _entries[i].next) - { - if (_entries[i].hashKey == key) - { - if (last < 0) - { - _buckets[bucket] = _entries[i].next; - } - else - { - _entries[last].next = _entries[i].next; - } - _entries[i].next = _freeList; - _entries[i].hashKey = -1; - _entries[i].value = default; - _freeList = i; - _freeCount++; - return true; - } - } - return false; - } - #endregion - - #region Find/Insert - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private int FindEntry(int key) - { - for (int i = _buckets[key & _modBitMask]; i >= 0; i = _entries[i].next) - if (_entries[i].hashKey == key) return i; - return -1; - } - private void Insert(int key, TValue value) - { - int targetBucket = key & _modBitMask; - - for (int i = _buckets[targetBucket]; i >= 0; i = _entries[i].next) - { - if (_entries[i].hashKey == key) - { - _entries[i].value = value; - return; - } - } - - int index; - if (_freeCount > 0) - { - index = _freeList; - _freeList = _entries[index].next; - _freeCount--; - } - else - { - if (_count == _entries.Length) - { - Resize(); - targetBucket = key & _modBitMask; - } - index = _count++; - } - - _entries[index].next = _buckets[targetBucket]; - _entries[index].hashKey = key; - _entries[index].value = value; - _buckets[targetBucket] = index; - } - #endregion - - #region TryGetValue - public bool TryGetValue(int key, out TValue value) - { - int index = FindEntry(key); - if (index < 0) - { - value = default; - return false; - } - value = _entries[index].value; - return true; - } - #endregion - - #region Clear - public void Clear() - { - if (_count > 0) - { - for (int i = 0; i < _buckets.Length; i++) - { - _buckets[i] = -1; - } - Array.Clear(_entries, 0, _count); - _count = 0; - } - } - #endregion - - #region Resize - private void Resize() - { - int newSize = _buckets.Length << 1; - _modBitMask = (newSize - 1) & 0x7FFFFFFF; - - Contract.Assert(newSize >= _entries.Length); - int[] newBuckets = new int[newSize]; - for (int i = 0; i < newBuckets.Length; i++) - newBuckets[i] = EMPTY; - - Entry[] newEntries = new Entry[newSize]; - Array.Copy(_entries, 0, newEntries, 0, _count); - for (int i = 0; i < _count; i++) - { - if (newEntries[i].hashKey >= 0) - { - int bucket = newEntries[i].hashKey % newSize; - newEntries[i].next = newBuckets[bucket]; - newBuckets[bucket] = i; - } - } - _buckets = newBuckets; - _entries = newEntries; - } - - private int NormalizeCapacity(int capacity) - { - int result = MIN_CAPACITY; - while (result < capacity) result <<= 1; - return result; - } - #endregion - - #region Utils - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct Entry - { - public int next; // Index of next entry, -1 if last - public int hashKey; - public TValue value; - } - #endregion - } -} \ No newline at end of file diff --git a/src/Internal/SparseArray.cs.meta b/src/Internal/SparseArray.cs.meta deleted file mode 100644 index d8ea5e1..0000000 --- a/src/Internal/SparseArray.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c3dd2571d8641a142a77b4dc93c8a33b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: