Skip to content

Commit 4bbe5a0

Browse files
gzliudanwgr523
authored andcommitted
common: implement old version of func sort.Slice
1 parent 9d6adab commit 4bbe5a0

File tree

1 file changed

+190
-0
lines changed

1 file changed

+190
-0
lines changed

common/sort/slice.go

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
// Copyright 2017 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package sort
6+
7+
import "reflect"
8+
9+
// any is an alias for interface{} and is equivalent to interface{} in all ways.
10+
type any = interface{}
11+
12+
// lessSwap is a pair of Less and Swap function for use with the
13+
// auto-generated func-optimized variant of sort.go in
14+
// zfuncversion.go.
15+
type lessSwap struct {
16+
Less func(i, j int) bool
17+
Swap func(i, j int)
18+
}
19+
20+
// Slice sorts the slice x given the provided less function.
21+
// It panics if x is not a slice.
22+
//
23+
// The sort is not guaranteed to be stable: equal elements
24+
// may be reversed from their original order.
25+
// For a stable sort, use SliceStable.
26+
//
27+
// The less function must satisfy the same requirements as
28+
// the Interface type's Less method.
29+
func Slice(x any, less func(i, j int) bool) {
30+
rv := reflect.ValueOf(x)
31+
swap := reflect.Swapper(x)
32+
length := rv.Len()
33+
quickSort_func(lessSwap{less, swap}, 0, length, maxDepth(length))
34+
}
35+
36+
// maxDepth returns a threshold at which quicksort should switch
37+
// to heapsort. It returns 2*ceil(lg(n+1)).
38+
func maxDepth(n int) int {
39+
var depth int
40+
for i := n; i > 0; i >>= 1 {
41+
depth++
42+
}
43+
return depth * 2
44+
}
45+
46+
// Auto-generated variant of sort.go:quickSort
47+
func quickSort_func(data lessSwap, a, b, maxDepth int) {
48+
for b-a > 12 {
49+
if maxDepth == 0 {
50+
heapSort_func(data, a, b)
51+
return
52+
}
53+
maxDepth--
54+
mlo, mhi := doPivot_func(data, a, b)
55+
if mlo-a < b-mhi {
56+
quickSort_func(data, a, mlo, maxDepth)
57+
a = mhi
58+
} else {
59+
quickSort_func(data, mhi, b, maxDepth)
60+
b = mlo
61+
}
62+
}
63+
if b-a > 1 {
64+
for i := a + 6; i < b; i++ {
65+
if data.Less(i, i-6) {
66+
data.Swap(i, i-6)
67+
}
68+
}
69+
insertionSort_func(data, a, b)
70+
}
71+
}
72+
73+
// Auto-generated variant of sort.go:heapSort
74+
func heapSort_func(data lessSwap, a, b int) {
75+
first := a
76+
lo := 0
77+
hi := b - a
78+
for i := (hi - 1) / 2; i >= 0; i-- {
79+
siftDown_func(data, i, hi, first)
80+
}
81+
for i := hi - 1; i >= 0; i-- {
82+
data.Swap(first, first+i)
83+
siftDown_func(data, lo, i, first)
84+
}
85+
}
86+
87+
// Auto-generated variant of sort.go:doPivot
88+
func doPivot_func(data lessSwap, lo, hi int) (midlo, midhi int) {
89+
m := int(uint(lo+hi) >> 1)
90+
if hi-lo > 40 {
91+
s := (hi - lo) / 8
92+
medianOfThree_func(data, lo, lo+s, lo+2*s)
93+
medianOfThree_func(data, m, m-s, m+s)
94+
medianOfThree_func(data, hi-1, hi-1-s, hi-1-2*s)
95+
}
96+
medianOfThree_func(data, lo, m, hi-1)
97+
pivot := lo
98+
a, c := lo+1, hi-1
99+
for ; a < c && data.Less(a, pivot); a++ {
100+
}
101+
b := a
102+
for {
103+
for ; b < c && !data.Less(pivot, b); b++ {
104+
}
105+
for ; b < c && data.Less(pivot, c-1); c-- {
106+
}
107+
if b >= c {
108+
break
109+
}
110+
data.Swap(b, c-1)
111+
b++
112+
c--
113+
}
114+
protect := hi-c < 5
115+
if !protect && hi-c < (hi-lo)/4 {
116+
dups := 0
117+
if !data.Less(pivot, hi-1) {
118+
data.Swap(c, hi-1)
119+
c++
120+
dups++
121+
}
122+
if !data.Less(b-1, pivot) {
123+
b--
124+
dups++
125+
}
126+
if !data.Less(m, pivot) {
127+
data.Swap(m, b-1)
128+
b--
129+
dups++
130+
}
131+
protect = dups > 1
132+
}
133+
if protect {
134+
for {
135+
for ; a < b && !data.Less(b-1, pivot); b-- {
136+
}
137+
for ; a < b && data.Less(a, pivot); a++ {
138+
}
139+
if a >= b {
140+
break
141+
}
142+
data.Swap(a, b-1)
143+
a++
144+
b--
145+
}
146+
}
147+
data.Swap(pivot, b-1)
148+
return b - 1, c
149+
}
150+
151+
// Auto-generated variant of sort.go:insertionSort
152+
func insertionSort_func(data lessSwap, a, b int) {
153+
for i := a + 1; i < b; i++ {
154+
for j := i; j > a && data.Less(j, j-1); j-- {
155+
data.Swap(j, j-1)
156+
}
157+
}
158+
}
159+
160+
// Auto-generated variant of sort.go:siftDown
161+
func siftDown_func(data lessSwap, lo, hi, first int) {
162+
root := lo
163+
for {
164+
child := 2*root + 1
165+
if child >= hi {
166+
break
167+
}
168+
if child+1 < hi && data.Less(first+child, first+child+1) {
169+
child++
170+
}
171+
if !data.Less(first+root, first+child) {
172+
return
173+
}
174+
data.Swap(first+root, first+child)
175+
root = child
176+
}
177+
}
178+
179+
// Auto-generated variant of sort.go:medianOfThree
180+
func medianOfThree_func(data lessSwap, m1, m0, m2 int) {
181+
if data.Less(m1, m0) {
182+
data.Swap(m1, m0)
183+
}
184+
if data.Less(m2, m1) {
185+
data.Swap(m2, m1)
186+
if data.Less(m1, m0) {
187+
data.Swap(m1, m0)
188+
}
189+
}
190+
}

0 commit comments

Comments
 (0)