// data.Less and O(n*log(n)*log(n)) calls to data.Swap.
func Stable(data Interface) {
n := data.Len()
- blockSize := 20
+ blockSize := 20 // must be > 0
a, b := 0, blockSize
for b <= n {
insertionSort(data, a, b)
a = b
b += 2 * blockSize
}
- symMerge(data, a, a+blockSize, n)
+ if m := a + blockSize; m < n {
+ symMerge(data, a, m, n)
+ }
blockSize *= 2
}
}
// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation
// in the paper carries through for Swap operations, especially as the block
// swapping rotate uses only O(M+N) Swaps.
+//
+// symMerge assumes non-degenerate arguments: a < m && m < b.
+// Having the caller check this condition eliminates many leaf recursion calls,
+// which improves performance.
func symMerge(data Interface, a, m, b int) {
- if a >= m || m >= b {
- return
- }
-
mid := a + (b-a)/2
n := mid + m
var start, r int
end := n - start
rotate(data, start, m, end)
- symMerge(data, a, start, mid)
- symMerge(data, mid, end, b)
+ if a < start && start < mid {
+ symMerge(data, a, start, mid)
+ }
+ if mid < end && end < b {
+ symMerge(data, mid, end, b)
+ }
}
// Rotate two consecutives blocks u = data[a:m] and v = data[m:b] in data: