1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
package qsort
type uint256 = struct {
a uint64 // hi
b uint64
c uint64
d uint64 // lo
}
type smallsort256 func(data []uint256, base int, swap func(int, int))
type partition256 func(data []uint256, base int, swap func(int, int)) int
func quicksort256(data []uint256, base, cutoff int, smallsort smallsort256, partition partition256, swap func(int, int)) {
for len(data) > 1 {
if len(data) <= cutoff/32 {
smallsort(data, base, swap)
return
}
medianOfThree256(data, base, swap)
p := partition(data, base, swap)
if p < len(data)-p { // recurse on the smaller side
quicksort256(data[:p], base, cutoff, smallsort, partition, swap)
data = data[p+1:]
base = base + p + 1
} else {
quicksort256(data[p+1:], base+p+1, cutoff, smallsort, partition, swap)
data = data[:p]
}
}
}
func insertionsort256(data []uint256, base int, swap func(int, int)) {
for i := 1; i < len(data); i++ {
item := data[i]
for j := i; j > 0 && less256(item, data[j-1]); j-- {
data[j], data[j-1] = data[j-1], data[j]
callswap(base, swap, j, j-1)
}
}
}
func medianOfThree256(data []uint256, base int, swap func(int, int)) {
end := len(data) - 1
mid := len(data) / 2
if less256(data[0], data[mid]) {
data[mid], data[0] = data[0], data[mid]
callswap(base, swap, mid, 0)
}
if less256(data[end], data[0]) {
data[0], data[end] = data[end], data[0]
callswap(base, swap, 0, end)
if less256(data[0], data[mid]) {
data[mid], data[0] = data[0], data[mid]
callswap(base, swap, mid, 0)
}
}
}
func hoarePartition256(data []uint256, base int, swap func(int, int)) int {
i, j := 1, len(data)-1
if len(data) > 0 {
pivot := data[0]
for j < len(data) {
for i < len(data) && less256(data[i], pivot) {
i++
}
for j > 0 && less256(pivot, data[j]) {
j--
}
if i >= j {
break
}
data[i], data[j] = data[j], data[i]
callswap(base, swap, i, j)
i++
j--
}
data[0], data[j] = data[j], data[0]
callswap(base, swap, 0, j)
}
return j
}
func hybridPartition256(data, scratch []uint256) int {
pivot, lo, hi, limit := 0, 1, len(data)-1, len(scratch)
p := distributeForward256(data, scratch, limit, lo, hi)
if hi-p <= limit {
scratch = scratch[limit-hi+p:]
} else {
lo = p + limit
for {
hi = distributeBackward256(data, data[lo+1-limit:], limit, lo, hi) - limit
if hi < lo {
p = hi
break
}
lo = distributeForward256(data, data[hi+1:], limit, lo, hi) + limit
if hi < lo {
p = lo - limit
break
}
}
}
copy(data[p+1:], scratch[:])
data[pivot], data[p] = data[p], data[pivot]
return p
}
func less256(a, b uint256) bool {
return a.a < b.a ||
(a.a == b.a && a.b < b.b) ||
(a.a == b.a && a.b == b.b && a.c < b.c) ||
(a.a == b.a && a.b == b.b && a.c == b.c && a.d < b.d)
}
|