mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 13:21:37 +00:00
common: implement old version of func sort.Slice
This commit is contained in:
parent
9d6adab8fb
commit
4bbe5a0443
1 changed files with 190 additions and 0 deletions
190
common/sort/slice.go
Normal file
190
common/sort/slice.go
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue