update internal

This commit is contained in:
Mikhail 2026-03-16 22:53:20 +08:00
parent b686e4ab5f
commit 8472280d4b
3 changed files with 262 additions and 283 deletions

View File

@ -1,272 +0,0 @@
#if DISABLE_DEBUG
#undef DEBUG
#endif
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
#if ENABLE_IL2CPP
using Unity.IL2CPP.CompilerServices;
#endif
namespace DCFApixels.DragonECS.Core.Internal
{
internal interface IStructComparer<T> : IComparer<T>
{
// a > b = return > 0
// int Compare(T a, T b);
}
#if ENABLE_IL2CPP
[Il2CppSetOption(Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
#endif
internal static class ArraySortHalperX<T>
{
private const int IntrosortSizeThreshold = 16;
#region IStructComparer
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SwapIfGreater<TComparer>(T[] items, ref TComparer comparer, int i, int j) where TComparer : IStructComparer<T>
{
if (comparer.Compare(items[i], items[j]) > 0)
{
T key = items[i];
items[i] = items[j];
items[j] = key;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InsertionSort<TComparer>(T[] items, ref TComparer comparer) where TComparer : IStructComparer<T>
{
for (int i = 0; i < items.Length - 1; i++)
{
T t = items[i + 1];
int j = i;
while (j >= 0 && comparer.Compare(t, items[j]) < 0)
{
items[j + 1] = items[j];
j--;
}
items[j + 1] = t;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Sort<TComparer>(T[] items, ref TComparer comparer) where TComparer : IStructComparer<T>
{
int length = items.Length;
if (length == 1)
{
return;
}
if (length <= IntrosortSizeThreshold)
{
if (length == 2)
{
SwapIfGreater(items, ref comparer, 0, 1);
return;
}
if (length == 3)
{
SwapIfGreater(items, ref comparer, 0, 1);
SwapIfGreater(items, ref comparer, 0, 2);
SwapIfGreater(items, ref comparer, 1, 2);
return;
}
InsertionSort(items, ref comparer);
return;
}
IStructComparer<T> packed = comparer;
Array.Sort(items, 0, items.Length, packed);
comparer = (TComparer)packed;
}
#endregion
#region Comparison
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SwapIfGreater(T[] items, Comparison<T> comparison, int i, int j)
{
if (comparison(items[i], items[j]) > 0)
{
T key = items[i];
items[i] = items[j];
items[j] = key;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InsertionSort(T[] items, int length, Comparison<T> comparison)
{
for (int i = 0; i < length - 1; i++)
{
T t = items[i + 1];
int j = i;
while (j >= 0 && comparison(t, items[j]) < 0)
{
items[j + 1] = items[j];
j--;
}
items[j + 1] = t;
}
}
#if ENABLE_IL2CPP
[Il2CppSetOption(Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
#endif
private class ComparisonHach : IComparer<T>
{
public static readonly ComparisonHach Instance = new ComparisonHach();
public Comparison<T> comparison;
private ComparisonHach() { }
public int Compare(T x, T y) { return comparison(x, y); }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Sort(T[] items, Comparison<T> comparison)
{
Sort(items, comparison, items.Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Sort(T[] items, Comparison<T> comparison, int length)
{
if (length <= IntrosortSizeThreshold)
{
if (length == 1)
{
return;
}
if (length == 2)
{
SwapIfGreater(items, comparison, 0, 1);
return;
}
if (length == 3)
{
SwapIfGreater(items, comparison, 0, 1);
SwapIfGreater(items, comparison, 0, 2);
SwapIfGreater(items, comparison, 1, 2);
return;
}
InsertionSort(items, length, comparison);
return;
}
ComparisonHach.Instance.comparison = comparison;
Array.Sort(items, 0, length, ComparisonHach.Instance);
}
#endregion
}
#if ENABLE_IL2CPP
[Il2CppSetOption(Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
#endif
internal static unsafe class UnsafeArraySortHalperX<T> where T : unmanaged
{
private const int IntrosortSizeThreshold = 16;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SwapIfGreater<TComparer>(T* items, ref TComparer comparer, int i, int j) where TComparer : IStructComparer<T>
{
if (comparer.Compare(items[i], items[j]) > 0)
{
T key = items[i];
items[i] = items[j];
items[j] = key;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InsertionSort_Unchecked<TComparer>(T* items, int length, ref TComparer comparer) where TComparer : IStructComparer<T>
{
for (int i = 0; i < length - 1; i++)
{
T t = items[i + 1];
int j = i;
while (j >= 0 && comparer.Compare(t, items[j]) < 0)
{
items[j + 1] = items[j];
j--;
}
items[j + 1] = t;
}
}
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
//public static void OptimizedBubbleSort_Unchecked<TComparer>(T* items, int length, ref TComparer comparer) where TComparer : IComparerX<T>
//{
// for (int i = 0, n = length - 1; i < n; i++)
// {
// bool noSwaped = true;
// for (int j = 0; j < n - i;)
// {
// ref T j0 = ref items[j++];
// if(comparer.Compare(j0, items[j]) < 0)
// {
// T tmp = items[j];
// items[j] = j0;
// j0 = tmp;
// noSwaped = false;
// }
// }
// if (noSwaped)
// break;
// }
//}
public static void InsertionSort<TComparer>(T* items, int length, ref TComparer comparer) where TComparer : IStructComparer<T>
{
if (length == 1)
{
return;
}
if (length == 2)
{
SwapIfGreater(items, ref comparer, 0, 1);
return;
}
if (length == 3)
{
SwapIfGreater(items, ref comparer, 0, 1);
SwapIfGreater(items, ref comparer, 0, 2);
SwapIfGreater(items, ref comparer, 1, 2);
return;
}
InsertionSort_Unchecked(items, length, ref comparer);
}
//public static void OptimizedBubbleSort<TComparer>(T* items, int length, ref TComparer comparer) where TComparer : IComparerX<T>
//{
// if (length == 1)
// {
// return;
// }
//
// if (length == 2)
// {
// SwapIfGreater(items, ref comparer, 0, 1);
// return;
// }
//
// if (length == 3)
// {
// SwapIfGreater(items, ref comparer, 0, 1);
// SwapIfGreater(items, ref comparer, 0, 2);
// SwapIfGreater(items, ref comparer, 1, 2);
// return;
// }
//
// OptimizedBubbleSort_Unchecked(items, length, ref comparer);
//}
}
}

View File

@ -0,0 +1,246 @@
#if DISABLE_DEBUG
#undef DEBUG
#endif
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Numerics;
using System.Runtime.CompilerServices;
#if ENABLE_IL2CPP
using Unity.IL2CPP.CompilerServices;
#endif
namespace DCFApixels.DragonECS.Core.Internal
{
// a > b = return > 0
// int Compare(T a, T b);
//IComparer<T> comparer
//if (comparer == null)
//{
// comparer = Comparer<T>.Default;
//}
#if ENABLE_IL2CPP
[Il2CppSetOption(Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
#endif
internal static class ArraySortUtility<T, TComparer>
where TComparer : struct, IComparer<T>
{
private const int IntrosortSizeThreshold = 16;
#region Public
public static void Sort(Span<T> keys, ref TComparer comparer)
{
// Add a try block here to detect IComparers (or their
// underlying IComparables, etc) that are bogus.
IntrospectiveSort(keys, ref comparer);
}
public static int BinarySearch(T[] array, int index, int length, T value, ref TComparer comparer)
{
return InternalBinarySearch(array, index, length, value, ref comparer);
}
#endregion
#region Internal
internal static int InternalBinarySearch(T[] array, int index, int length, T value, ref TComparer comparer)
{
Debug.Assert(array != null, "Check the arguments in the caller!");
Debug.Assert(index >= 0 && length >= 0 && (array.Length - index >= length), "Check the arguments in the caller!");
int lo = index;
int hi = index + length - 1;
while (lo <= hi)
{
int i = lo + ((hi - lo) >> 1);
int order = comparer.Compare(array[i], value);
if (order == 0) return i;
if (order < 0)
{
lo = i + 1;
}
else
{
hi = i - 1;
}
}
return ~lo;
}
private static void SwapIfGreater(Span<T> keys, ref TComparer comparer, int i, int j)
{
Debug.Assert(i != j);
if (comparer.Compare(keys[i], keys[j]) > 0)
{
T key = keys[i];
keys[i] = keys[j];
keys[j] = key;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void Swap(Span<T> a, int i, int j)
{
Debug.Assert(i != j);
T t = a[i];
a[i] = a[j];
a[j] = t;
}
internal static void IntrospectiveSort(Span<T> keys, ref TComparer comparer)
{
//Debug.Assert(comparer != null);
if (keys.Length > 1)
{
IntroSort(keys, 2 * (BitOperations.Log2((uint)keys.Length) + 1), ref comparer);
}
}
// IntroSort is recursive; block it from being inlined into itself as
// this is currenly not profitable.
[MethodImpl(MethodImplOptions.NoInlining)]
private static void IntroSort(Span<T> keys, int depthLimit, ref TComparer comparer)
{
Debug.Assert(!keys.IsEmpty);
Debug.Assert(depthLimit >= 0);
//Debug.Assert(comparer != null);
int partitionSize = keys.Length;
while (partitionSize > 1)
{
if (partitionSize <= IntrosortSizeThreshold)
{
if (partitionSize == 2)
{
SwapIfGreater(keys, ref comparer, 0, 1);
return;
}
if (partitionSize == 3)
{
SwapIfGreater(keys, ref comparer, 0, 1);
SwapIfGreater(keys, ref comparer, 0, 2);
SwapIfGreater(keys, ref comparer, 1, 2);
return;
}
InsertionSort(keys.Slice(0, partitionSize), ref comparer);
return;
}
if (depthLimit == 0)
{
HeapSort(keys.Slice(0, partitionSize), ref comparer);
return;
}
depthLimit--;
int p = PickPivotAndPartition(keys.Slice(0, partitionSize), ref comparer);
// Note we've already partitioned around the pivot and do not have to move the pivot again.
IntroSort(keys.Slice(p + 1, partitionSize - (p + 1)), depthLimit, ref comparer);
partitionSize = p;
}
}
private static int PickPivotAndPartition(Span<T> keys, ref TComparer comparer)
{
Debug.Assert(keys.Length >= IntrosortSizeThreshold);
//Debug.Assert(comparer != null);
int hi = keys.Length - 1;
// Compute median-of-three. But also partition them, since we've done the comparison.
int middle = hi >> 1;
// Sort lo, mid and hi appropriately, then pick mid as the pivot.
SwapIfGreater(keys, ref comparer, 0, middle); // swap the low with the mid point
SwapIfGreater(keys, ref comparer, 0, hi); // swap the low with the high
SwapIfGreater(keys, ref comparer, middle, hi); // swap the middle with the high
T pivot = keys[middle];
Swap(keys, middle, hi - 1);
int left = 0, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
while (left < right)
{
while (comparer.Compare(keys[++left], pivot) < 0) ;
while (comparer.Compare(pivot, keys[--right]) < 0) ;
if (left >= right)
break;
Swap(keys, left, right);
}
// Put pivot in the right location.
if (left != hi - 1)
{
Swap(keys, left, hi - 1);
}
return left;
}
private static void HeapSort(Span<T> keys, ref TComparer comparer)
{
//Debug.Assert(comparer != null);
Debug.Assert(!keys.IsEmpty);
int n = keys.Length;
for (int i = n >> 1; i >= 1; i--)
{
DownHeap(keys, i, n, ref comparer);
}
for (int i = n; i > 1; i--)
{
Swap(keys, 0, i - 1);
DownHeap(keys, 1, i - 1, ref comparer);
}
}
private static void DownHeap(Span<T> keys, int i, int n, ref TComparer comparer)
{
//Debug.Assert(comparer != null);
T d = keys[i - 1];
while (i <= n >> 1)
{
int child = 2 * i;
if (child < n && comparer.Compare(keys[child - 1], keys[child]) < 0)
{
child++;
}
if (!(comparer.Compare(d, keys[child - 1]) < 0))
break;
keys[i - 1] = keys[child - 1];
i = child;
}
keys[i - 1] = d;
}
private static void InsertionSort(Span<T> keys, ref TComparer comparer)
{
for (int i = 0; i < keys.Length - 1; i++)
{
T t = keys[i + 1];
int j = i;
while (j >= 0 && comparer.Compare(t, keys[j]) < 0)
{
keys[j + 1] = keys[j];
j--;
}
keys[j + 1] = t;
}
}
#endregion
}
}

View File

@ -284,11 +284,17 @@ namespace DCFApixels.DragonECS.Core.Internal
internal static class SpanUtility
{
internal static StructComparison<T> ToStruct<T>(this Comparison<T> self)
{
return new StructComparison<T>(self);
}
public static void Sort<T>(Span<T> span, Comparison<T> comparison)
{
span.Sort(new StructComparison<T>(comparison));
var c = comparison.ToStruct();
ArraySortUtility<T, StructComparison<T>>.Sort(span, ref c);
}
private readonly struct StructComparison<T> : IComparer<T>
}
internal readonly struct StructComparison<T> : IComparer<T>
{
public readonly Comparison<T> Comparison;
public StructComparison(Comparison<T> comparison)
@ -300,5 +306,4 @@ namespace DCFApixels.DragonECS.Core.Internal
return Comparison(x, y);
}
}
}
}