Sin descripción
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

NoAllocUtils.cs 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. using System;
  2. // Utilities that do not allocate.
  3. namespace UnityEngine.Rendering.Universal
  4. {
  5. // Non-allocating sorts.
  6. // NOTE: Do NOT make this public. It's likely that these will be merged/moved to core or replaced by something else.
  7. internal struct Sorting
  8. {
  9. // Add profling samplers to sorts as they often are a bottleneck when scaling things up.
  10. // By default avoid sampling recursion, but these can be used externally as well.
  11. static public ProfilingSampler s_QuickSortSampler = new ProfilingSampler("QuickSort");
  12. static public ProfilingSampler s_InsertionSortSampler = new ProfilingSampler("InsertionSort");
  13. public static void QuickSort<T>(T[] data, Func<T, T, int> compare)
  14. {
  15. using var scope = new ProfilingScope(s_QuickSortSampler);
  16. QuickSort<T>(data, 0, data.Length - 1, compare);
  17. }
  18. // <summary>
  19. // A non-allocating predicated sub-array quick sort for managed arrays.
  20. //
  21. // Example: Sorting.QuickSort(test, 0, test.Length - 1, (int a, int b) => a - b);
  22. // </summary>
  23. // <param name="data"></param>
  24. // <param name="start"></param>
  25. // <param name="end"> Then end param is inclusive! </param>
  26. // <param name="compare"> Should return int -1, 0 or 1 </param>
  27. //
  28. // NOTE: Similar to UnityEngine.Rendering.CoreUnsafeUtils.QuickSort in CoreUnsafeUtils.cs,
  29. // we should see if these could be merged in the future.
  30. //
  31. // TODO: parallel alternative
  32. public static void QuickSort<T>(T[] data, int start, int end, Func<T, T, int> compare)
  33. {
  34. int diff = end - start;
  35. if (diff < 1)
  36. return;
  37. if (diff < 8)
  38. {
  39. InsertionSort(data, start, end, compare);
  40. return;
  41. }
  42. Assertions.Assert.IsTrue((uint)start < data.Length);
  43. Assertions.Assert.IsTrue((uint)end < data.Length); // end == inclusive
  44. if (start < end)
  45. {
  46. int pivot = Partition<T>(data, start, end, compare);
  47. if (pivot >= 1)
  48. QuickSort<T>(data, start, pivot, compare);
  49. if (pivot + 1 < end)
  50. QuickSort<T>(data, pivot + 1, end, compare);
  51. }
  52. }
  53. static T Median3Pivot<T>(T[] data, int start, int pivot, int end, Func<T, T, int> compare)
  54. {
  55. void Swap(int a, int b)
  56. {
  57. var tmp = data[a];
  58. data[a] = data[b];
  59. data[b] = tmp;
  60. }
  61. if (compare(data[end], data[start]) < 0) Swap(start, end);
  62. if (compare(data[pivot], data[start]) < 0) Swap(start, pivot);
  63. if (compare(data[end], data[pivot]) < 0) Swap(pivot, end);
  64. return data[pivot];
  65. }
  66. static int Partition<T>(T[] data, int start, int end, Func<T, T, int> compare)
  67. {
  68. int diff = end - start;
  69. int pivot = start + diff / 2;
  70. var pivotValue = Median3Pivot(data, start, pivot, end, compare);
  71. while (true)
  72. {
  73. while (compare(data[start], pivotValue) < 0) ++start;
  74. while (compare(data[end], pivotValue) > 0) --end;
  75. if (start >= end)
  76. {
  77. return end;
  78. }
  79. var tmp = data[start];
  80. data[start++] = data[end];
  81. data[end--] = tmp;
  82. }
  83. }
  84. static public void InsertionSort<T>(T[] data, Func<T, T, int> compare)
  85. {
  86. using var scope = new ProfilingScope(s_InsertionSortSampler);
  87. InsertionSort<T>(data, 0, data.Length - 1, compare);
  88. }
  89. // A non-allocating predicated sub-array insertion sort for managed arrays.
  90. //
  91. // NOTE: called also from QuickSort for small ranges.
  92. static public void InsertionSort<T>(T[] data, int start, int end, Func<T, T, int> compare)
  93. {
  94. Assertions.Assert.IsTrue((uint)start < data.Length);
  95. Assertions.Assert.IsTrue((uint)end < data.Length);
  96. for (int i = start + 1; i < end + 1; i++)
  97. {
  98. var iData = data[i];
  99. int j = i - 1;
  100. while (j >= 0 && compare(iData, data[j]) < 0)
  101. {
  102. data[j + 1] = data[j];
  103. j--;
  104. }
  105. data[j + 1] = iData;
  106. }
  107. }
  108. }
  109. }