mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
190 lines
4 KiB
Go
190 lines
4 KiB
Go
// Copyright 2017 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package sort
|
|
|
|
import "reflect"
|
|
|
|
// any is an alias for interface{} and is equivalent to interface{} in all ways.
|
|
type any = interface{}
|
|
|
|
// lessSwap is a pair of Less and Swap function for use with the
|
|
// auto-generated func-optimized variant of sort.go in
|
|
// zfuncversion.go.
|
|
type lessSwap struct {
|
|
Less func(i, j int) bool
|
|
Swap func(i, j int)
|
|
}
|
|
|
|
// Slice sorts the slice x given the provided less function.
|
|
// It panics if x is not a slice.
|
|
//
|
|
// The sort is not guaranteed to be stable: equal elements
|
|
// may be reversed from their original order.
|
|
// For a stable sort, use SliceStable.
|
|
//
|
|
// The less function must satisfy the same requirements as
|
|
// the Interface type's Less method.
|
|
func Slice(x any, less func(i, j int) bool) {
|
|
rv := reflect.ValueOf(x)
|
|
swap := reflect.Swapper(x)
|
|
length := rv.Len()
|
|
quickSort_func(lessSwap{less, swap}, 0, length, maxDepth(length))
|
|
}
|
|
|
|
// maxDepth returns a threshold at which quicksort should switch
|
|
// to heapsort. It returns 2*ceil(lg(n+1)).
|
|
func maxDepth(n int) int {
|
|
var depth int
|
|
for i := n; i > 0; i >>= 1 {
|
|
depth++
|
|
}
|
|
return depth * 2
|
|
}
|
|
|
|
// Auto-generated variant of sort.go:quickSort
|
|
func quickSort_func(data lessSwap, a, b, maxDepth int) {
|
|
for b-a > 12 {
|
|
if maxDepth == 0 {
|
|
heapSort_func(data, a, b)
|
|
return
|
|
}
|
|
maxDepth--
|
|
mlo, mhi := doPivot_func(data, a, b)
|
|
if mlo-a < b-mhi {
|
|
quickSort_func(data, a, mlo, maxDepth)
|
|
a = mhi
|
|
} else {
|
|
quickSort_func(data, mhi, b, maxDepth)
|
|
b = mlo
|
|
}
|
|
}
|
|
if b-a > 1 {
|
|
for i := a + 6; i < b; i++ {
|
|
if data.Less(i, i-6) {
|
|
data.Swap(i, i-6)
|
|
}
|
|
}
|
|
insertionSort_func(data, a, b)
|
|
}
|
|
}
|
|
|
|
// Auto-generated variant of sort.go:heapSort
|
|
func heapSort_func(data lessSwap, a, b int) {
|
|
first := a
|
|
lo := 0
|
|
hi := b - a
|
|
for i := (hi - 1) / 2; i >= 0; i-- {
|
|
siftDown_func(data, i, hi, first)
|
|
}
|
|
for i := hi - 1; i >= 0; i-- {
|
|
data.Swap(first, first+i)
|
|
siftDown_func(data, lo, i, first)
|
|
}
|
|
}
|
|
|
|
// Auto-generated variant of sort.go:doPivot
|
|
func doPivot_func(data lessSwap, lo, hi int) (midlo, midhi int) {
|
|
m := int(uint(lo+hi) >> 1)
|
|
if hi-lo > 40 {
|
|
s := (hi - lo) / 8
|
|
medianOfThree_func(data, lo, lo+s, lo+2*s)
|
|
medianOfThree_func(data, m, m-s, m+s)
|
|
medianOfThree_func(data, hi-1, hi-1-s, hi-1-2*s)
|
|
}
|
|
medianOfThree_func(data, lo, m, hi-1)
|
|
pivot := lo
|
|
a, c := lo+1, hi-1
|
|
for ; a < c && data.Less(a, pivot); a++ {
|
|
}
|
|
b := a
|
|
for {
|
|
for ; b < c && !data.Less(pivot, b); b++ {
|
|
}
|
|
for ; b < c && data.Less(pivot, c-1); c-- {
|
|
}
|
|
if b >= c {
|
|
break
|
|
}
|
|
data.Swap(b, c-1)
|
|
b++
|
|
c--
|
|
}
|
|
protect := hi-c < 5
|
|
if !protect && hi-c < (hi-lo)/4 {
|
|
dups := 0
|
|
if !data.Less(pivot, hi-1) {
|
|
data.Swap(c, hi-1)
|
|
c++
|
|
dups++
|
|
}
|
|
if !data.Less(b-1, pivot) {
|
|
b--
|
|
dups++
|
|
}
|
|
if !data.Less(m, pivot) {
|
|
data.Swap(m, b-1)
|
|
b--
|
|
dups++
|
|
}
|
|
protect = dups > 1
|
|
}
|
|
if protect {
|
|
for {
|
|
for ; a < b && !data.Less(b-1, pivot); b-- {
|
|
}
|
|
for ; a < b && data.Less(a, pivot); a++ {
|
|
}
|
|
if a >= b {
|
|
break
|
|
}
|
|
data.Swap(a, b-1)
|
|
a++
|
|
b--
|
|
}
|
|
}
|
|
data.Swap(pivot, b-1)
|
|
return b - 1, c
|
|
}
|
|
|
|
// Auto-generated variant of sort.go:insertionSort
|
|
func insertionSort_func(data lessSwap, a, b int) {
|
|
for i := a + 1; i < b; i++ {
|
|
for j := i; j > a && data.Less(j, j-1); j-- {
|
|
data.Swap(j, j-1)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Auto-generated variant of sort.go:siftDown
|
|
func siftDown_func(data lessSwap, lo, hi, first int) {
|
|
root := lo
|
|
for {
|
|
child := 2*root + 1
|
|
if child >= hi {
|
|
break
|
|
}
|
|
if child+1 < hi && data.Less(first+child, first+child+1) {
|
|
child++
|
|
}
|
|
if !data.Less(first+root, first+child) {
|
|
return
|
|
}
|
|
data.Swap(first+root, first+child)
|
|
root = child
|
|
}
|
|
}
|
|
|
|
// Auto-generated variant of sort.go:medianOfThree
|
|
func medianOfThree_func(data lessSwap, m1, m0, m2 int) {
|
|
if data.Less(m1, m0) {
|
|
data.Swap(m1, m0)
|
|
}
|
|
if data.Less(m2, m1) {
|
|
data.Swap(m2, m1)
|
|
if data.Less(m1, m0) {
|
|
data.Swap(m1, m0)
|
|
}
|
|
}
|
|
}
|