github.com/gopherd/gonum@v0.0.4/spatial/kdtree/medians_test.go (about) 1 // Copyright ©2019 The Gonum 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 kdtree 6 7 import ( 8 "sort" 9 "testing" 10 11 "math/rand" 12 ) 13 14 type ints []int 15 16 func (a ints) Len() int { return len(a) } 17 func (a ints) Less(i, j int) bool { return a[i] < a[j] } 18 func (a ints) Slice(s, e int) SortSlicer { return a[s:e] } 19 func (a ints) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 20 21 func TestPartition(t *testing.T) { 22 rnd := rand.New(rand.NewSource(1)) 23 24 for p := 0; p < 100; p++ { 25 list := make(ints, 1e5) 26 for i := range list { 27 list[i] = rnd.Int() 28 } 29 pi := Partition(list, rnd.Intn(list.Len())) 30 for i := 0; i < pi; i++ { 31 if list[i] > list[pi] { 32 t.Errorf("unexpected partition sort order p[%d] > p[%d]: %d > %d", i, pi, list[i], list[pi]) 33 } 34 } 35 for i := pi + 1; i < len(list); i++ { 36 if list[i] <= list[pi] { 37 t.Errorf("unexpected partition sort order p[%d] <= p[%d]: %d <= %d", i, pi, list[i], list[pi]) 38 } 39 } 40 } 41 } 42 43 func TestPartitionCollision(t *testing.T) { 44 rnd := rand.New(rand.NewSource(1)) 45 46 for p := 0; p < 10; p++ { 47 list := make(ints, 10) 48 for i := range list { 49 list[i] = rnd.Intn(5) 50 } 51 pi := Partition(list, p) 52 for i := 0; i < pi; i++ { 53 if list[i] > list[pi] { 54 t.Errorf("unexpected partition sort order p[%d] > p[%d]: %d > %d", i, pi, list[i], list[pi]) 55 } 56 } 57 for i := pi + 1; i < len(list); i++ { 58 if list[i] <= list[pi] { 59 t.Errorf("unexpected partition sort order p[%d] <= p[%d]: %d <= %d", i, pi, list[i], list[pi]) 60 } 61 } 62 } 63 } 64 65 func sortSelection(list ints, k int) int { 66 sort.Sort(list) 67 return list[k] 68 } 69 70 func TestSelect(t *testing.T) { 71 rnd := rand.New(rand.NewSource(1)) 72 73 for k := 0; k < 2121; k++ { 74 list := make(ints, 2121) 75 for i := range list { 76 list[i] = rnd.Intn(1000) 77 } 78 Select(list, k) 79 sorted := append(ints(nil), list...) 80 want := sortSelection(sorted, k) 81 if list[k] != want { 82 t.Errorf("unexpected result from Select(..., %d): got:%v want:%d", k, list[k], want) 83 } 84 } 85 } 86 87 func TestMedianOfMedians(t *testing.T) { 88 rnd := rand.New(rand.NewSource(1)) 89 90 list := make(ints, 1e4) 91 for i := range list { 92 list[i] = rnd.Int() 93 } 94 p := MedianOfMedians(list) 95 med := list[p] 96 sort.Sort(list) 97 var found bool 98 for _, v := range list[len(list)*3/10 : len(list)*7/10+1] { 99 if v == med { 100 found = true 101 break 102 } 103 } 104 if !found { 105 t.Error("failed to find median") 106 } 107 } 108 109 func TestMedianOfRandoms(t *testing.T) { 110 rnd := rand.New(rand.NewSource(1)) 111 112 list := make(ints, 1e4) 113 for i := range list { 114 list[i] = rnd.Int() 115 } 116 p := MedianOfRandoms(list, randoms) 117 med := list[p] 118 sort.Sort(list) 119 var found bool 120 for _, v := range list[len(list)*3/10 : len(list)*7/10+1] { 121 if v == med { 122 found = true 123 break 124 } 125 } 126 if !found { 127 t.Error("failed to find median") 128 } 129 } 130 131 var benchSink int 132 133 func BenchmarkMedianOfMedians(b *testing.B) { 134 rnd := rand.New(rand.NewSource(1)) 135 136 for i := 0; i < b.N; i++ { 137 b.StopTimer() 138 list := make(ints, 1e4) 139 for i := range list { 140 list[i] = rnd.Int() 141 } 142 b.StartTimer() 143 benchSink = MedianOfMedians(list) 144 } 145 } 146 147 func BenchmarkPartitionMedianOfMedians(b *testing.B) { 148 rnd := rand.New(rand.NewSource(1)) 149 150 for i := 0; i < b.N; i++ { 151 b.StopTimer() 152 list := make(ints, 1e4) 153 for i := range list { 154 list[i] = rnd.Int() 155 } 156 b.StartTimer() 157 benchSink = Partition(list, MedianOfMedians(list)) 158 } 159 } 160 161 func BenchmarkMedianOfRandoms(b *testing.B) { 162 rnd := rand.New(rand.NewSource(1)) 163 164 b.StopTimer() 165 list := make(ints, 1e4) 166 for i := range list { 167 list[i] = rnd.Int() 168 } 169 b.StartTimer() 170 for i := 0; i < b.N; i++ { 171 benchSink = MedianOfRandoms(list, list.Len()/1e3) 172 } 173 } 174 175 func BenchmarkPartitionMedianOfRandoms(b *testing.B) { 176 rnd := rand.New(rand.NewSource(1)) 177 178 b.StopTimer() 179 list := make(ints, 1e4) 180 for i := range list { 181 list[i] = rnd.Int() 182 } 183 b.StartTimer() 184 for i := 0; i < b.N; i++ { 185 benchSink = Partition(list, MedianOfRandoms(list, list.Len()/1e3)) 186 } 187 }