diff --git a/src/Numerics/Sorting.cs b/src/Numerics/Sorting.cs index 7b259164..03e68e14 100644 --- a/src/Numerics/Sorting.cs +++ b/src/Numerics/Sorting.cs @@ -133,7 +133,7 @@ namespace MathNet.Numerics } /// - /// Sort a range of a list of keys, in place using the introsort algorithm. + /// Sort a range of a list of keys, in place using the quick sort algorithm. /// /// The type of element in the list. /// List to sort. @@ -152,11 +152,43 @@ namespace MathNet.Numerics throw new ArgumentOutOfRangeException(nameof(count)); } + if (count <= 1) + { + return; + } + if (null == comparer) { comparer = Comparer.Default; } + if (count == 2) + { + if (comparer.Compare(keys[index], keys[index + 1]) > 0) + { + Swap(keys, index, index + 1); + } + return; + } + + // insertion sort + if (count <= 10) + { + int to = index + count; + for (int i = index + 1; i < to; i++) + { + var key = keys[i]; + int j = i - 1; + while (j >= index && comparer.Compare(keys[j], key) > 0) + { + keys[j + 1] = keys[j]; + j--; + } + keys[j + 1] = key; + } + return; + } + // array case if (keys is T[] keysArray) { @@ -172,11 +204,11 @@ namespace MathNet.Numerics } // fall back: local sort implementation - IntroSort(keys, comparer, index, index + count, (int a, int b) => Swap(keys, a, b)); + QuickSort(keys, comparer, index, count - 1); } /// - /// Sort a list of keys and items with respect to the keys, in place using the introsort algorithm. + /// Sort a list of keys and items with respect to the keys, in place using the quick sort algorithm. /// /// The type of elements in the key list. /// The type of elements in the item list. @@ -197,22 +229,60 @@ namespace MathNet.Numerics throw new ArgumentOutOfRangeException(nameof(count)); } + if (count <= 1) + { + return; + } + if (null == comparer) { comparer = Comparer.Default; } - // fall back: local sort implementation - Action swap = (int a, int b) => + if (count == 2) { - Swap(keys, a, b); - Swap(items, a, b); - }; - IntroSort(keys, comparer, index, index + count, swap); + if (comparer.Compare(keys[index], keys[index + 1]) > 0) + { + Swap(keys, index, index + 1); + Swap(items, index, index + 1); + } + return; + } + + // insertion sort + if (count <= 10) + { + int to = index + count; + for (int i = index + 1; i < to; i++) + { + var key = keys[i]; + var item = items[i]; + int j = i - 1; + while (j >= index && comparer.Compare(keys[j], key) > 0) + { + keys[j + 1] = keys[j]; + items[j + 1] = items[j]; + j--; + } + keys[j + 1] = key; + items[j + 1] = item; + } + return; + } + + // array case + if (keys is TKey[] keysArray && items is TItem[] itemsArray) + { + Array.Sort(keysArray, itemsArray, index, count, comparer); + return; + } + + // fall back: local sort implementation + QuickSort(keys, items, comparer, index, count - 1); } /// - /// Sort a list of keys, items1 and items2 with respect to the keys, in place using the introsort algorithm. + /// Sort a list of keys, items1 and items2 with respect to the keys, in place using the quick sort algorithm. /// /// The type of elements in the key list. /// The type of elements in the first item list. @@ -235,19 +305,53 @@ namespace MathNet.Numerics throw new ArgumentOutOfRangeException(nameof(count)); } + if (count <= 1) + { + return; + } + if (null == comparer) { comparer = Comparer.Default; } - // fall back: local sort implementation - Action swap = (int a, int b) => + if (count == 2) { - Swap(keys, a, b); - Swap(items1, a, b); - Swap(items2, a, b); - }; - IntroSort(keys, comparer, index, index + count, swap); + if (comparer.Compare(keys[index], keys[index + 1]) > 0) + { + Swap(keys, index, index + 1); + Swap(items1, index, index + 1); + Swap(items2, index, index + 1); + } + return; + } + + // insertion sort + if (count <= 10) + { + int to = index + count; + for (int i = index + 1; i < to; i++) + { + var key = keys[i]; + var item1 = items1[i]; + var item2 = items2[i]; + int j = i - 1; + while (j >= index && comparer.Compare(keys[j], key) > 0) + { + keys[j + 1] = keys[j]; + items1[j + 1] = items1[j]; + items2[j + 1] = items2[j]; + j--; + } + keys[j + 1] = key; + items1[j + 1] = item1; + items2[j + 1] = item2; + } + return; + } + + // fall back: local sort implementation + QuickSort(keys, items1, items2, comparer, index, count - 1); } ///