var ( wasBalanced = true// whether the last partitioning was reasonably balanced wasPartitioned = true// whether the slice was already partitioned )
for { length := b - a
if length <= maxInsertion { insertionSort(data, a, b) return }
// Fall back to heapsort if too many bad choices were made. if limit == 0 { heapSort(data, a, b) return }
// If the last partitioning was imbalanced, we need to breaking patterns. if !wasBalanced { breakPatterns(data, a, b) limit-- }
pivot, hint := choosePivot(data, a, b) if hint == decreasingHint { reverseRange(data, a, b) // The chosen pivot was pivot-a elements after the start of the array. // After reversing it is pivot-a elements before the end of the array. // The idea came from Rust's implementation. pivot = (b - 1) - (pivot - a) hint = increasingHint }
// The slice is likely already sorted. if wasBalanced && wasPartitioned && hint == increasingHint { if partialInsertionSort(data, a, b) { return } }
// Probably the slice contains many duplicate elements, partition the slice into // elements equal to and elements greater than the pivot. if a > 0 && !data.Less(a-1, pivot) { mid := partitionEqual(data, a, b, pivot) a = mid continue }
mid, alreadyPartitioned := partition(data, a, b, pivot) wasPartitioned = alreadyPartitioned