package qsort
type smallsort64 func(data []uint64, base int, swap func(int, int))
type partition64 func(data []uint64, base int, swap func(int, int)) int
func quicksort64(data []uint64, base, cutoff int, smallsort smallsort64, partition partition64, swap func(int, int)) {
for len(data) > 1 {
if len(data) <= cutoff/8 {
smallsort(data, base, swap)
return
}
medianOfThree64(data, base, swap)
p := partition(data, base, swap)
if p < len(data)-p { // recurse on the smaller side
quicksort64(data[:p], base, cutoff, smallsort, partition, swap)
data = data[p+1:]
base = base + p + 1
} else {
quicksort64(data[p+1:], base+p+1, cutoff, smallsort, partition, swap)
data = data[:p]
}
}
}
func bubblesort64NoSwap1(data []uint64, base int, swap func(int, int)) {
for i := len(data); i > 1; i-- {
max := data[0]
for j := 1; j < i; j++ {
y := data[j]
x := uint64(0)
if max <= y {
x = max
} else {
x = y
}
if max <= y {
max = y
}
data[j-1] = x
}
data[i-1] = max
}
}
func bubblesort64NoSwap2(data []uint64, base int, swap func(int, int)) {
for i := len(data); i > 1; i -= 2 {
x := data[0]
y := data[1]
if y < x {
x, y = y, x
}
for j := 2; j < i; j++ {
z := data[j]
w := uint64(0)
v := uint64(0)
if y <= z {
w = y
} else {
w = z
}
if y <= z {
y = z
}
if x <= z {
v = x
} else {
v = z
}
if x <= z {
x = w
}
data[j-2] = v
}
data[i-2] = x
data[i-1] = y
}
}
func insertionsort64(data []uint64, base int, swap func(int, int)) {
for i := 1; i < len(data); i++ {
item := data[i]
for j := i; j > 0 && item < data[j-1]; j-- {
data[j], data[j-1] = data[j-1], data[j]
callswap(base, swap, j, j-1)
}
}
}
func medianOfThree64(data []uint64, base int, swap func(int, int)) {
end := len(data) - 1
mid := len(data) / 2
if data[0] < data[mid] {
data[mid], data[0] = data[0], data[mid]
callswap(base, swap, mid, 0)
}
if data[end] < data[0] {
data[0], data[end] = data[end], data[0]
callswap(base, swap, 0, end)
if data[0] < data[mid] {
data[mid], data[0] = data[0], data[mid]
callswap(base, swap, mid, 0)
}
}
}
func hoarePartition64(data []uint64, 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) && data[i] < pivot {
i++
}
for j > 0 && 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 hybridPartition64(data, scratch []uint64) int {
pivot, lo, hi, limit := 0, 1, len(data)-1, len(scratch)
p := distributeForward64(data, scratch, limit, lo, hi)
if hi-p <= limit {
scratch = scratch[limit-hi+p:]
} else {
lo = p + limit
for {
hi = distributeBackward64(data, data[lo+1-limit:], limit, lo, hi) - limit
if hi < lo {
p = hi
break
}
lo = distributeForward64(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
}