blob: f693611348dfd168352c261aaf7b7a53210833cb [file] [log] [blame]
// Copyright ©2019 The Gonum 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 kdtree
import (
"sort"
"testing"
"golang.org/x/exp/rand"
)
type ints []int
func (a ints) Len() int { return len(a) }
func (a ints) Less(i, j int) bool { return a[i] < a[j] }
func (a ints) Slice(s, e int) SortSlicer { return a[s:e] }
func (a ints) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func TestPartition(t *testing.T) {
rnd := rand.New(rand.NewSource(1))
for p := 0; p < 100; p++ {
list := make(ints, 1e5)
for i := range list {
list[i] = rnd.Int()
}
pi := Partition(list, rnd.Intn(list.Len()))
for i := 0; i < pi; i++ {
if list[i] > list[pi] {
t.Errorf("unexpected partition sort order p[%d] > p[%d]: %d > %d", i, pi, list[i], list[pi])
}
}
for i := pi + 1; i < len(list); i++ {
if list[i] <= list[pi] {
t.Errorf("unexpected partition sort order p[%d] <= p[%d]: %d <= %d", i, pi, list[i], list[pi])
}
}
}
}
func TestPartitionCollision(t *testing.T) {
rnd := rand.New(rand.NewSource(1))
for p := 0; p < 10; p++ {
list := make(ints, 10)
for i := range list {
list[i] = rnd.Intn(5)
}
pi := Partition(list, p)
for i := 0; i < pi; i++ {
if list[i] > list[pi] {
t.Errorf("unexpected partition sort order p[%d] > p[%d]: %d > %d", i, pi, list[i], list[pi])
}
}
for i := pi + 1; i < len(list); i++ {
if list[i] <= list[pi] {
t.Errorf("unexpected partition sort order p[%d] <= p[%d]: %d <= %d", i, pi, list[i], list[pi])
}
}
}
}
func sortSelection(list ints, k int) int {
sort.Sort(list)
return list[k]
}
func TestSelect(t *testing.T) {
rnd := rand.New(rand.NewSource(1))
for k := 0; k < 2121; k++ {
list := make(ints, 2121)
for i := range list {
list[i] = rnd.Intn(1000)
}
Select(list, k)
sorted := append(ints(nil), list...)
want := sortSelection(sorted, k)
if list[k] != want {
t.Errorf("unexpected result from Select(..., %d): got:%v want:%d", k, list[k], want)
}
}
}
func TestMedianOfMedians(t *testing.T) {
rnd := rand.New(rand.NewSource(1))
list := make(ints, 1e4)
for i := range list {
list[i] = rnd.Int()
}
p := MedianOfMedians(list)
med := list[p]
sort.Sort(list)
var found bool
for _, v := range list[len(list)*3/10 : len(list)*7/10+1] {
if v == med {
found = true
break
}
}
if !found {
t.Error("failed to find median")
}
}
func TestMedianOfRandoms(t *testing.T) {
rnd := rand.New(rand.NewSource(1))
list := make(ints, 1e4)
for i := range list {
list[i] = rnd.Int()
}
p := MedianOfRandoms(list, randoms)
med := list[p]
sort.Sort(list)
var found bool
for _, v := range list[len(list)*3/10 : len(list)*7/10+1] {
if v == med {
found = true
break
}
}
if !found {
t.Error("failed to find median")
}
}
var benchSink int
func BenchmarkMedianOfMedians(b *testing.B) {
rnd := rand.New(rand.NewSource(1))
for i := 0; i < b.N; i++ {
b.StopTimer()
list := make(ints, 1e4)
for i := range list {
list[i] = rnd.Int()
}
b.StartTimer()
benchSink = MedianOfMedians(list)
}
}
func BenchmarkPartitionMedianOfMedians(b *testing.B) {
rnd := rand.New(rand.NewSource(1))
for i := 0; i < b.N; i++ {
b.StopTimer()
list := make(ints, 1e4)
for i := range list {
list[i] = rnd.Int()
}
b.StartTimer()
benchSink = Partition(list, MedianOfMedians(list))
}
}
func BenchmarkMedianOfRandoms(b *testing.B) {
rnd := rand.New(rand.NewSource(1))
b.StopTimer()
list := make(ints, 1e4)
for i := range list {
list[i] = rnd.Int()
}
b.StartTimer()
for i := 0; i < b.N; i++ {
benchSink = MedianOfRandoms(list, list.Len()/1e3)
}
}
func BenchmarkPartitionMedianOfRandoms(b *testing.B) {
rnd := rand.New(rand.NewSource(1))
b.StopTimer()
list := make(ints, 1e4)
for i := range list {
list[i] = rnd.Int()
}
b.StartTimer()
for i := 0; i < b.N; i++ {
benchSink = Partition(list, MedianOfRandoms(list, list.Len()/1e3))
}
}