├── .gitignore ├── .travis.yml ├── BENCHMARKS.md ├── LICENSE ├── README.md ├── bench_test.go ├── benchint_test.go ├── benchstring_test.go ├── codecov.yml ├── go.mod ├── scripts ├── benchmark_table.sh └── benchmarkint_table.sh ├── timsort.go ├── timsort_test.go ├── timsortint.go ├── timsortint_test.go ├── timsortintf.go ├── timsortintf_test.go └── v2 ├── bench_test.go ├── benchint_test.go ├── benchstring_test.go ├── go.mod ├── timsort.go ├── timsort_test.go ├── timsortint.go ├── timsortint_test.go ├── timsortintf.go └── timsortintf_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | .project 2 | *.swp 3 | coverage.txt 4 | 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | arch: 4 | - amd64 5 | 6 | go: 7 | - 1.19 8 | 9 | before_script: 10 | - go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest 11 | 12 | script: 13 | - cd v2 14 | - golangci-lint run 15 | - go test -v -race -coverprofile=coverage.txt -covermode=atomic 16 | 17 | after_success: 18 | - bash <(curl -s https://codecov.io/bash) 19 | 20 | -------------------------------------------------------------------------------- /BENCHMARKS.md: -------------------------------------------------------------------------------- 1 | # Benchmarking timsort 2 | 3 | Tested on: Intel i7 8809G @3.10G running Debian 4.18.20-2 (2018-11-23) x86_64 GNU/Linux, go1.11.2 linux/amd64 4 | 5 | Numbers are ns/op as reported by `go test -test.bench=.*` / `scripts/*.sh`. First number is for timsort, followed by standard sort.Sort (for ints) or sort.Stable otherwise, in parentheses. 6 | `Xor100` means - sorting 100 elements generated using `Xor` method, 7 | `Random1M` means - sorting 1 meg (1024*1024) records generated randomly. 8 | For more detail on data shapes see the source - [bench_test.go][bench_test.go]. 9 | Three columns represent three benchmark runs. 10 | 11 | ### Comparing stable sort 12 | 13 | benchmark_table.sh: 14 | 15 | Sorted100: 1421 (668) 1362 (696) 1400 (682) 16 | RevSorted100: 1540 (7934) 1541 (7858) 1544 (8351) 17 | Xor100: 4797 (5909) 4787 (6060) 4913 (5848) 18 | Random100: 5211 (8144) 5251 (7878) 5259 (7979) 19 | 20 | Sorted1K: 5528 (4856) 5604 (4958) 5575 (4994) 21 | RevSorted1K: 6694 (86263) 6549 (89099) 6473 (89702) 22 | Xor1K: 45905 (115574) 45706 (121319) 48774 (114212) 23 | Random1K: 117190 (206253) 113427 (202286) 116871 (208261) 24 | 25 | Sorted1M: 4238347 (8991637) 4125454 (8718271) 4199811 (8524249) 26 | RevSorted1M: 6498133 (122685926) 6274050 (113631337) 6218917 (117388612) 27 | Xor1M: 103830787 (226644420) 97834093 (232690160) 100051210 (228723419) 28 | Random1M: 348764192 (663024283) 367589312 (690514504) 377960208 (733221145) 29 | 30 | Timsort is crazy fast on patterned inputs, but even for random input it is much faster than stable sort in Go. Exception is a fully sorted input, where Go's stable sort greatly benefits on small inputs because it uses insertion sort in implementation. 31 | Disclaimer: The above benchmark applies only to one specific type of data element (`record` structure as defined in [bench_test.go][bench_test.go]). For other data types results may vary. 32 | 33 | 34 | ### Benchmarking primitives 35 | 36 | benchmarkint_table.sh: 37 | 38 | Sorted100: 948 (1977) 942 (1926) 918 (1965) 39 | RevSorted100: 1003 (2161) 1016 (2166) 1004 (2133) 40 | Xor100: 3327 (2831) 3297 (2858) 3256 (2876) 41 | Random100: 3640 (2895) 3580 (2900) 3546 (2892) 42 | 43 | Sorted1K: 3664 (29693) 3757 (29639) 3568 (29545) 44 | RevSorted1K: 4724 (31183) 4629 (31691) 4653 (31430) 45 | Xor1K: 30678 (53533) 31136 (53791) 32052 (55790) 46 | Random1K: 93291 (78021) 93153 (75886) 96178 (77012) 47 | 48 | Sorted1M: 2612806 (63640085) 2657223 (66381050) 2782516 (65576825) 49 | RevSorted1M: 3236216 (65236079) 3241050 (62996742) 3445819 (66550484) 50 | Xor1M: 62054181 (61609233) 58021830 (59778514) 57094210 (65384476) 51 | Random1M: 212171678 (185525353) 199493986 (184466052) 223314023 (188326317) 52 | 53 | If stable sort is not required then default sort in Go (quicksort) gives better results for random inputs. 54 | 55 | 56 | [bench_test.go]: http://github.com/psilva261/timsort/blob/master/bench_test.go 57 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2011 Mike Kroutikov 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # timsort [![Build Status](https://api.travis-ci.com/psilva261/timsort.svg?branch=master)](https://travis-ci.com/psilva261/timsort) [![codecov](https://codecov.io/gh/psilva261/timsort/branch/master/graph/badge.svg)](https://codecov.io/gh/psilva261/timsort) 2 | 3 | **timsort** is a Go implementation of Tim Peters' mergesort 4 | sorting algorithm. It's stable and runs in O(n) time for presorted 5 | inputs and O(n log n) otherwise. 6 | 7 | For many input types it is 2-3 times faster than Go's built-in sorting. 8 | 9 | The main drawback of this sort method is that it is not in-place (as any 10 | mergesort), and may put extra strain on garbage collector. 11 | 12 | This implementation was ported to Go by Mike Kroutikov 13 | and derived from Java's TimSort object by Josh Bloch, 14 | which, in turn, was based on the [original code by Tim Peters][listsort]. 15 | 16 | ## Installation 17 | 18 | $ go get -u github.com/psilva261/timsort/v2 19 | 20 | ## Testing 21 | 22 | Inside the source directory, type 23 | 24 | go test 25 | 26 | to run test harness. 27 | 28 | ## Benchmarking 29 | 30 | Inside the source directory, type 31 | 32 | go test -test.bench=.* 33 | 34 | to run benchmarks. Each combination of input type/size is presented to timsort, 35 | and, for comparison, to the standard Go sort (sort.Sort for ints or sort.Stable otherwise). 36 | See [BENCHMARKS.md][BENCHMARKS.md] for more info and some benchmarking results. 37 | 38 | ## Examples 39 | 40 | ### As drop-in replacement for sort.Sort 41 | 42 | package main 43 | 44 | import ( 45 | "github.com/psilva261/timsort/v2" 46 | "fmt" 47 | "sort" 48 | ) 49 | 50 | func main() { 51 | l := []string{"c", "a", "b"} 52 | timsort.TimSort(sort.StringSlice(l) 53 | fmt.Printf("sorted array: %+v\n", l) 54 | } 55 | 56 | ### Explicit "less" function 57 | 58 | package main 59 | 60 | import ( 61 | "github.com/psilva261/timsort/v2" 62 | "fmt" 63 | ) 64 | 65 | type Record struct { 66 | ssn int 67 | name string 68 | } 69 | 70 | func BySsn(a, b interface{}) bool { 71 | return a.(Record).ssn < b.(Record).ssn 72 | } 73 | 74 | func ByName(a, b interface{}) bool { 75 | return a.(Record).name < b.(Record).name 76 | } 77 | 78 | func main() { 79 | db := make([]interface{}, 3) 80 | db[0] = Record{123456789, "joe"} 81 | db[1] = Record{101765430, "sue"} 82 | db[2] = Record{345623452, "mary"} 83 | 84 | // sorts array by ssn (ascending) 85 | timsort.Sort(db, BySsn) 86 | fmt.Printf("sorted by ssn: %v\n", db) 87 | 88 | // now re-sort same array by name (ascending) 89 | timsort.Sort(db, ByName) 90 | fmt.Printf("sorted by name: %v\n", db) 91 | } 92 | 93 | [listsort]: http://svn.python.org/projects/python/trunk/Objects/listsort.txt 94 | [BENCHMARKS.md]: http://github.com/psilva261/timsort/blob/master/BENCHMARKS.md 95 | -------------------------------------------------------------------------------- /bench_test.go: -------------------------------------------------------------------------------- 1 | package timsort 2 | 3 | import ( 4 | "math/rand" 5 | "sort" 6 | "testing" 7 | ) 8 | 9 | type record struct { 10 | key, order int 11 | } 12 | 13 | type records []interface{} 14 | 15 | func LessThanByKey(a, b interface{}) bool { 16 | return a.(*record).key < b.(*record).key 17 | } 18 | 19 | type RecordSlice []record 20 | 21 | func (s *RecordSlice) Len() int { 22 | return len(*s) 23 | } 24 | 25 | func (s *RecordSlice) Swap(i, j int) { 26 | (*s)[i], (*s)[j] = (*s)[j], (*s)[i] 27 | } 28 | 29 | func (s *RecordSlice) Less(i, j int) bool { 30 | return (*s)[i].key < (*s)[j].key 31 | } 32 | 33 | func makeVector(size int, shape string) (v records) { 34 | v = make(records, size) 35 | switch shape { 36 | 37 | case "xor": 38 | for i := 0; i < size; i++ { 39 | v[i] = &record{0xff & (i ^ 0xab), i} 40 | } 41 | 42 | case "sorted": 43 | for i := 0; i < size; i++ { 44 | v[i] = &record{i, i} 45 | } 46 | 47 | case "revsorted": 48 | for i := 0; i < size; i++ { 49 | v[i] = &record{size - i, i} 50 | } 51 | 52 | case "random": 53 | rand.Seed(1) 54 | 55 | for i := 0; i < size; i++ { 56 | v[i] = &record{rand.Int(), i} 57 | } 58 | 59 | default: 60 | panic(shape) 61 | } 62 | 63 | return v 64 | } 65 | 66 | func makeRecords(size int, shape string) (v RecordSlice) { 67 | v = make(RecordSlice, size) 68 | switch shape { 69 | 70 | case "xor": 71 | for i := 0; i < size; i++ { 72 | v[i] = record{0xff & (i ^ 0xab), i} 73 | } 74 | 75 | case "sorted": 76 | for i := 0; i < size; i++ { 77 | v[i] = record{i, i} 78 | } 79 | 80 | case "revsorted": 81 | for i := 0; i < size; i++ { 82 | v[i] = record{size - i, i} 83 | } 84 | 85 | case "random": 86 | rand.Seed(1) 87 | 88 | for i := 0; i < size; i++ { 89 | v[i] = record{rand.Int(), i} 90 | } 91 | 92 | default: 93 | panic(shape) 94 | } 95 | 96 | return v 97 | } 98 | 99 | func benchmarkTimsort(b *testing.B, size int, shape string) { 100 | b.StopTimer() 101 | 102 | for j := 0; j < b.N; j++ { 103 | v := makeVector(size, shape) 104 | 105 | b.StartTimer() 106 | err := Sort(v, LessThanByKey) 107 | b.StopTimer() 108 | if err != nil { 109 | b.Fatalf("Sort: %v", err) 110 | } 111 | } 112 | } 113 | 114 | func benchmarkTimsortInterface(b *testing.B, size int, shape string) { 115 | b.StopTimer() 116 | 117 | for j := 0; j < b.N; j++ { 118 | v := makeRecords(size, shape) 119 | 120 | b.StartTimer() 121 | err := TimSort(&v) 122 | b.StopTimer() 123 | if err != nil { 124 | b.Fatalf("TimSort: %v", err) 125 | } 126 | } 127 | } 128 | 129 | func benchmarkStandardSort(b *testing.B, size int, shape string) { 130 | b.StopTimer() 131 | 132 | for j := 0; j < b.N; j++ { 133 | v := makeRecords(size, shape) 134 | 135 | b.StartTimer() 136 | sort.Stable(&v) 137 | b.StopTimer() 138 | } 139 | } 140 | 141 | func BenchmarkTimsortXor100(b *testing.B) { 142 | benchmarkTimsort(b, 100, "xor") 143 | } 144 | 145 | func BenchmarkTimsortInterXor100(b *testing.B) { 146 | benchmarkTimsortInterface(b, 100, "xor") 147 | } 148 | 149 | func BenchmarkStandardSortXor100(b *testing.B) { 150 | benchmarkStandardSort(b, 100, "xor") 151 | } 152 | 153 | func BenchmarkTimsortSorted100(b *testing.B) { 154 | benchmarkTimsort(b, 100, "sorted") 155 | } 156 | 157 | func BenchmarkTimsortInterSorted100(b *testing.B) { 158 | benchmarkTimsortInterface(b, 100, "sorted") 159 | } 160 | 161 | func BenchmarkStandardSortSorted100(b *testing.B) { 162 | benchmarkStandardSort(b, 100, "sorted") 163 | } 164 | 165 | func BenchmarkTimsortRevSorted100(b *testing.B) { 166 | benchmarkTimsort(b, 100, "revsorted") 167 | } 168 | 169 | func BenchmarkTimsortInterRevSorted100(b *testing.B) { 170 | benchmarkTimsortInterface(b, 100, "revsorted") 171 | } 172 | 173 | func BenchmarkStandardSortRevSorted100(b *testing.B) { 174 | benchmarkStandardSort(b, 100, "revsorted") 175 | } 176 | 177 | func BenchmarkTimsortRandom100(b *testing.B) { 178 | benchmarkTimsort(b, 100, "random") 179 | } 180 | 181 | func BenchmarkTimsortInterRandom100(b *testing.B) { 182 | benchmarkTimsortInterface(b, 100, "random") 183 | } 184 | 185 | func BenchmarkStandardSortRandom100(b *testing.B) { 186 | benchmarkStandardSort(b, 100, "random") 187 | } 188 | 189 | func BenchmarkTimsortXor1K(b *testing.B) { 190 | benchmarkTimsort(b, 1024, "xor") 191 | } 192 | 193 | func BenchmarkTimsortInterXor1K(b *testing.B) { 194 | benchmarkTimsortInterface(b, 1024, "xor") 195 | } 196 | 197 | func BenchmarkStandardSortXor1K(b *testing.B) { 198 | benchmarkStandardSort(b, 1024, "xor") 199 | } 200 | 201 | func BenchmarkTimsortSorted1K(b *testing.B) { 202 | benchmarkTimsort(b, 1024, "sorted") 203 | } 204 | 205 | func BenchmarkTimsortInterSorted1K(b *testing.B) { 206 | benchmarkTimsortInterface(b, 1024, "sorted") 207 | } 208 | 209 | func BenchmarkStandardSortSorted1K(b *testing.B) { 210 | benchmarkStandardSort(b, 1024, "sorted") 211 | } 212 | 213 | func BenchmarkTimsortRevSorted1K(b *testing.B) { 214 | benchmarkTimsort(b, 1024, "revsorted") 215 | } 216 | 217 | func BenchmarkTimsortInterRevSorted1K(b *testing.B) { 218 | benchmarkTimsortInterface(b, 1024, "revsorted") 219 | } 220 | 221 | func BenchmarkStandardSortRevSorted1K(b *testing.B) { 222 | benchmarkStandardSort(b, 1024, "revsorted") 223 | } 224 | 225 | func BenchmarkTimsortRandom1K(b *testing.B) { 226 | benchmarkTimsort(b, 1024, "random") 227 | } 228 | 229 | func BenchmarkTimsortInterRandom1K(b *testing.B) { 230 | benchmarkTimsortInterface(b, 1024, "random") 231 | } 232 | 233 | func BenchmarkStandardSortRandom1K(b *testing.B) { 234 | benchmarkStandardSort(b, 1024, "random") 235 | } 236 | 237 | func BenchmarkTimsortXor1M(b *testing.B) { 238 | benchmarkTimsort(b, 1024*1024, "xor") 239 | } 240 | 241 | func BenchmarkTimsortInterXor1M(b *testing.B) { 242 | benchmarkTimsortInterface(b, 1024*1024, "xor") 243 | } 244 | 245 | func BenchmarkStandardSortXor1M(b *testing.B) { 246 | benchmarkStandardSort(b, 1024*1024, "xor") 247 | } 248 | 249 | func BenchmarkTimsortSorted1M(b *testing.B) { 250 | benchmarkTimsort(b, 1024*1024, "sorted") 251 | } 252 | 253 | func BenchmarkTimsortInterSorted1M(b *testing.B) { 254 | benchmarkTimsortInterface(b, 1024*1024, "sorted") 255 | } 256 | 257 | func BenchmarkStandardSortSorted1M(b *testing.B) { 258 | benchmarkStandardSort(b, 1024*1024, "sorted") 259 | } 260 | 261 | func BenchmarkTimsortRevSorted1M(b *testing.B) { 262 | benchmarkTimsort(b, 1024*1024, "revsorted") 263 | } 264 | 265 | func BenchmarkTimsortInterRevSorted1M(b *testing.B) { 266 | benchmarkTimsortInterface(b, 1024*1024, "revsorted") 267 | } 268 | 269 | func BenchmarkStandardSortRevSorted1M(b *testing.B) { 270 | benchmarkStandardSort(b, 1024*1024, "revsorted") 271 | } 272 | 273 | func BenchmarkTimsortRandom1M(b *testing.B) { 274 | benchmarkTimsort(b, 1024*1024, "random") 275 | } 276 | 277 | func BenchmarkTimsortInterRandom1M(b *testing.B) { 278 | benchmarkTimsortInterface(b, 1024*1024, "random") 279 | } 280 | 281 | func BenchmarkStandardSortRandom1M(b *testing.B) { 282 | benchmarkStandardSort(b, 1024*1024, "random") 283 | } 284 | -------------------------------------------------------------------------------- /benchint_test.go: -------------------------------------------------------------------------------- 1 | package timsort 2 | 3 | import ( 4 | "math/rand" 5 | "sort" 6 | "testing" 7 | ) 8 | 9 | type ints []int 10 | 11 | func (p *ints) Len() int { return len(*p) } 12 | func (p *ints) Less(i, j int) bool { return (*p)[i] < (*p)[j] } 13 | func (p *ints) Swap(i, j int) { (*p)[i], (*p)[j] = (*p)[j], (*p)[i] } 14 | 15 | func LessThanInt(a, b int) bool { 16 | return a < b 17 | } 18 | 19 | func makeInts(size int, shape string) (v ints) { 20 | v = make(ints, 0, size) 21 | switch shape { 22 | 23 | case "xor": 24 | for i := 0; i < size; i++ { 25 | v = append(v, 0xff&(i^0xab)) 26 | } 27 | 28 | case "sorted": 29 | for i := 0; i < size; i++ { 30 | v = append(v, i) 31 | } 32 | 33 | case "revsorted": 34 | for i := 0; i < size; i++ { 35 | v = append(v, size-i) 36 | } 37 | 38 | case "random": 39 | rand.Seed(1) 40 | 41 | for i := 0; i < size; i++ { 42 | v = append(v, rand.Int()) 43 | } 44 | 45 | default: 46 | panic(shape) 47 | } 48 | 49 | return v 50 | } 51 | 52 | func benchmarkTimsortI(b *testing.B, size int, shape string) { 53 | b.StopTimer() 54 | 55 | for j := 0; j < b.N; j++ { 56 | v := makeInts(size, shape) 57 | 58 | b.StartTimer() 59 | err := Ints(v, LessThanInt) 60 | b.StopTimer() 61 | if err != nil { 62 | b.Fatalf("Ints: %v", err) 63 | } 64 | } 65 | } 66 | 67 | func benchmarkStandardSortI(b *testing.B, size int, shape string) { 68 | b.StopTimer() 69 | 70 | for j := 0; j < b.N; j++ { 71 | v := makeInts(size, shape) 72 | 73 | b.StartTimer() 74 | sort.Sort(&v) 75 | b.StopTimer() 76 | } 77 | } 78 | 79 | func BenchmarkTimsortIXor100(b *testing.B) { 80 | benchmarkTimsortI(b, 100, "xor") 81 | } 82 | 83 | func BenchmarkStandardSortIXor100(b *testing.B) { 84 | benchmarkStandardSortI(b, 100, "xor") 85 | } 86 | 87 | func BenchmarkTimsortISorted100(b *testing.B) { 88 | benchmarkTimsortI(b, 100, "sorted") 89 | } 90 | 91 | func BenchmarkStandardSortISorted100(b *testing.B) { 92 | benchmarkStandardSortI(b, 100, "sorted") 93 | } 94 | 95 | func BenchmarkTimsortIRevSorted100(b *testing.B) { 96 | benchmarkTimsortI(b, 100, "revsorted") 97 | } 98 | 99 | func BenchmarkStandardSortIRevSorted100(b *testing.B) { 100 | benchmarkStandardSortI(b, 100, "revsorted") 101 | } 102 | 103 | func BenchmarkTimsortIRandom100(b *testing.B) { 104 | benchmarkTimsortI(b, 100, "random") 105 | } 106 | 107 | func BenchmarkStandardSortIRandom100(b *testing.B) { 108 | benchmarkStandardSortI(b, 100, "random") 109 | } 110 | 111 | func BenchmarkTimsortIXor1K(b *testing.B) { 112 | benchmarkTimsortI(b, 1024, "xor") 113 | } 114 | 115 | func BenchmarkStandardSortIXor1K(b *testing.B) { 116 | benchmarkStandardSortI(b, 1024, "xor") 117 | } 118 | 119 | func BenchmarkTimsortISorted1K(b *testing.B) { 120 | benchmarkTimsortI(b, 1024, "sorted") 121 | } 122 | 123 | func BenchmarkStandardSortISorted1K(b *testing.B) { 124 | benchmarkStandardSortI(b, 1024, "sorted") 125 | } 126 | 127 | func BenchmarkTimsortIRevSorted1K(b *testing.B) { 128 | benchmarkTimsortI(b, 1024, "revsorted") 129 | } 130 | 131 | func BenchmarkStandardSortIRevSorted1K(b *testing.B) { 132 | benchmarkStandardSortI(b, 1024, "revsorted") 133 | } 134 | 135 | func BenchmarkTimsortIRandom1K(b *testing.B) { 136 | benchmarkTimsortI(b, 1024, "random") 137 | } 138 | 139 | func BenchmarkStandardSortIRandom1K(b *testing.B) { 140 | benchmarkStandardSortI(b, 1024, "random") 141 | } 142 | 143 | func BenchmarkTimsortIXor1M(b *testing.B) { 144 | benchmarkTimsortI(b, 1024*1024, "xor") 145 | } 146 | 147 | func BenchmarkStandardSortIXor1M(b *testing.B) { 148 | benchmarkStandardSortI(b, 1024*1024, "xor") 149 | } 150 | 151 | func BenchmarkTimsortISorted1M(b *testing.B) { 152 | benchmarkTimsortI(b, 1024*1024, "sorted") 153 | } 154 | 155 | func BenchmarkStandardSortISorted1M(b *testing.B) { 156 | benchmarkStandardSortI(b, 1024*1024, "sorted") 157 | } 158 | 159 | func BenchmarkTimsortIRevSorted1M(b *testing.B) { 160 | benchmarkTimsortI(b, 1024*1024, "revsorted") 161 | } 162 | 163 | func BenchmarkStandardSortIRevSorted1M(b *testing.B) { 164 | benchmarkStandardSortI(b, 1024*1024, "revsorted") 165 | } 166 | 167 | func BenchmarkTimsortIRandom1M(b *testing.B) { 168 | benchmarkTimsortI(b, 1024*1024, "random") 169 | } 170 | 171 | func BenchmarkStandardSortIRandom1M(b *testing.B) { 172 | benchmarkStandardSortI(b, 1024*1024, "random") 173 | } 174 | -------------------------------------------------------------------------------- /benchstring_test.go: -------------------------------------------------------------------------------- 1 | package timsort 2 | 3 | import ( 4 | "math/rand" 5 | "sort" 6 | "strconv" 7 | "testing" 8 | ) 9 | 10 | func makeStrings(size int, shape string) (v sort.StringSlice) { 11 | v = make(sort.StringSlice, 0, size) 12 | switch shape { 13 | 14 | case "xor": 15 | for i := 0; i < size; i++ { 16 | v = append(v, strconv.Itoa(0xff&(i^0xab))) 17 | } 18 | 19 | case "sorted": 20 | for i := 0; i < size; i++ { 21 | v = append(v, strconv.Itoa(i)) 22 | } 23 | 24 | case "revsorted": 25 | for i := 0; i < size; i++ { 26 | v = append(v, strconv.Itoa(size-i)) 27 | } 28 | 29 | case "random": 30 | rand.Seed(1) 31 | 32 | for i := 0; i < size; i++ { 33 | v = append(v, strconv.Itoa(rand.Int())) 34 | } 35 | 36 | default: 37 | panic(shape) 38 | } 39 | 40 | return v 41 | } 42 | 43 | func benchmarkTimsortStr(b *testing.B, size int, shape string) { 44 | b.StopTimer() 45 | 46 | for j := 0; j < b.N; j++ { 47 | v := makeStrings(size, shape) 48 | 49 | b.StartTimer() 50 | err := TimSort(v) 51 | b.StopTimer() 52 | if err != nil { 53 | b.Fatalf("TimSort: %v", err) 54 | } 55 | } 56 | } 57 | 58 | func benchmarkStandardSortStr(b *testing.B, size int, shape string) { 59 | b.StopTimer() 60 | 61 | for j := 0; j < b.N; j++ { 62 | v := makeStrings(size, shape) 63 | 64 | b.StartTimer() 65 | sort.Sort(&v) 66 | b.StopTimer() 67 | } 68 | } 69 | 70 | func BenchmarkTimsortStrXor100(b *testing.B) { 71 | benchmarkTimsortStr(b, 100, "xor") 72 | } 73 | 74 | func BenchmarkStandardSortStrXor100(b *testing.B) { 75 | benchmarkStandardSortStr(b, 100, "xor") 76 | } 77 | 78 | func BenchmarkTimsortStrSorted100(b *testing.B) { 79 | benchmarkTimsortStr(b, 100, "sorted") 80 | } 81 | 82 | func BenchmarkStandardSortStrSorted100(b *testing.B) { 83 | benchmarkStandardSortStr(b, 100, "sorted") 84 | } 85 | 86 | func BenchmarkTimsortStrRevSorted100(b *testing.B) { 87 | benchmarkTimsortStr(b, 100, "revsorted") 88 | } 89 | 90 | func BenchmarkStandardSortStrRevSorted100(b *testing.B) { 91 | benchmarkStandardSortStr(b, 100, "revsorted") 92 | } 93 | 94 | func BenchmarkTimsortStrRandom100(b *testing.B) { 95 | benchmarkTimsortStr(b, 100, "random") 96 | } 97 | 98 | func BenchmarkStandardSortStrRandom100(b *testing.B) { 99 | benchmarkStandardSortStr(b, 100, "random") 100 | } 101 | 102 | func BenchmarkTimsortStrXor1K(b *testing.B) { 103 | benchmarkTimsortStr(b, 1024, "xor") 104 | } 105 | 106 | func BenchmarkStandardSortStrXor1K(b *testing.B) { 107 | benchmarkStandardSortStr(b, 1024, "xor") 108 | } 109 | 110 | func BenchmarkTimsortStrSorted1K(b *testing.B) { 111 | benchmarkTimsortStr(b, 1024, "sorted") 112 | } 113 | 114 | func BenchmarkStandardSortStrSorted1K(b *testing.B) { 115 | benchmarkStandardSortStr(b, 1024, "sorted") 116 | } 117 | 118 | func BenchmarkTimsortStrRevSorted1K(b *testing.B) { 119 | benchmarkTimsortStr(b, 1024, "revsorted") 120 | } 121 | 122 | func BenchmarkStandardSortStrRevSorted1K(b *testing.B) { 123 | benchmarkStandardSortStr(b, 1024, "revsorted") 124 | } 125 | 126 | func BenchmarkTimsortStrRandom1K(b *testing.B) { 127 | benchmarkTimsortStr(b, 1024, "random") 128 | } 129 | 130 | func BenchmarkStandardSortStrRandom1K(b *testing.B) { 131 | benchmarkStandardSortStr(b, 1024, "random") 132 | } 133 | 134 | func BenchmarkTimsortStrXor1M(b *testing.B) { 135 | benchmarkTimsortStr(b, 1024*1024, "xor") 136 | } 137 | 138 | func BenchmarkStandardSortStrXor1M(b *testing.B) { 139 | benchmarkStandardSortStr(b, 1024*1024, "xor") 140 | } 141 | 142 | func BenchmarkTimsortStrSorted1M(b *testing.B) { 143 | benchmarkTimsortStr(b, 1024*1024, "sorted") 144 | } 145 | 146 | func BenchmarkStandardSortStrSorted1M(b *testing.B) { 147 | benchmarkStandardSortStr(b, 1024*1024, "sorted") 148 | } 149 | 150 | func BenchmarkTimsortStrRevSorted1M(b *testing.B) { 151 | benchmarkTimsortStr(b, 1024*1024, "revsorted") 152 | } 153 | 154 | func BenchmarkStandardSortStrRevSorted1M(b *testing.B) { 155 | benchmarkStandardSortStr(b, 1024*1024, "revsorted") 156 | } 157 | 158 | func BenchmarkTimsortStrRandom1M(b *testing.B) { 159 | benchmarkTimsortStr(b, 1024*1024, "random") 160 | } 161 | 162 | func BenchmarkStandardSortStrRandom1M(b *testing.B) { 163 | benchmarkStandardSortStr(b, 1024*1024, "random") 164 | } 165 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | ignore: 2 | - "*.go" # ignore old v1 for coverage; instead check v2 3 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/psilva261/timsort 2 | 3 | go 1.13 4 | -------------------------------------------------------------------------------- /scripts/benchmark_table.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o pipefail 5 | set -o nounset 6 | # set -o xtrace 7 | 8 | 9 | sortings=( Sorted RevSorted Xor Random ) 10 | amounts=( 100 1K 1M ) 11 | 12 | for amount in "${amounts[@]}" 13 | do 14 | for sorting in "${sortings[@]}" 15 | do 16 | printf '%-14s' $sorting$amount: 17 | for n in {1..3} 18 | do 19 | printf '%-14s' $(go test -test.bench=Timsort$sorting$amount | grep Benchmark | awk '{print $3}') 20 | printf '%-14s' '('$(go test -test.bench=StandardSort$sorting$amount | grep Benchmark | awk '{print $3}')')' 21 | done 22 | echo 23 | done 24 | echo 25 | done 26 | 27 | -------------------------------------------------------------------------------- /scripts/benchmarkint_table.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o pipefail 5 | set -o nounset 6 | # set -o xtrace 7 | 8 | 9 | sortings=( Sorted RevSorted Xor Random ) 10 | amounts=( 100 1K 1M ) 11 | 12 | for amount in "${amounts[@]}" 13 | do 14 | for sorting in "${sortings[@]}" 15 | do 16 | printf '%-14s' $sorting$amount: 17 | for n in {1..3} 18 | do 19 | printf '%-14s' $(go test -test.bench=TimsortI$sorting$amount | grep Benchmark | awk '{print $3}') 20 | printf '%-14s' '('$(go test -test.bench=StandardSortI$sorting$amount | grep Benchmark | awk '{print $3}')')' 21 | done 22 | echo 23 | done 24 | echo 25 | done 26 | 27 | -------------------------------------------------------------------------------- /timsort.go: -------------------------------------------------------------------------------- 1 | // Package timsort provides fast stable sort, uses external comparator. 2 | // 3 | // A stable, adaptive, iterative mergesort that requires far fewer than 4 | // n lg(n) comparisons when running on partially sorted arrays, while 5 | // offering performance comparable to a traditional mergesort when run 6 | // on random arrays. Like all proper mergesorts, this sort is stable and 7 | // runs O(n log n) time (worst case). In the worst case, this sort requires 8 | // temporary storage space for n/2 object references; in the best case, 9 | // it requires only a small constant amount of space. 10 | // 11 | // This implementation was derived from Java's TimSort object by Josh Bloch, 12 | // which, in turn, was based on the original code by Tim Peters: 13 | // 14 | // http://svn.python.org/projects/python/trunk/Objects/listsort.txt 15 | // 16 | // Mike K. 17 | package timsort 18 | 19 | import ( 20 | "errors" 21 | "fmt" 22 | ) 23 | 24 | const ( 25 | /** 26 | * This is the minimum sized sequence that will be merged. Shorter 27 | * sequences will be lengthened by calling binarySort. If the entire 28 | * array is less than this length, no merges will be performed. 29 | * 30 | * This constant should be a power of two. It was 64 in Tim Peter's C 31 | * implementation, but 32 was empirically determined to work better in 32 | * this implementation. In the unlikely event that you set this constant 33 | * to be a number that's not a power of two, you'll need to change the 34 | * {@link #minRunLength} computation. 35 | * 36 | * If you decrease this constant, you must change the stackLen 37 | * computation in the TimSort constructor, or you risk an 38 | * ArrayOutOfBounds exception. See listsort.txt for a discussion 39 | * of the minimum stack length required as a function of the length 40 | * of the array being sorted and the minimum merge sequence length. 41 | */ 42 | minMerge = 32 43 | // mk: tried higher MIN_MERGE and got slower sorting (348->375) 44 | // c_MIN_MERGE = 64 45 | 46 | /** 47 | * When we get into galloping mode, we stay there until both runs win less 48 | * often than cminGallop consecutive times. 49 | */ 50 | minGallop = 7 51 | 52 | /** 53 | * Maximum initial size of tmp array, which is used for merging. The array 54 | * can grow to accommodate demand. 55 | * 56 | * Unlike Tim's original C version, we do not allocate this much storage 57 | * when sorting smaller arrays. This change was required for performance. 58 | */ 59 | initialTmpStorageLength = 256 60 | ) 61 | 62 | // LessThan is Delegate type that sorting uses as a comparator 63 | type LessThan func(a, b interface{}) bool 64 | 65 | type timSortHandler struct { 66 | 67 | /** 68 | * The array being sorted. 69 | */ 70 | a []interface{} 71 | 72 | /** 73 | * The comparator for this sort. 74 | */ 75 | lt LessThan 76 | 77 | /** 78 | * This controls when we get *into* galloping mode. It is initialized 79 | * to cminGallop. The mergeLo and mergeHi methods nudge it higher for 80 | * random data, and lower for highly structured data. 81 | */ 82 | minGallop int 83 | 84 | /** 85 | * Temp storage for merges. 86 | */ 87 | tmp []interface{} // Actual runtime type will be Object[], regardless of T 88 | 89 | /** 90 | * A stack of pending runs yet to be merged. Run i starts at 91 | * address base[i] and extends for len[i] elements. It's always 92 | * true (so long as the indices are in bounds) that: 93 | * 94 | * runBase[i] + runLen[i] == runBase[i + 1] 95 | * 96 | * so we could cut the storage for this, but it's a minor amount, 97 | * and keeping all the info explicit simplifies the code. 98 | */ 99 | stackSize int // Number of pending runs on stack 100 | runBase []int 101 | runLen []int 102 | } 103 | 104 | /** 105 | * Creates a TimSort instance to maintain the state of an ongoing sort. 106 | * 107 | * @param a the array to be sorted 108 | * @param c the comparator to determine the order of the sort 109 | */ 110 | func newTimSort(a []interface{}, lt LessThan) (h *timSortHandler) { 111 | h = new(timSortHandler) 112 | 113 | h.a = a 114 | h.lt = lt 115 | h.minGallop = minGallop 116 | h.stackSize = 0 117 | 118 | // Allocate temp storage (which may be increased later if necessary) 119 | len := len(a) 120 | 121 | tmpSize := initialTmpStorageLength 122 | if len < 2*tmpSize { 123 | tmpSize = len / 2 124 | } 125 | 126 | h.tmp = make([]interface{}, tmpSize) 127 | 128 | /* 129 | * Allocate runs-to-be-merged stack (which cannot be expanded). The 130 | * stack length requirements are described in listsort.txt. The C 131 | * version always uses the same stack length (85), but this was 132 | * measured to be too expensive when sorting "mid-sized" arrays (e.g., 133 | * 100 elements) in Java. Therefore, we use smaller (but sufficiently 134 | * large) stack lengths for smaller arrays. The "magic numbers" in the 135 | * computation below must be changed if c_MIN_MERGE is decreased. See 136 | * the c_MIN_MERGE declaration above for more information. 137 | */ 138 | // mk: confirmed that for small sorts this optimization gives measurable (albeit small) 139 | // performance enhancement 140 | stackLen := 40 141 | if len < 120 { 142 | stackLen = 5 143 | } else if len < 1542 { 144 | stackLen = 10 145 | } else if len < 119151 { 146 | stackLen = 19 147 | } 148 | 149 | h.runBase = make([]int, stackLen) 150 | h.runLen = make([]int, stackLen) 151 | 152 | return h 153 | } 154 | 155 | // Sort an array using the provided comparator 156 | func Sort(a []interface{}, lt LessThan) (err error) { 157 | lo := 0 158 | hi := len(a) 159 | nRemaining := hi 160 | 161 | if nRemaining < 2 { 162 | return // Arrays of size 0 and 1 are always sorted 163 | } 164 | 165 | // If array is small, do a "mini-TimSort" with no merges 166 | if nRemaining < minMerge { 167 | initRunLen, err := countRunAndMakeAscending(a, lo, hi, lt) 168 | if err != nil { 169 | return err 170 | } 171 | 172 | return binarySort(a, lo, hi, lo+initRunLen, lt) 173 | } 174 | 175 | /** 176 | * March over the array once, left to right, finding natural runs, 177 | * extending short natural runs to minRun elements, and merging runs 178 | * to maintain stack invariant. 179 | */ 180 | 181 | ts := newTimSort(a, lt) 182 | minRun, err := minRunLength(nRemaining) 183 | if err != nil { 184 | return 185 | } 186 | for { 187 | // Identify next run 188 | runLen, err := countRunAndMakeAscending(a, lo, hi, lt) 189 | if err != nil { 190 | return err 191 | } 192 | 193 | // If run is short, extend to min(minRun, nRemaining) 194 | if runLen < minRun { 195 | force := minRun 196 | if nRemaining <= minRun { 197 | force = nRemaining 198 | } 199 | if err = binarySort(a, lo, lo+force, lo+runLen, lt); err != nil { 200 | return err 201 | } 202 | runLen = force 203 | } 204 | 205 | // Push run onto pending-run stack, and maybe merge 206 | ts.pushRun(lo, runLen) 207 | if err = ts.mergeCollapse(); err != nil { 208 | return err 209 | } 210 | 211 | // Advance to find next run 212 | lo += runLen 213 | nRemaining -= runLen 214 | if nRemaining == 0 { 215 | break 216 | } 217 | } 218 | 219 | // Merge all remaining runs to complete sort 220 | if lo != hi { 221 | return errors.New("lo must equal hi") 222 | } 223 | 224 | if err = ts.mergeForceCollapse(); err != nil { 225 | return 226 | } 227 | if ts.stackSize != 1 { 228 | return errors.New("ts.stackSize != 1") 229 | } 230 | return 231 | } 232 | 233 | /** 234 | * Sorts the specified portion of the specified array using a binary 235 | * insertion sort. This is the best method for sorting small numbers 236 | * of elements. It requires O(n log n) compares, but O(n^2) data 237 | * movement (worst case). 238 | * 239 | * If the initial part of the specified range is already sorted, 240 | * this method can take advantage of it: the method assumes that the 241 | * elements from index {@code lo}, inclusive, to {@code start}, 242 | * exclusive are already sorted. 243 | * 244 | * @param a the array in which a range is to be sorted 245 | * @param lo the index of the first element in the range to be sorted 246 | * @param hi the index after the last element in the range to be sorted 247 | * @param start the index of the first element in the range that is 248 | * not already known to be sorted (@code lo <= start <= hi} 249 | * @param c comparator to used for the sort 250 | */ 251 | func binarySort(a []interface{}, lo, hi, start int, lt LessThan) (err error) { 252 | if lo > start || start > hi { 253 | return errors.New("lo <= start && start <= hi") 254 | } 255 | 256 | if start == lo { 257 | start++ 258 | } 259 | 260 | for ; start < hi; start++ { 261 | pivot := a[start] 262 | 263 | // Set left (and right) to the index where a[start] (pivot) belongs 264 | left := lo 265 | right := start 266 | 267 | if left > right { 268 | return errors.New("left <= right") 269 | } 270 | 271 | /* 272 | * Invariants: 273 | * pivot >= all in [lo, left). 274 | * pivot < all in [right, start). 275 | */ 276 | for left < right { 277 | mid := int(uint(left+right) >> 1) 278 | if lt(pivot, a[mid]) { 279 | right = mid 280 | } else { 281 | left = mid + 1 282 | } 283 | } 284 | 285 | if left != right { 286 | return errors.New("left == right") 287 | } 288 | 289 | /* 290 | * The invariants still hold: pivot >= all in [lo, left) and 291 | * pivot < all in [left, start), so pivot belongs at left. Note 292 | * that if there are elements equal to pivot, left points to the 293 | * first slot after them -- that's why this sort is stable. 294 | * Slide elements over to make room to make room for pivot. 295 | */ 296 | n := start - left // The number of elements to move 297 | // just an optimization for copy in default case 298 | if n <= 2 { 299 | if n == 2 { 300 | a[left+2] = a[left+1] 301 | } 302 | if n > 0 { 303 | a[left+1] = a[left] 304 | } 305 | } else { 306 | copy(a[left+1:], a[left:left+n]) 307 | } 308 | a[left] = pivot 309 | } 310 | return 311 | } 312 | 313 | /** 314 | * Returns the length of the run beginning at the specified position in 315 | * the specified array and reverses the run if it is descending (ensuring 316 | * that the run will always be ascending when the method returns). 317 | * 318 | * A run is the longest ascending sequence with: 319 | * 320 | * a[lo] <= a[lo + 1] <= a[lo + 2] <= ... 321 | * 322 | * or the longest descending sequence with: 323 | * 324 | * a[lo] > a[lo + 1] > a[lo + 2] > ... 325 | * 326 | * For its intended use in a stable mergesort, the strictness of the 327 | * definition of "descending" is needed so that the call can safely 328 | * reverse a descending sequence without violating stability. 329 | * 330 | * @param a the array in which a run is to be counted and possibly reversed 331 | * @param lo index of the first element in the run 332 | * @param hi index after the last element that may be contained in the run. 333 | It is required that @code{lo < hi}. 334 | * @param c the comparator to used for the sort 335 | * @return the length of the run beginning at the specified position in 336 | * the specified array 337 | */ 338 | func countRunAndMakeAscending(a []interface{}, lo, hi int, lt LessThan) (int, error) { 339 | 340 | if lo >= hi { 341 | return 0, errors.New("lo < hi") 342 | } 343 | 344 | runHi := lo + 1 345 | if runHi == hi { 346 | return 1, nil 347 | } 348 | 349 | // Find end of run, and reverse range if descending 350 | if lt(a[runHi], a[lo]) { // Descending 351 | runHi++ 352 | 353 | for runHi < hi && lt(a[runHi], a[runHi-1]) { 354 | runHi++ 355 | } 356 | reverseRange(a, lo, runHi) 357 | } else { // Ascending 358 | for runHi < hi && !lt(a[runHi], a[runHi-1]) { 359 | runHi++ 360 | } 361 | } 362 | 363 | return runHi - lo, nil 364 | } 365 | 366 | /** 367 | * Reverse the specified range of the specified array. 368 | * 369 | * @param a the array in which a range is to be reversed 370 | * @param lo the index of the first element in the range to be reversed 371 | * @param hi the index after the last element in the range to be reversed 372 | */ 373 | func reverseRange(a []interface{}, lo, hi int) { 374 | hi-- 375 | for lo < hi { 376 | a[lo], a[hi] = a[hi], a[lo] 377 | lo++ 378 | hi-- 379 | } 380 | } 381 | 382 | /** 383 | * Returns the minimum acceptable run length for an array of the specified 384 | * length. Natural runs shorter than this will be extended with 385 | * {@link #binarySort}. 386 | * 387 | * Roughly speaking, the computation is: 388 | * 389 | * If n < c_MIN_MERGE, return n (it's too small to bother with fancy stuff). 390 | * Else if n is an exact power of 2, return c_MIN_MERGE/2. 391 | * Else return an int k, c_MIN_MERGE/2 <= k <= c_MIN_MERGE, such that n/k 392 | * is close to, but strictly less than, an exact power of 2. 393 | * 394 | * For the rationale, see listsort.txt. 395 | * 396 | * @param n the length of the array to be sorted 397 | * @return the length of the minimum run to be merged 398 | */ 399 | func minRunLength(n int) (int, error) { 400 | if n < 0 { 401 | return 0, errors.New("n >= 0") 402 | } 403 | r := 0 // Becomes 1 if any 1 bits are shifted off 404 | for n >= minMerge { 405 | r |= (n & 1) 406 | n >>= 1 407 | } 408 | return n + r, nil 409 | } 410 | 411 | /** 412 | * Pushes the specified run onto the pending-run stack. 413 | * 414 | * @param runBase index of the first element in the run 415 | * @param runLen the number of elements in the run 416 | */ 417 | func (h *timSortHandler) pushRun(runBase, runLen int) { 418 | h.runBase[h.stackSize] = runBase 419 | h.runLen[h.stackSize] = runLen 420 | h.stackSize++ 421 | } 422 | 423 | /** 424 | * Examines the stack of runs waiting to be merged and merges adjacent runs 425 | * until the stack invariants are reestablished: 426 | * 427 | * 1. runLen[i - 3] > runLen[i - 2] + runLen[i - 1] 428 | * 2. runLen[i - 2] > runLen[i - 1] 429 | * 430 | * This method is called each time a new run is pushed onto the stack, 431 | * so the invariants are guaranteed to hold for i < stackSize upon 432 | * entry to the method. 433 | */ 434 | func (h *timSortHandler) mergeCollapse() (err error) { 435 | for h.stackSize > 1 { 436 | n := h.stackSize - 2 437 | if (n > 0 && h.runLen[n-1] <= h.runLen[n]+h.runLen[n+1]) || 438 | (n > 1 && h.runLen[n-2] <= h.runLen[n-1]+h.runLen[n]) { 439 | if h.runLen[n-1] < h.runLen[n+1] { 440 | n-- 441 | } 442 | if err = h.mergeAt(n); err != nil { 443 | return 444 | } 445 | } else if h.runLen[n] <= h.runLen[n+1] { 446 | if err = h.mergeAt(n); err != nil { 447 | return 448 | } 449 | } else { 450 | break // Invariant is established 451 | } 452 | } 453 | return 454 | } 455 | 456 | /** 457 | * Merges all runs on the stack until only one remains. This method is 458 | * called once, to complete the sort. 459 | */ 460 | func (h *timSortHandler) mergeForceCollapse() (err error) { 461 | for h.stackSize > 1 { 462 | n := h.stackSize - 2 463 | if n > 0 && h.runLen[n-1] < h.runLen[n+1] { 464 | n-- 465 | } 466 | if err = h.mergeAt(n); err != nil { 467 | return 468 | } 469 | } 470 | return 471 | } 472 | 473 | /** 474 | * Merges the two runs at stack indices i and i+1. Run i must be 475 | * the penultimate or antepenultimate run on the stack. In other words, 476 | * i must be equal to stackSize-2 or stackSize-3. 477 | * 478 | * @param i stack index of the first of the two runs to merge 479 | */ 480 | func (h *timSortHandler) mergeAt(i int) (err error) { 481 | if h.stackSize < 2 { 482 | return errors.New("stackSize >= 2") 483 | } 484 | 485 | if i < 0 { 486 | return errors.New(" i >= 0") 487 | } 488 | 489 | if i != h.stackSize-2 && i != h.stackSize-3 { 490 | return errors.New("if i == stackSize - 2 || i == stackSize - 3") 491 | } 492 | 493 | base1 := h.runBase[i] 494 | len1 := h.runLen[i] 495 | base2 := h.runBase[i+1] 496 | len2 := h.runLen[i+1] 497 | 498 | if len1 <= 0 || len2 <= 0 { 499 | return errors.New("len1 > 0 && len2 > 0") 500 | } 501 | 502 | if base1+len1 != base2 { 503 | return errors.New("base1 + len1 == base2") 504 | } 505 | 506 | /* 507 | * Record the length of the combined runs; if i is the 3rd-last 508 | * run now, also slide over the last run (which isn't involved 509 | * in this merge). The current run (i+1) goes away in any case. 510 | */ 511 | h.runLen[i] = len1 + len2 512 | if i == h.stackSize-3 { 513 | h.runBase[i+1] = h.runBase[i+2] 514 | h.runLen[i+1] = h.runLen[i+2] 515 | } 516 | h.stackSize-- 517 | 518 | /* 519 | * Find where the first element of run2 goes in run1. Prior elements 520 | * in run1 can be ignored (because they're already in place). 521 | */ 522 | k, err := gallopRight(h.a[base2], h.a, base1, len1, 0, h.lt) 523 | if err != nil { 524 | return err 525 | } 526 | if k < 0 { 527 | return errors.New(" k >= 0;") 528 | } 529 | base1 += k 530 | len1 -= k 531 | if len1 == 0 { 532 | return 533 | } 534 | 535 | /* 536 | * Find where the last element of run1 goes in run2. Subsequent elements 537 | * in run2 can be ignored (because they're already in place). 538 | */ 539 | len2, err = gallopLeft(h.a[base1+len1-1], h.a, base2, len2, len2-1, h.lt) 540 | if err != nil { 541 | return 542 | } 543 | if len2 < 0 { 544 | return errors.New(" len2 >= 0;") 545 | } 546 | if len2 == 0 { 547 | return 548 | } 549 | 550 | // Merge remaining runs, using tmp array with min(len1, len2) elements 551 | if len1 <= len2 { 552 | err = h.mergeLo(base1, len1, base2, len2) 553 | if err != nil { 554 | return fmt.Errorf("mergeLo: %v", err) 555 | } 556 | } else { 557 | err = h.mergeHi(base1, len1, base2, len2) 558 | if err != nil { 559 | return fmt.Errorf("mergeHi: %v", err) 560 | } 561 | } 562 | return 563 | } 564 | 565 | /** 566 | * Locates the position at which to insert the specified key into the 567 | * specified sorted range; if the range contains an element equal to key, 568 | * returns the index of the leftmost equal element. 569 | * 570 | * @param key the key whose insertion point to search for 571 | * @param a the array in which to search 572 | * @param base the index of the first element in the range 573 | * @param len the length of the range; must be > 0 574 | * @param hint the index at which to begin the search, 0 <= hint < n. 575 | * The closer hint is to the result, the faster this method will run. 576 | * @param c the comparator used to order the range, and to search 577 | * @return the int k, 0 <= k <= n such that a[b + k - 1] < key <= a[b + k], 578 | * pretending that a[b - 1] is minus infinity and a[b + n] is infinity. 579 | * In other words, key belongs at index b + k; or in other words, 580 | * the first k elements of a should precede key, and the last n - k 581 | * should follow it. 582 | */ 583 | func gallopLeft(key interface{}, a []interface{}, base, len, hint int, c LessThan) (int, error) { 584 | if len <= 0 || hint < 0 || hint >= len { 585 | return 0, errors.New(" len > 0 && hint >= 0 && hint < len;") 586 | } 587 | lastOfs := 0 588 | ofs := 1 589 | 590 | if c(a[base+hint], key) { 591 | // Gallop right until a[base+hint+lastOfs] < key <= a[base+hint+ofs] 592 | maxOfs := len - hint 593 | for ofs < maxOfs && c(a[base+hint+ofs], key) { 594 | lastOfs = ofs 595 | ofs = (ofs << 1) + 1 596 | if ofs <= 0 { // int overflow 597 | ofs = maxOfs 598 | } 599 | } 600 | if ofs > maxOfs { 601 | ofs = maxOfs 602 | } 603 | 604 | // Make offsets relative to base 605 | lastOfs += hint 606 | ofs += hint 607 | } else { // key <= a[base + hint] 608 | // Gallop left until a[base+hint-ofs] < key <= a[base+hint-lastOfs] 609 | maxOfs := hint + 1 610 | for ofs < maxOfs && !c(a[base+hint-ofs], key) { 611 | lastOfs = ofs 612 | ofs = (ofs << 1) + 1 613 | if ofs <= 0 { // int overflow 614 | ofs = maxOfs 615 | } 616 | } 617 | if ofs > maxOfs { 618 | ofs = maxOfs 619 | } 620 | 621 | // Make offsets relative to base 622 | tmp := lastOfs 623 | lastOfs = hint - ofs 624 | ofs = hint - tmp 625 | } 626 | 627 | if -1 > lastOfs || lastOfs >= ofs || ofs > len { 628 | return 0, errors.New(" -1 <= lastOfs && lastOfs < ofs && ofs <= len;") 629 | } 630 | 631 | /* 632 | * Now a[base+lastOfs] < key <= a[base+ofs], so key belongs somewhere 633 | * to the right of lastOfs but no farther right than ofs. Do a binary 634 | * search, with invariant a[base + lastOfs - 1] < key <= a[base + ofs]. 635 | */ 636 | lastOfs++ 637 | for lastOfs < ofs { 638 | m := lastOfs + (ofs-lastOfs)/2 639 | 640 | if c(a[base+m], key) { 641 | lastOfs = m + 1 // a[base + m] < key 642 | } else { 643 | ofs = m // key <= a[base + m] 644 | } 645 | } 646 | 647 | if lastOfs != ofs { 648 | return 0, errors.New(" lastOfs == ofs") // so a[base + ofs - 1] < key <= a[base + ofs] 649 | } 650 | return ofs, nil 651 | } 652 | 653 | /** 654 | * Like gallopLeft, except that if the range contains an element equal to 655 | * key, gallopRight returns the index after the rightmost equal element. 656 | * 657 | * @param key the key whose insertion point to search for 658 | * @param a the array in which to search 659 | * @param base the index of the first element in the range 660 | * @param len the length of the range; must be > 0 661 | * @param hint the index at which to begin the search, 0 <= hint < n. 662 | * The closer hint is to the result, the faster this method will run. 663 | * @param c the comparator used to order the range, and to search 664 | * @return the int k, 0 <= k <= n such that a[b + k - 1] <= key < a[b + k] 665 | */ 666 | func gallopRight(key interface{}, a []interface{}, base, len, hint int, c LessThan) (int, error) { 667 | if len <= 0 || hint < 0 || hint >= len { 668 | return 0, errors.New(" len > 0 && hint >= 0 && hint < len;") 669 | } 670 | 671 | ofs := 1 672 | lastOfs := 0 673 | if c(key, a[base+hint]) { 674 | // Gallop left until a[b+hint - ofs] <= key < a[b+hint - lastOfs] 675 | maxOfs := hint + 1 676 | for ofs < maxOfs && c(key, a[base+hint-ofs]) { 677 | lastOfs = ofs 678 | ofs = (ofs << 1) + 1 679 | if ofs <= 0 { // int overflow 680 | ofs = maxOfs 681 | } 682 | } 683 | if ofs > maxOfs { 684 | ofs = maxOfs 685 | } 686 | 687 | // Make offsets relative to b 688 | tmp := lastOfs 689 | lastOfs = hint - ofs 690 | ofs = hint - tmp 691 | } else { // a[b + hint] <= key 692 | // Gallop right until a[b+hint + lastOfs] <= key < a[b+hint + ofs] 693 | maxOfs := len - hint 694 | for ofs < maxOfs && !c(key, a[base+hint+ofs]) { 695 | lastOfs = ofs 696 | ofs = (ofs << 1) + 1 697 | if ofs <= 0 { // int overflow 698 | ofs = maxOfs 699 | } 700 | } 701 | if ofs > maxOfs { 702 | ofs = maxOfs 703 | } 704 | 705 | // Make offsets relative to b 706 | lastOfs += hint 707 | ofs += hint 708 | } 709 | if -1 > lastOfs || lastOfs >= ofs || ofs > len { 710 | return 0, errors.New("-1 <= lastOfs && lastOfs < ofs && ofs <= len") 711 | } 712 | 713 | /* 714 | * Now a[b + lastOfs] <= key < a[b + ofs], so key belongs somewhere to 715 | * the right of lastOfs but no farther right than ofs. Do a binary 716 | * search, with invariant a[b + lastOfs - 1] <= key < a[b + ofs]. 717 | */ 718 | lastOfs++ 719 | for lastOfs < ofs { 720 | m := lastOfs + (ofs-lastOfs)/2 721 | 722 | if c(key, a[base+m]) { 723 | ofs = m // key < a[b + m] 724 | } else { 725 | lastOfs = m + 1 // a[b + m] <= key 726 | } 727 | } 728 | if lastOfs != ofs { 729 | return 0, errors.New(" lastOfs == ofs") // so a[b + ofs - 1] <= key < a[b + ofs] 730 | } 731 | return ofs, nil 732 | } 733 | 734 | /** 735 | * Merges two adjacent runs in place, in a stable fashion. The first 736 | * element of the first run must be greater than the first element of the 737 | * second run (a[base1] > a[base2]), and the last element of the first run 738 | * (a[base1 + len1-1]) must be greater than all elements of the second run. 739 | * 740 | * For performance, this method should be called only when len1 <= len2; 741 | * its twin, mergeHi should be called if len1 >= len2. (Either method 742 | * may be called if len1 == len2.) 743 | * 744 | * @param base1 index of first element in first run to be merged 745 | * @param len1 length of first run to be merged (must be > 0) 746 | * @param base2 index of first element in second run to be merged 747 | * (must be aBase + aLen) 748 | * @param len2 length of second run to be merged (must be > 0) 749 | */ 750 | func (h *timSortHandler) mergeLo(base1, len1, base2, len2 int) (err error) { 751 | if len1 <= 0 || len2 <= 0 || base1+len1 != base2 { 752 | return errors.New(" len1 > 0 && len2 > 0 && base1 + len1 == base2") 753 | } 754 | 755 | // Copy first run into temp array 756 | a := h.a // For performance 757 | tmp := h.ensureCapacity(len1) 758 | 759 | copy(tmp, a[base1:base1+len1]) 760 | 761 | cursor1 := 0 // Indexes into tmp array 762 | cursor2 := base2 // Indexes int a 763 | dest := base1 // Indexes int a 764 | 765 | // Move first element of second run and deal with degenerate cases 766 | a[dest] = a[cursor2] 767 | dest++ 768 | cursor2++ 769 | len2-- 770 | if len2 == 0 { 771 | copy(a[dest:dest+len1], tmp) 772 | return 773 | } 774 | if len1 == 1 { 775 | copy(a[dest:dest+len2], a[cursor2:cursor2+len2]) 776 | a[dest+len2] = tmp[cursor1] // Last elt of run 1 to end of merge 777 | return 778 | } 779 | 780 | lt := h.lt // Use local variable for performance 781 | minGallop := h.minGallop // " " " " " 782 | 783 | outer: 784 | for { 785 | count1 := 0 // Number of times in a row that first run won 786 | count2 := 0 // Number of times in a row that second run won 787 | 788 | /* 789 | * Do the straightforward thing until (if ever) one run starts 790 | * winning consistently. 791 | */ 792 | for { 793 | if len1 <= 1 || len2 <= 0 { 794 | return errors.New(" len1 > 1 && len2 > 0") 795 | } 796 | 797 | if lt(a[cursor2], tmp[cursor1]) { 798 | a[dest] = a[cursor2] 799 | dest++ 800 | cursor2++ 801 | count2++ 802 | count1 = 0 803 | len2-- 804 | if len2 == 0 { 805 | break outer 806 | } 807 | } else { 808 | a[dest] = tmp[cursor1] 809 | dest++ 810 | cursor1++ 811 | count1++ 812 | count2 = 0 813 | len1-- 814 | if len1 == 1 { 815 | break outer 816 | } 817 | } 818 | if (count1 | count2) >= minGallop { 819 | break 820 | } 821 | } 822 | 823 | /* 824 | * One run is winning so consistently that galloping may be a 825 | * huge win. So try that, and continue galloping until (if ever) 826 | * neither run appears to be winning consistently anymore. 827 | */ 828 | for { 829 | if len1 <= 1 || len2 <= 0 { 830 | return errors.New("len1 > 1 && len2 > 0") 831 | } 832 | count1, err = gallopRight(a[cursor2], tmp, cursor1, len1, 0, lt) 833 | if err != nil { 834 | return 835 | } 836 | if count1 != 0 { 837 | copy(a[dest:dest+count1], tmp[cursor1:cursor1+count1]) 838 | dest += count1 839 | cursor1 += count1 840 | len1 -= count1 841 | if len1 <= 1 { // len1 == 1 || len1 == 0 842 | break outer 843 | } 844 | } 845 | a[dest] = a[cursor2] 846 | dest++ 847 | cursor2++ 848 | len2-- 849 | if len2 == 0 { 850 | break outer 851 | } 852 | 853 | count2, err = gallopLeft(tmp[cursor1], a, cursor2, len2, 0, lt) 854 | if err != nil { 855 | return 856 | } 857 | if count2 != 0 { 858 | copy(a[dest:dest+count2], a[cursor2:cursor2+count2]) 859 | dest += count2 860 | cursor2 += count2 861 | len2 -= count2 862 | if len2 == 0 { 863 | break outer 864 | } 865 | } 866 | a[dest] = tmp[cursor1] 867 | dest++ 868 | cursor1++ 869 | len1-- 870 | if len1 == 1 { 871 | break outer 872 | } 873 | minGallop-- 874 | if count1 < minGallop && count2 < minGallop { 875 | break 876 | } 877 | } 878 | if minGallop < 0 { 879 | minGallop = 0 880 | } 881 | minGallop += 2 // Penalize for leaving gallop mode 882 | } // End of "outer" loop 883 | 884 | if minGallop < 1 { 885 | minGallop = 1 886 | } 887 | h.minGallop = minGallop // Write back to field 888 | 889 | if len1 == 1 { 890 | 891 | if len2 <= 0 { 892 | return errors.New(" len2 > 0;") 893 | } 894 | copy(a[dest:dest+len2], a[cursor2:cursor2+len2]) 895 | a[dest+len2] = tmp[cursor1] // Last elt of run 1 to end of merge 896 | } else if len1 == 0 { 897 | return errors.New("comparison method violates its general contract") 898 | } else { 899 | if len2 != 0 { 900 | return errors.New("len2 == 0;") 901 | } 902 | if len1 <= 1 { 903 | return errors.New(" len1 > 1;") 904 | } 905 | 906 | copy(a[dest:dest+len1], tmp[cursor1:cursor1+len1]) 907 | } 908 | return 909 | } 910 | 911 | /** 912 | * Like mergeLo, except that this method should be called only if 913 | * len1 >= len2; mergeLo should be called if len1 <= len2. (Either method 914 | * may be called if len1 == len2.) 915 | * 916 | * @param base1 index of first element in first run to be merged 917 | * @param len1 length of first run to be merged (must be > 0) 918 | * @param base2 index of first element in second run to be merged 919 | * (must be aBase + aLen) 920 | * @param len2 length of second run to be merged (must be > 0) 921 | */ 922 | func (h *timSortHandler) mergeHi(base1, len1, base2, len2 int) (err error) { 923 | if len1 <= 0 || len2 <= 0 || base1+len1 != base2 { 924 | return errors.New("len1 > 0 && len2 > 0 && base1 + len1 == base2;") 925 | } 926 | 927 | // Copy second run into temp array 928 | a := h.a // For performance 929 | tmp := h.ensureCapacity(len2) 930 | 931 | copy(tmp, a[base2:base2+len2]) 932 | 933 | cursor1 := base1 + len1 - 1 // Indexes into a 934 | cursor2 := len2 - 1 // Indexes into tmp array 935 | dest := base2 + len2 - 1 // Indexes into a 936 | 937 | // Move last element of first run and deal with degenerate cases 938 | a[dest] = a[cursor1] 939 | dest-- 940 | cursor1-- 941 | len1-- 942 | if len1 == 0 { 943 | dest -= len2 - 1 944 | copy(a[dest:dest+len2], tmp) 945 | return 946 | } 947 | if len2 == 1 { 948 | dest -= len1 - 1 949 | cursor1 -= len1 - 1 950 | copy(a[dest:dest+len1], a[cursor1:cursor1+len1]) 951 | a[dest-1] = tmp[cursor2] 952 | return 953 | } 954 | 955 | lt := h.lt // Use local variable for performance 956 | minGallop := h.minGallop // " " " " " 957 | 958 | outer: 959 | for { 960 | count1 := 0 // Number of times in a row that first run won 961 | count2 := 0 // Number of times in a row that second run won 962 | 963 | /* 964 | * Do the straightforward thing until (if ever) one run 965 | * appears to win consistently. 966 | */ 967 | for { 968 | if len1 <= 0 || len2 <= 1 { 969 | return errors.New(" len1 > 0 && len2 > 1;") 970 | } 971 | if lt(tmp[cursor2], a[cursor1]) { 972 | a[dest] = a[cursor1] 973 | dest-- 974 | cursor1-- 975 | count1++ 976 | count2 = 0 977 | len1-- 978 | if len1 == 0 { 979 | break outer 980 | } 981 | } else { 982 | a[dest] = tmp[cursor2] 983 | dest-- 984 | cursor2-- 985 | count2++ 986 | count1 = 0 987 | len2-- 988 | if len2 == 1 { 989 | break outer 990 | } 991 | } 992 | if (count1 | count2) >= minGallop { 993 | break 994 | } 995 | } 996 | 997 | /* 998 | * One run is winning so consistently that galloping may be a 999 | * huge win. So try that, and continue galloping until (if ever) 1000 | * neither run appears to be winning consistently anymore. 1001 | */ 1002 | for { 1003 | if len1 <= 0 || len2 <= 1 { 1004 | return errors.New(" len1 > 0 && len2 > 1;") 1005 | } 1006 | if gr, err := gallopRight(tmp[cursor2], a, base1, len1, len1-1, lt); err == nil { 1007 | count1 = len1 - gr 1008 | } else { 1009 | return err 1010 | } 1011 | if count1 != 0 { 1012 | dest -= count1 1013 | cursor1 -= count1 1014 | len1 -= count1 1015 | copy(a[dest+1:dest+1+count1], a[cursor1+1:cursor1+1+count1]) 1016 | if len1 == 0 { 1017 | break outer 1018 | } 1019 | } 1020 | a[dest] = tmp[cursor2] 1021 | dest-- 1022 | cursor2-- 1023 | len2-- 1024 | if len2 == 1 { 1025 | break outer 1026 | } 1027 | 1028 | if gl, err := gallopLeft(a[cursor1], tmp, 0, len2, len2-1, lt); err == nil { 1029 | count2 = len2 - gl 1030 | } else { 1031 | return err 1032 | } 1033 | if count2 != 0 { 1034 | dest -= count2 1035 | cursor2 -= count2 1036 | len2 -= count2 1037 | copy(a[dest+1:dest+1+count2], tmp[cursor2+1:cursor2+1+count2]) 1038 | if len2 <= 1 { // len2 == 1 || len2 == 0 1039 | break outer 1040 | } 1041 | } 1042 | a[dest] = a[cursor1] 1043 | dest-- 1044 | cursor1-- 1045 | len1-- 1046 | if len1 == 0 { 1047 | break outer 1048 | } 1049 | minGallop-- 1050 | 1051 | if count1 < minGallop && count2 < minGallop { 1052 | break 1053 | } 1054 | } 1055 | if minGallop < 0 { 1056 | minGallop = 0 1057 | } 1058 | minGallop += 2 // Penalize for leaving gallop mode 1059 | } // End of "outer" loop 1060 | 1061 | if minGallop < 1 { 1062 | minGallop = 1 1063 | } 1064 | 1065 | h.minGallop = minGallop // Write back to field 1066 | 1067 | if len2 == 1 { 1068 | if len1 <= 0 { 1069 | return errors.New(" len1 > 0;") 1070 | } 1071 | dest -= len1 1072 | cursor1 -= len1 1073 | 1074 | copy(a[dest+1:dest+1+len1], a[cursor1+1:cursor1+1+len1]) 1075 | a[dest] = tmp[cursor2] // Move first elt of run2 to front of merge 1076 | } else if len2 == 0 { 1077 | return errors.New("comparison method violates its general contract") 1078 | } else { 1079 | if len1 != 0 { 1080 | return errors.New("len1 == 0;") 1081 | } 1082 | 1083 | if len2 <= 0 { 1084 | return errors.New(" len2 > 0;") 1085 | } 1086 | 1087 | copy(a[dest-(len2-1):dest+1], tmp) 1088 | } 1089 | return 1090 | } 1091 | 1092 | /** 1093 | * Ensures that the external array tmp has at least the specified 1094 | * number of elements, increasing its size if necessary. The size 1095 | * increases exponentially to ensure amortized linear time complexity. 1096 | * 1097 | * @param minCapacity the minimum required capacity of the tmp array 1098 | * @return tmp, whether or not it grew 1099 | */ 1100 | func (h *timSortHandler) ensureCapacity(minCapacity int) []interface{} { 1101 | if len(h.tmp) < minCapacity { 1102 | // Compute smallest power of 2 > minCapacity 1103 | newSize := minCapacity 1104 | newSize |= newSize >> 1 1105 | newSize |= newSize >> 2 1106 | newSize |= newSize >> 4 1107 | newSize |= newSize >> 8 1108 | newSize |= newSize >> 16 1109 | newSize++ 1110 | 1111 | if newSize < 0 { // Not bloody likely! 1112 | newSize = minCapacity 1113 | } else { 1114 | ns := len(h.a) / 2 1115 | if ns < newSize { 1116 | newSize = ns 1117 | } 1118 | } 1119 | 1120 | h.tmp = make([]interface{}, newSize) 1121 | } 1122 | 1123 | return h.tmp 1124 | } 1125 | -------------------------------------------------------------------------------- /timsort_test.go: -------------------------------------------------------------------------------- 1 | package timsort 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "testing" 7 | ) 8 | 9 | type val struct { 10 | key, order int 11 | } 12 | 13 | func makeTestArray(size int) []interface{} { 14 | a := make([]interface{}, size) 15 | 16 | for i := 0; i < size; i++ { 17 | a[i] = val{i & 0xeeeeee, i} 18 | } 19 | 20 | return a 21 | } 22 | 23 | func IsSorted(a []interface{}, lessThan LessThan) bool { 24 | len := len(a) 25 | 26 | if len < 2 { 27 | return true 28 | } 29 | 30 | prev := a[0] 31 | for i := 1; i < len; i++ { 32 | if lessThan(a[i], prev) { 33 | return false 34 | } 35 | prev = a[i] 36 | } 37 | 38 | return true 39 | } 40 | 41 | func TestIsSorted(t *testing.T) { 42 | a := make([]interface{}, 5) 43 | a[0] = val{3, 1} 44 | a[1] = val{1, 5} 45 | a[2] = val{2, 3} 46 | a[3] = val{3, 4} 47 | a[4] = val{4, 5} 48 | 49 | if IsSorted(a, OrderLessThan) { 50 | t.Error("Sorted") 51 | } 52 | 53 | } 54 | 55 | // use this comparator for sorting 56 | func KeyLessThan(a, b interface{}) bool { 57 | return a.(val).key < b.(val).key 58 | } 59 | 60 | type KeyLessThanSlice []interface{} 61 | 62 | func (s KeyLessThanSlice) Len() int { 63 | return len(s) 64 | } 65 | 66 | func (s KeyLessThanSlice) Swap(i, j int) { 67 | s[i], s[j] = s[j], s[i] 68 | } 69 | 70 | func (s KeyLessThanSlice) Less(i, j int) bool { 71 | return s[i].(val).key < s[j].(val).key 72 | } 73 | 74 | // use this comparator to validate sorted data (and prove its stable) 75 | func KeyOrderLessThan(a, b interface{}) bool { 76 | if a.(val).key < b.(val).key { 77 | return true 78 | } else if a.(val).key == b.(val).key { 79 | return a.(val).order < b.(val).order 80 | } 81 | 82 | return false 83 | } 84 | 85 | // use this comparator to restore the original order of elements (by sorting on order field) 86 | func OrderLessThan(a, b interface{}) bool { 87 | return a.(val).order < b.(val).order 88 | } 89 | 90 | type OrderLessThanSlice []interface{} 91 | 92 | func (s OrderLessThanSlice) Len() int { 93 | return len(s) 94 | } 95 | 96 | func (s OrderLessThanSlice) Swap(i, j int) { 97 | s[i], s[j] = s[j], s[i] 98 | } 99 | 100 | func (s OrderLessThanSlice) Less(i, j int) bool { 101 | return s[i].(val).order < s[j].(val).order 102 | } 103 | 104 | func TestSmoke(t *testing.T) { 105 | a := make([]interface{}, 3) 106 | a[0] = val{3, 0} 107 | a[1] = val{1, 1} 108 | a[2] = val{2, 2} 109 | 110 | err := Sort(a, KeyLessThan) 111 | if err != nil { 112 | t.Fatalf("sort: %v", err) 113 | } 114 | 115 | if !IsSorted(a, KeyOrderLessThan) { 116 | t.Error("not sorted") 117 | } 118 | } 119 | 120 | func TestSmokeStability(t *testing.T) { 121 | a := make([]interface{}, 3) 122 | a[0] = val{3, 0} 123 | a[1] = val{2, 1} 124 | a[2] = val{2, 2} 125 | 126 | err := Sort(a, KeyLessThan) 127 | if err != nil { 128 | t.Fatalf("sort: %v", err) 129 | } 130 | 131 | if !IsSorted(a, KeyOrderLessThan) { 132 | t.Error("not sorted") 133 | } 134 | } 135 | 136 | func Test1K(t *testing.T) { 137 | a := makeTestArray(1024) 138 | 139 | err := Sort(a, KeyLessThan) 140 | if err != nil { 141 | t.Fatalf("sort: %v", err) 142 | } 143 | if !IsSorted(a, KeyOrderLessThan) { 144 | t.Error("not sorted") 145 | } 146 | } 147 | 148 | func Test1M(t *testing.T) { 149 | a := makeTestArray(1024 * 1024) 150 | 151 | err := Sort(a, KeyLessThan) 152 | if err != nil { 153 | t.Fatalf("sort: %v", err) 154 | } 155 | if !IsSorted(a, KeyOrderLessThan) { 156 | t.Error("not sorted") 157 | } 158 | } 159 | 160 | func makeRandomArray(size int) []interface{} { 161 | a := make([]interface{}, size) 162 | 163 | for i := 0; i < size; i++ { 164 | a[i] = val{rand.Intn(100), i} 165 | } 166 | 167 | return a 168 | } 169 | 170 | func Equals(a, b interface{}) bool { 171 | return a.(val).key == b.(val).key && a.(val).order == b.(val).order 172 | } 173 | 174 | func TestRandom1M(t *testing.T) { 175 | size := 1024 * 1024 176 | 177 | a := makeRandomArray(size) 178 | b := make([]interface{}, size) 179 | copy(b, a) 180 | 181 | err := Sort(a, KeyLessThan) 182 | if err != nil { 183 | t.Fatalf("sort: %v", err) 184 | } 185 | if !IsSorted(a, KeyOrderLessThan) { 186 | t.Error("not sorted") 187 | } 188 | 189 | // sort by order 190 | err = Sort(a, OrderLessThan) 191 | if err != nil { 192 | t.Fatalf("sort: %v", err) 193 | } 194 | for i := 0; i < len(b); i++ { 195 | if !Equals(b[i], a[i]) { 196 | t.Error("oops") 197 | } 198 | } 199 | } 200 | 201 | const ( 202 | _Sawtooth = iota 203 | _Rand 204 | _Stagger 205 | _Plateau 206 | _Shuffle 207 | _NDist 208 | ) 209 | 210 | const ( 211 | _Copy = iota 212 | _Reverse 213 | _ReverseFirstHalf 214 | _ReverseSecondHalf 215 | _Sorted 216 | _Dither 217 | _NMode 218 | ) 219 | 220 | func TestBentleyMcIlroy(t *testing.T) { 221 | // sizes := []int{100, 1023, 1024, 1025, 1023 * 1023, 1024 * 1024, 1025 * 1025} 222 | sizes := []int{100, 1023, 1024, 1025} 223 | dists := []string{"sawtooth", "rand", "stagger", "plateau", "shuffle"} 224 | modes := []string{"copy", "reverse", "reverse1", "reverse2", "sort", "dither"} 225 | tmp1 := make([]interface{}, 1025*1025) 226 | tmp2 := make([]interface{}, 1025*1025) 227 | for ni := 0; ni < len(sizes); ni++ { 228 | n := sizes[ni] 229 | for m := 1; m < 2*n; m *= 2 { 230 | for dist := 0; dist < _NDist; dist++ { 231 | j := 0 232 | k := 1 233 | data := tmp1[0:n] 234 | for i := 0; i < n; i++ { 235 | switch dist { 236 | case _Sawtooth: 237 | data[i] = val{i % m, i} 238 | case _Rand: 239 | data[i] = val{rand.Intn(m), i} 240 | case _Stagger: 241 | data[i] = val{(i*m + i) % n, i} 242 | case _Plateau: 243 | if i < m { 244 | data[i] = val{i, i} 245 | } else { 246 | data[i] = val{m, i} 247 | } 248 | case _Shuffle: 249 | if rand.Intn(m) != 0 { 250 | j += 2 251 | data[i] = val{j, i} 252 | } else { 253 | k += 2 254 | data[i] = val{k, i} 255 | } 256 | } 257 | } 258 | 259 | mdata := tmp2[0:n] 260 | for mode := 0; mode < _NMode; mode++ { 261 | switch mode { 262 | case _Copy: 263 | for i := 0; i < n; i++ { 264 | mdata[i] = val{data[i].(val).key, i} 265 | } 266 | case _Reverse: 267 | for i := 0; i < n; i++ { 268 | mdata[i] = val{data[n-i-1].(val).key, i} 269 | } 270 | case _ReverseFirstHalf: 271 | for i := 0; i < n/2; i++ { 272 | mdata[i] = val{data[n/2-i-1].(val).key, i} 273 | } 274 | for i := n / 2; i < n; i++ { 275 | mdata[i] = val{data[i].(val).key, i} 276 | } 277 | case _ReverseSecondHalf: 278 | for i := 0; i < n/2; i++ { 279 | mdata[i] = val{data[i].(val).key, i} 280 | } 281 | for i := n / 2; i < n; i++ { 282 | mdata[i] = val{data[n-(i-n/2)-1].(val).key, i} 283 | } 284 | case _Sorted: 285 | for i := 0; i < n; i++ { 286 | mdata[i] = data[i] 287 | } 288 | // SortInts is known to be correct 289 | // because mode Sort runs after mode _Copy. 290 | err := Sort(mdata, KeyLessThan) 291 | if err != nil { 292 | t.Fatalf("Sort: %v", err) 293 | } 294 | case _Dither: 295 | for i := 0; i < n; i++ { 296 | mdata[i] = val{data[i].(val).key + i%5, i} 297 | } 298 | } 299 | 300 | desc := fmt.Sprintf("n=%d m=%d dist=%s mode=%s", n, m, dists[dist], modes[mode]) 301 | 302 | for i := 0; i < len(mdata); i++ { 303 | mdata[i] = val{mdata[i].(val).key, i} 304 | } 305 | 306 | gdata := make([]interface{}, len(mdata)) 307 | copy(gdata, mdata) 308 | 309 | err := Sort(mdata, KeyLessThan) 310 | if err != nil { 311 | t.Fatalf("sort: %v", err) 312 | } 313 | 314 | // If we were testing C qsort, we'd have to make a copy 315 | // of the array and sort it ourselves and then compare 316 | // x against it, to ensure that qsort was only permuting 317 | // the data, not (for example) overwriting it with zeros. 318 | // 319 | // In go, we don't have to be so paranoid: since the only 320 | // mutating method Sort can call is TestingData.swap, 321 | // it suffices here just to check that the final array is sorted. 322 | if !IsSorted(mdata, KeyOrderLessThan) { 323 | t.Errorf("%s: ints not sorted", desc) 324 | t.Errorf("\t%v", mdata) 325 | t.FailNow() 326 | } 327 | 328 | err = Sort(mdata, OrderLessThan) 329 | if err != nil { 330 | t.Fatalf("sort: %v", err) 331 | } 332 | for i := 0; i < len(data); i++ { 333 | if !Equals(gdata[i], mdata[i]) { 334 | t.Error("restore sort failed") 335 | t.Errorf("gdata=%v", gdata) 336 | t.Errorf("mdata=%v", mdata) 337 | t.Errorf("bad index: %v\n", i) 338 | t.FailNow() 339 | } 340 | } 341 | } 342 | } 343 | } 344 | } 345 | } 346 | -------------------------------------------------------------------------------- /timsortint.go: -------------------------------------------------------------------------------- 1 | package timsort 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | // IntLessThan is a Delegate type that sorting uses as a comparator 9 | type IntLessThan func(a, b int) bool 10 | 11 | type timSortHandlerI struct { 12 | 13 | /** 14 | * The array being sorted. 15 | */ 16 | a []int 17 | 18 | /** 19 | * The comparator for this sort. 20 | */ 21 | lt IntLessThan 22 | 23 | /** 24 | * This controls when we get *into* galloping mode. It is initialized 25 | * to c_MIN_GALLOP. The mergeLo and mergeHi methods nudge it higher for 26 | * random data, and lower for highly structured data. 27 | */ 28 | minGallop int 29 | 30 | /** 31 | * Temp storage for merges. 32 | */ 33 | tmp []int // Actual runtime type will be Object[], regardless of T 34 | 35 | /** 36 | * A stack of pending runs yet to be merged. Run i starts at 37 | * address base[i] and extends for len[i] elements. It's always 38 | * true (so long as the indices are in bounds) that: 39 | * 40 | * runBase[i] + runLen[i] == runBase[i + 1] 41 | * 42 | * so we could cut the storage for this, but it's a minor amount, 43 | * and keeping all the info explicit simplifies the code. 44 | */ 45 | stackSize int // Number of pending runs on stack 46 | runBase []int 47 | runLen []int 48 | } 49 | 50 | /** 51 | * Creates a TimSort instance to maintain the state of an ongoing sort. 52 | * 53 | * @param a the array to be sorted 54 | * @param c the comparator to determine the order of the sort 55 | */ 56 | func newTimSortI(a []int, lt IntLessThan) (hi *timSortHandlerI) { 57 | hi = &timSortHandlerI{ 58 | a: a, 59 | lt: lt, 60 | minGallop: minGallop} 61 | 62 | // Allocate temp storage (which may be increased later if necessary) 63 | len := len(a) 64 | 65 | tmpSize := initialTmpStorageLength 66 | if len < 2*tmpSize { 67 | tmpSize = len / 2 68 | } 69 | 70 | hi.tmp = make([]int, tmpSize) 71 | 72 | /* 73 | * Allocate runs-to-be-merged stack (which cannot be expanded). The 74 | * stack length requirements are described in listsort.txt. The C 75 | * version always uses the same stack length (85), but this was 76 | * measured to be too expensive when sorting "mid-sized" arrays (e.g., 77 | * 100 elements) in Java. Therefore, we use smaller (but sufficiently 78 | * large) stack lengths for smaller arrays. The "magic numbers" in the 79 | * computation below must be changed if c_MIN_MERGE is decreased. See 80 | * the c_MIN_MERGE declaration above for more information. 81 | */ 82 | // mk: confirmed that for small sorts this optimization gives measurable (albeit small) 83 | // performance enhancement 84 | stackLen := 40 85 | if len < 120 { 86 | stackLen = 5 87 | } else if len < 1542 { 88 | stackLen = 10 89 | } else if len < 119151 { 90 | stackLen = 19 91 | } 92 | 93 | hi.runBase = make([]int, stackLen) 94 | hi.runLen = make([]int, stackLen) 95 | 96 | return hi 97 | } 98 | 99 | // Ints sorts an interger array using the provided comparator 100 | func Ints(a []int, lt IntLessThan) (err error) { 101 | lo := 0 102 | hi := len(a) 103 | nRemaining := hi 104 | 105 | if nRemaining < 2 { 106 | return // Arrays of size 0 and 1 are always sorted 107 | } 108 | 109 | // If array is small, do a "mini-TimSort" with no merges 110 | if nRemaining < minMerge { 111 | initRunLen, err := countRunAndMakeAscendingI(a, lo, hi, lt) 112 | if err != nil { 113 | return err 114 | } 115 | 116 | return binarySortI(a, lo, hi, lo+initRunLen, lt) 117 | } 118 | 119 | /** 120 | * March over the array once, left to right, finding natural runs, 121 | * extending short natural runs to minRun elements, and merging runs 122 | * to maintain stack invariant. 123 | */ 124 | 125 | ts := newTimSortI(a, lt) 126 | minRun, err := minRunLength(nRemaining) 127 | if err != nil { 128 | return 129 | } 130 | for { 131 | // Identify next run 132 | runLen, err := countRunAndMakeAscendingI(a, lo, hi, lt) 133 | if err != nil { 134 | return err 135 | } 136 | 137 | // If run is short, extend to min(minRun, nRemaining) 138 | if runLen < minRun { 139 | force := minRun 140 | if nRemaining <= minRun { 141 | force = nRemaining 142 | } 143 | if err = binarySortI(a, lo, lo+force, lo+runLen, lt); err != nil { 144 | return err 145 | } 146 | runLen = force 147 | } 148 | 149 | // Push run onto pending-run stack, and maybe merge 150 | ts.pushRun(lo, runLen) 151 | if err = ts.mergeCollapse(); err != nil { 152 | return err 153 | } 154 | 155 | // Advance to find next run 156 | lo += runLen 157 | nRemaining -= runLen 158 | if nRemaining == 0 { 159 | break 160 | } 161 | } 162 | 163 | // Merge all remaining runs to complete sort 164 | if lo != hi { 165 | return errors.New("lo must equal hi") 166 | } 167 | 168 | if err = ts.mergeForceCollapse(); err != nil { 169 | return 170 | } 171 | if ts.stackSize != 1 { 172 | return errors.New("ts.stackSize != 1") 173 | } 174 | return 175 | } 176 | 177 | /** 178 | * Sorts the specified portion of the specified array using a binary 179 | * insertion sort. This is the best method for sorting small numbers 180 | * of elements. It requires O(n log n) compares, but O(n^2) data 181 | * movement (worst case). 182 | * 183 | * If the initial part of the specified range is already sorted, 184 | * this method can take advantage of it: the method assumes that the 185 | * elements from index {@code lo}, inclusive, to {@code start}, 186 | * exclusive are already sorted. 187 | * 188 | * @param a the array in which a range is to be sorted 189 | * @param lo the index of the first element in the range to be sorted 190 | * @param hi the index after the last element in the range to be sorted 191 | * @param start the index of the first element in the range that is 192 | * not already known to be sorted (@code lo <= start <= hi} 193 | * @param c comparator to used for the sort 194 | */ 195 | func binarySortI(a []int, lo, hi, start int, lt IntLessThan) (err error) { 196 | if lo > start || start > hi { 197 | return errors.New("lo <= start && start <= hi") 198 | } 199 | 200 | if start == lo { 201 | start++ 202 | } 203 | 204 | for ; start < hi; start++ { 205 | pivot := a[start] 206 | 207 | // Set left (and right) to the index where a[start] (pivot) belongs 208 | left := lo 209 | right := start 210 | 211 | if left > right { 212 | return errors.New("left <= right") 213 | } 214 | 215 | /* 216 | * Invariants: 217 | * pivot >= all in [lo, left). 218 | * pivot < all in [right, start). 219 | */ 220 | for left < right { 221 | mid := int(uint(left+right) >> 1) 222 | if lt(pivot, a[mid]) { 223 | right = mid 224 | } else { 225 | left = mid + 1 226 | } 227 | } 228 | 229 | if left != right { 230 | return errors.New("left == right") 231 | } 232 | 233 | /* 234 | * The invariants still hold: pivot >= all in [lo, left) and 235 | * pivot < all in [left, start), so pivot belongs at left. Note 236 | * that if there are elements equal to pivot, left points to the 237 | * first slot after them -- that's why this sort is stable. 238 | * Slide elements over to make room to make room for pivot. 239 | */ 240 | n := start - left // The number of elements to move 241 | // just an optimization for copy in default case 242 | if n <= 2 { 243 | if n == 2 { 244 | a[left+2] = a[left+1] 245 | } 246 | if n > 0 { 247 | a[left+1] = a[left] 248 | } 249 | } else { 250 | copy(a[left+1:], a[left:left+n]) 251 | } 252 | a[left] = pivot 253 | } 254 | return 255 | } 256 | 257 | /** 258 | * Returns the length of the run beginning at the specified position in 259 | * the specified array and reverses the run if it is descending (ensuring 260 | * that the run will always be ascending when the method returns). 261 | * 262 | * A run is the longest ascending sequence with: 263 | * 264 | * a[lo] <= a[lo + 1] <= a[lo + 2] <= ... 265 | * 266 | * or the longest descending sequence with: 267 | * 268 | * a[lo] > a[lo + 1] > a[lo + 2] > ... 269 | * 270 | * For its intended use in a stable mergesort, the strictness of the 271 | * definition of "descending" is needed so that the call can safely 272 | * reverse a descending sequence without violating stability. 273 | * 274 | * @param a the array in which a run is to be counted and possibly reversed 275 | * @param lo index of the first element in the run 276 | * @param hi index after the last element that may be contained in the run. 277 | It is required that @code{lo < hi}. 278 | * @param c the comparator to used for the sort 279 | * @return the length of the run beginning at the specified position in 280 | * the specified array 281 | */ 282 | func countRunAndMakeAscendingI(a []int, lo, hi int, lt IntLessThan) (int, error) { 283 | 284 | if lo >= hi { 285 | return 0, errors.New("lo < hi") 286 | } 287 | 288 | runHi := lo + 1 289 | if runHi == hi { 290 | return 1, nil 291 | } 292 | 293 | // Find end of run, and reverse range if descending 294 | if lt(a[runHi], a[lo]) { // Descending 295 | runHi++ 296 | 297 | for runHi < hi && lt(a[runHi], a[runHi-1]) { 298 | runHi++ 299 | } 300 | reverseRangeI(a, lo, runHi) 301 | } else { // Ascending 302 | for runHi < hi && !lt(a[runHi], a[runHi-1]) { 303 | runHi++ 304 | } 305 | } 306 | 307 | return runHi - lo, nil 308 | } 309 | 310 | /** 311 | * Reverse the specified range of the specified array. 312 | * 313 | * @param a the array in which a range is to be reversed 314 | * @param lo the index of the first element in the range to be reversed 315 | * @param hi the index after the last element in the range to be reversed 316 | */ 317 | func reverseRangeI(a []int, lo, hi int) { 318 | hi-- 319 | for lo < hi { 320 | a[lo], a[hi] = a[hi], a[lo] 321 | lo++ 322 | hi-- 323 | } 324 | } 325 | 326 | /** 327 | * Pushes the specified run onto the pending-run stack. 328 | * 329 | * @param runBase index of the first element in the run 330 | * @param runLen the number of elements in the run 331 | */ 332 | func (hi *timSortHandlerI) pushRun(runBase, runLen int) { 333 | hi.runBase[hi.stackSize] = runBase 334 | hi.runLen[hi.stackSize] = runLen 335 | hi.stackSize++ 336 | } 337 | 338 | /** 339 | * Examines the stack of runs waiting to be merged and merges adjacent runs 340 | * until the stack invariants are reestablished: 341 | * 342 | * 1. runLen[i - 3] > runLen[i - 2] + runLen[i - 1] 343 | * 2. runLen[i - 2] > runLen[i - 1] 344 | * 345 | * This method is called each time a new run is pushed onto the stack, 346 | * so the invariants are guaranteed to hold for i < stackSize upon 347 | * entry to the method. 348 | */ 349 | func (hi *timSortHandlerI) mergeCollapse() (err error) { 350 | for hi.stackSize > 1 { 351 | n := hi.stackSize - 2 352 | if (n > 0 && hi.runLen[n-1] <= hi.runLen[n]+hi.runLen[n+1]) || 353 | (n > 1 && hi.runLen[n-2] <= hi.runLen[n-1]+hi.runLen[n]) { 354 | if hi.runLen[n-1] < hi.runLen[n+1] { 355 | n-- 356 | } 357 | if err = hi.mergeAt(n); err != nil { 358 | return 359 | } 360 | } else if hi.runLen[n] <= hi.runLen[n+1] { 361 | if err = hi.mergeAt(n); err != nil { 362 | return 363 | } 364 | } else { 365 | break // Invariant is established 366 | } 367 | } 368 | return 369 | } 370 | 371 | /** 372 | * Merges all runs on the stack until only one remains. This method is 373 | * called once, to complete the sort. 374 | */ 375 | func (hi *timSortHandlerI) mergeForceCollapse() (err error) { 376 | for hi.stackSize > 1 { 377 | n := hi.stackSize - 2 378 | if n > 0 && hi.runLen[n-1] < hi.runLen[n+1] { 379 | n-- 380 | } 381 | if err = hi.mergeAt(n); err != nil { 382 | return 383 | } 384 | } 385 | return 386 | } 387 | 388 | /** 389 | * Merges the two runs at stack indices i and i+1. Run i must be 390 | * the penultimate or antepenultimate run on the stack. In other words, 391 | * i must be equal to stackSize-2 or stackSize-3. 392 | * 393 | * @param i stack index of the first of the two runs to merge 394 | */ 395 | func (hi *timSortHandlerI) mergeAt(i int) (err error) { 396 | if hi.stackSize < 2 { 397 | return errors.New("stackSize >= 2") 398 | } 399 | 400 | if i < 0 { 401 | return errors.New(" i >= 0") 402 | } 403 | 404 | if i != hi.stackSize-2 && i != hi.stackSize-3 { 405 | return errors.New("if i == stackSize - 2 || i == stackSize - 3") 406 | } 407 | 408 | base1 := hi.runBase[i] 409 | len1 := hi.runLen[i] 410 | base2 := hi.runBase[i+1] 411 | len2 := hi.runLen[i+1] 412 | 413 | if len1 <= 0 || len2 <= 0 { 414 | return errors.New("len1 > 0 && len2 > 0") 415 | } 416 | 417 | if base1+len1 != base2 { 418 | return errors.New("base1 + len1 == base2") 419 | } 420 | 421 | /* 422 | * Record the length of the combined runs; if i is the 3rd-last 423 | * run now, also slide over the last run (which isn't involved 424 | * in this merge). The current run (i+1) goes away in any case. 425 | */ 426 | hi.runLen[i] = len1 + len2 427 | if i == hi.stackSize-3 { 428 | hi.runBase[i+1] = hi.runBase[i+2] 429 | hi.runLen[i+1] = hi.runLen[i+2] 430 | } 431 | hi.stackSize-- 432 | 433 | /* 434 | * Find where the first element of run2 goes in run1. Prior elements 435 | * in run1 can be ignored (because they're already in place). 436 | */ 437 | k, err := gallopRightI(hi.a[base2], hi.a, base1, len1, 0, hi.lt) 438 | if err != nil { 439 | return err 440 | } 441 | if k < 0 { 442 | return errors.New(" k >= 0;") 443 | } 444 | base1 += k 445 | len1 -= k 446 | if len1 == 0 { 447 | return 448 | } 449 | 450 | /* 451 | * Find where the last element of run1 goes in run2. Subsequent elements 452 | * in run2 can be ignored (because they're already in place). 453 | */ 454 | len2, err = gallopLeftI(hi.a[base1+len1-1], hi.a, base2, len2, len2-1, hi.lt) 455 | if err != nil { 456 | return 457 | } 458 | if len2 < 0 { 459 | return errors.New(" len2 >= 0;") 460 | } 461 | if len2 == 0 { 462 | return 463 | } 464 | 465 | // Merge remaining runs, using tmp array with min(len1, len2) elements 466 | if len1 <= len2 { 467 | err = hi.mergeLo(base1, len1, base2, len2) 468 | if err != nil { 469 | return fmt.Errorf("mergeLo: %v", err) 470 | } 471 | } else { 472 | err = hi.mergeHi(base1, len1, base2, len2) 473 | if err != nil { 474 | return fmt.Errorf("mergeHi: %v", err) 475 | } 476 | } 477 | return 478 | } 479 | 480 | /** 481 | * Locates the position at which to insert the specified key into the 482 | * specified sorted range; if the range contains an element equal to key, 483 | * returns the index of the leftmost equal element. 484 | * 485 | * @param key the key whose insertion point to search for 486 | * @param a the array in which to search 487 | * @param base the index of the first element in the range 488 | * @param len the length of the range; must be > 0 489 | * @param hint the index at which to begin the search, 0 <= hint < n. 490 | * The closer hint is to the result, the faster this method will run. 491 | * @param c the comparator used to order the range, and to search 492 | * @return the int k, 0 <= k <= n such that a[b + k - 1] < key <= a[b + k], 493 | * pretending that a[b - 1] is minus infinity and a[b + n] is infinity. 494 | * In other words, key belongs at index b + k; or in other words, 495 | * the first k elements of a should precede key, and the last n - k 496 | * should follow it. 497 | */ 498 | func gallopLeftI(key int, a []int, base, len, hint int, c IntLessThan) (int, error) { 499 | if len <= 0 || hint < 0 || hint >= len { 500 | return 0, errors.New(" len > 0 && hint >= 0 && hint < len;") 501 | } 502 | lastOfs := 0 503 | ofs := 1 504 | 505 | if c(a[base+hint], key) { 506 | // Gallop right until a[base+hint+lastOfs] < key <= a[base+hint+ofs] 507 | maxOfs := len - hint 508 | for ofs < maxOfs && c(a[base+hint+ofs], key) { 509 | lastOfs = ofs 510 | ofs = (ofs << 1) + 1 511 | if ofs <= 0 { // int overflow 512 | ofs = maxOfs 513 | } 514 | } 515 | if ofs > maxOfs { 516 | ofs = maxOfs 517 | } 518 | 519 | // Make offsets relative to base 520 | lastOfs += hint 521 | ofs += hint 522 | } else { // key <= a[base + hint] 523 | // Gallop left until a[base+hint-ofs] < key <= a[base+hint-lastOfs] 524 | maxOfs := hint + 1 525 | for ofs < maxOfs && !c(a[base+hint-ofs], key) { 526 | lastOfs = ofs 527 | ofs = (ofs << 1) + 1 528 | if ofs <= 0 { // int overflow 529 | ofs = maxOfs 530 | } 531 | } 532 | if ofs > maxOfs { 533 | ofs = maxOfs 534 | } 535 | 536 | // Make offsets relative to base 537 | tmp := lastOfs 538 | lastOfs = hint - ofs 539 | ofs = hint - tmp 540 | } 541 | 542 | if -1 > lastOfs || lastOfs >= ofs || ofs > len { 543 | return 0, errors.New(" -1 <= lastOfs && lastOfs < ofs && ofs <= len;") 544 | } 545 | 546 | /* 547 | * Now a[base+lastOfs] < key <= a[base+ofs], so key belongs somewhere 548 | * to the right of lastOfs but no farther right than ofs. Do a binary 549 | * search, with invariant a[base + lastOfs - 1] < key <= a[base + ofs]. 550 | */ 551 | lastOfs++ 552 | for lastOfs < ofs { 553 | m := lastOfs + (ofs-lastOfs)/2 554 | 555 | if c(a[base+m], key) { 556 | lastOfs = m + 1 // a[base + m] < key 557 | } else { 558 | ofs = m // key <= a[base + m] 559 | } 560 | } 561 | 562 | if lastOfs != ofs { 563 | return 0, errors.New(" lastOfs == ofs") // so a[base + ofs - 1] < key <= a[base + ofs] 564 | } 565 | return ofs, nil 566 | } 567 | 568 | /** 569 | * Like gallopLeft, except that if the range contains an element equal to 570 | * key, gallopRight returns the index after the rightmost equal element. 571 | * 572 | * @param key the key whose insertion point to search for 573 | * @param a the array in which to search 574 | * @param base the index of the first element in the range 575 | * @param len the length of the range; must be > 0 576 | * @param hint the index at which to begin the search, 0 <= hint < n. 577 | * The closer hint is to the result, the faster this method will run. 578 | * @param c the comparator used to order the range, and to search 579 | * @return the int k, 0 <= k <= n such that a[b + k - 1] <= key < a[b + k] 580 | */ 581 | func gallopRightI(key int, a []int, base, len, hint int, c IntLessThan) (int, error) { 582 | if len <= 0 || hint < 0 || hint >= len { 583 | return 0, errors.New(" len > 0 && hint >= 0 && hint < len;") 584 | } 585 | 586 | ofs := 1 587 | lastOfs := 0 588 | if c(key, a[base+hint]) { 589 | // Gallop left until a[b+hint - ofs] <= key < a[b+hint - lastOfs] 590 | maxOfs := hint + 1 591 | for ofs < maxOfs && c(key, a[base+hint-ofs]) { 592 | lastOfs = ofs 593 | ofs = (ofs << 1) + 1 594 | if ofs <= 0 { // int overflow 595 | ofs = maxOfs 596 | } 597 | } 598 | if ofs > maxOfs { 599 | ofs = maxOfs 600 | } 601 | 602 | // Make offsets relative to b 603 | tmp := lastOfs 604 | lastOfs = hint - ofs 605 | ofs = hint - tmp 606 | } else { // a[b + hint] <= key 607 | // Gallop right until a[b+hint + lastOfs] <= key < a[b+hint + ofs] 608 | maxOfs := len - hint 609 | for ofs < maxOfs && !c(key, a[base+hint+ofs]) { 610 | lastOfs = ofs 611 | ofs = (ofs << 1) + 1 612 | if ofs <= 0 { // int overflow 613 | ofs = maxOfs 614 | } 615 | } 616 | if ofs > maxOfs { 617 | ofs = maxOfs 618 | } 619 | 620 | // Make offsets relative to b 621 | lastOfs += hint 622 | ofs += hint 623 | } 624 | if -1 > lastOfs || lastOfs >= ofs || ofs > len { 625 | return 0, errors.New("-1 <= lastOfs && lastOfs < ofs && ofs <= len") 626 | } 627 | 628 | /* 629 | * Now a[b + lastOfs] <= key < a[b + ofs], so key belongs somewhere to 630 | * the right of lastOfs but no farther right than ofs. Do a binary 631 | * search, with invariant a[b + lastOfs - 1] <= key < a[b + ofs]. 632 | */ 633 | lastOfs++ 634 | for lastOfs < ofs { 635 | m := lastOfs + (ofs-lastOfs)/2 636 | 637 | if c(key, a[base+m]) { 638 | ofs = m // key < a[b + m] 639 | } else { 640 | lastOfs = m + 1 // a[b + m] <= key 641 | } 642 | } 643 | if lastOfs != ofs { 644 | return 0, errors.New(" lastOfs == ofs") // so a[b + ofs - 1] <= key < a[b + ofs] 645 | } 646 | return ofs, nil 647 | } 648 | 649 | /** 650 | * Merges two adjacent runs in place, in a stable fashion. The first 651 | * element of the first run must be greater than the first element of the 652 | * second run (a[base1] > a[base2]), and the last element of the first run 653 | * (a[base1 + len1-1]) must be greater than all elements of the second run. 654 | * 655 | * For performance, this method should be called only when len1 <= len2; 656 | * its twin, mergeHi should be called if len1 >= len2. (Either method 657 | * may be called if len1 == len2.) 658 | * 659 | * @param base1 index of first element in first run to be merged 660 | * @param len1 length of first run to be merged (must be > 0) 661 | * @param base2 index of first element in second run to be merged 662 | * (must be aBase + aLen) 663 | * @param len2 length of second run to be merged (must be > 0) 664 | */ 665 | func (hi *timSortHandlerI) mergeLo(base1, len1, base2, len2 int) (err error) { 666 | if len1 <= 0 || len2 <= 0 || base1+len1 != base2 { 667 | return errors.New(" len1 > 0 && len2 > 0 && base1 + len1 == base2") 668 | } 669 | 670 | // Copy first run into temp array 671 | a := hi.a // For performance 672 | tmp := hi.ensureCapacity(len1) 673 | 674 | copy(tmp, a[base1:base1+len1]) 675 | 676 | cursor1 := 0 // Indexes into tmp array 677 | cursor2 := base2 // Indexes int a 678 | dest := base1 // Indexes int a 679 | 680 | // Move first element of second run and deal with degenerate cases 681 | a[dest] = a[cursor2] 682 | dest++ 683 | cursor2++ 684 | len2-- 685 | if len2 == 0 { 686 | copy(a[dest:dest+len1], tmp) 687 | return 688 | } 689 | if len1 == 1 { 690 | copy(a[dest:dest+len2], a[cursor2:cursor2+len2]) 691 | a[dest+len2] = tmp[cursor1] // Last elt of run 1 to end of merge 692 | return 693 | } 694 | 695 | lt := hi.lt // Use local variable for performance 696 | minGallop := hi.minGallop // " " " " " 697 | 698 | outer: 699 | for { 700 | count1 := 0 // Number of times in a row that first run won 701 | count2 := 0 // Number of times in a row that second run won 702 | 703 | /* 704 | * Do the straightforward thing until (if ever) one run starts 705 | * winning consistently. 706 | */ 707 | for { 708 | if len1 <= 1 || len2 <= 0 { 709 | return errors.New(" len1 > 1 && len2 > 0") 710 | } 711 | 712 | if lt(a[cursor2], tmp[cursor1]) { 713 | a[dest] = a[cursor2] 714 | dest++ 715 | cursor2++ 716 | count2++ 717 | count1 = 0 718 | len2-- 719 | if len2 == 0 { 720 | break outer 721 | } 722 | } else { 723 | a[dest] = tmp[cursor1] 724 | dest++ 725 | cursor1++ 726 | count1++ 727 | count2 = 0 728 | len1-- 729 | if len1 == 1 { 730 | break outer 731 | } 732 | } 733 | if (count1 | count2) >= minGallop { 734 | break 735 | } 736 | } 737 | 738 | /* 739 | * One run is winning so consistently that galloping may be a 740 | * huge win. So try that, and continue galloping until (if ever) 741 | * neither run appears to be winning consistently anymore. 742 | */ 743 | for { 744 | if len1 <= 1 || len2 <= 0 { 745 | return errors.New("len1 > 1 && len2 > 0") 746 | } 747 | count1, err = gallopRightI(a[cursor2], tmp, cursor1, len1, 0, lt) 748 | if err != nil { 749 | return 750 | } 751 | if count1 != 0 { 752 | copy(a[dest:dest+count1], tmp[cursor1:cursor1+count1]) 753 | dest += count1 754 | cursor1 += count1 755 | len1 -= count1 756 | if len1 <= 1 { // len1 == 1 || len1 == 0 757 | break outer 758 | } 759 | } 760 | a[dest] = a[cursor2] 761 | dest++ 762 | cursor2++ 763 | len2-- 764 | if len2 == 0 { 765 | break outer 766 | } 767 | 768 | count2, err = gallopLeftI(tmp[cursor1], a, cursor2, len2, 0, lt) 769 | if err != nil { 770 | return 771 | } 772 | if count2 != 0 { 773 | copy(a[dest:dest+count2], a[cursor2:cursor2+count2]) 774 | dest += count2 775 | cursor2 += count2 776 | len2 -= count2 777 | if len2 == 0 { 778 | break outer 779 | } 780 | } 781 | a[dest] = tmp[cursor1] 782 | dest++ 783 | cursor1++ 784 | len1-- 785 | if len1 == 1 { 786 | break outer 787 | } 788 | minGallop-- 789 | if count1 < minGallop && count2 < minGallop { 790 | break 791 | } 792 | } 793 | if minGallop < 0 { 794 | minGallop = 0 795 | } 796 | minGallop += 2 // Penalize for leaving gallop mode 797 | } // End of "outer" loop 798 | 799 | if minGallop < 1 { 800 | minGallop = 1 801 | } 802 | hi.minGallop = minGallop // Write back to field 803 | 804 | if len1 == 1 { 805 | 806 | if len2 <= 0 { 807 | return errors.New(" len2 > 0;") 808 | } 809 | copy(a[dest:dest+len2], a[cursor2:cursor2+len2]) 810 | a[dest+len2] = tmp[cursor1] // Last elt of run 1 to end of merge 811 | } else if len1 == 0 { 812 | return errors.New("comparison method violates its general contract") 813 | } else { 814 | if len2 != 0 { 815 | return errors.New("len2 == 0;") 816 | } 817 | if len1 <= 1 { 818 | return errors.New(" len1 > 1;") 819 | } 820 | 821 | copy(a[dest:dest+len1], tmp[cursor1:cursor1+len1]) 822 | } 823 | return 824 | } 825 | 826 | /** 827 | * Like mergeLo, except that this method should be called only if 828 | * len1 >= len2; mergeLo should be called if len1 <= len2. (Either method 829 | * may be called if len1 == len2.) 830 | * 831 | * @param base1 index of first element in first run to be merged 832 | * @param len1 length of first run to be merged (must be > 0) 833 | * @param base2 index of first element in second run to be merged 834 | * (must be aBase + aLen) 835 | * @param len2 length of second run to be merged (must be > 0) 836 | */ 837 | func (hi *timSortHandlerI) mergeHi(base1, len1, base2, len2 int) (err error) { 838 | if len1 <= 0 || len2 <= 0 || base1+len1 != base2 { 839 | return errors.New("len1 > 0 && len2 > 0 && base1 + len1 == base2;") 840 | } 841 | 842 | // Copy second run into temp array 843 | a := hi.a // For performance 844 | tmp := hi.ensureCapacity(len2) 845 | 846 | copy(tmp, a[base2:base2+len2]) 847 | 848 | cursor1 := base1 + len1 - 1 // Indexes into a 849 | cursor2 := len2 - 1 // Indexes into tmp array 850 | dest := base2 + len2 - 1 // Indexes into a 851 | 852 | // Move last element of first run and deal with degenerate cases 853 | a[dest] = a[cursor1] 854 | dest-- 855 | cursor1-- 856 | len1-- 857 | if len1 == 0 { 858 | dest -= len2 - 1 859 | copy(a[dest:dest+len2], tmp) 860 | return 861 | } 862 | if len2 == 1 { 863 | dest -= len1 - 1 864 | cursor1 -= len1 - 1 865 | copy(a[dest:dest+len1], a[cursor1:cursor1+len1]) 866 | a[dest-1] = tmp[cursor2] 867 | return 868 | } 869 | 870 | lt := hi.lt // Use local variable for performance 871 | minGallop := hi.minGallop // " " " " " 872 | 873 | outer: 874 | for { 875 | count1 := 0 // Number of times in a row that first run won 876 | count2 := 0 // Number of times in a row that second run won 877 | 878 | /* 879 | * Do the straightforward thing until (if ever) one run 880 | * appears to win consistently. 881 | */ 882 | for { 883 | if len1 <= 0 || len2 <= 1 { 884 | return errors.New(" len1 > 0 && len2 > 1;") 885 | } 886 | if lt(tmp[cursor2], a[cursor1]) { 887 | a[dest] = a[cursor1] 888 | dest-- 889 | cursor1-- 890 | count1++ 891 | count2 = 0 892 | len1-- 893 | if len1 == 0 { 894 | break outer 895 | } 896 | } else { 897 | a[dest] = tmp[cursor2] 898 | dest-- 899 | cursor2-- 900 | count2++ 901 | count1 = 0 902 | len2-- 903 | if len2 == 1 { 904 | break outer 905 | } 906 | } 907 | if (count1 | count2) >= minGallop { 908 | break 909 | } 910 | } 911 | 912 | /* 913 | * One run is winning so consistently that galloping may be a 914 | * huge win. So try that, and continue galloping until (if ever) 915 | * neither run appears to be winning consistently anymore. 916 | */ 917 | for { 918 | if len1 <= 0 || len2 <= 1 { 919 | return errors.New(" len1 > 0 && len2 > 1;") 920 | } 921 | if gr, err := gallopRightI(tmp[cursor2], a, base1, len1, len1-1, lt); err == nil { 922 | count1 = len1 - gr 923 | } else { 924 | return err 925 | } 926 | if count1 != 0 { 927 | dest -= count1 928 | cursor1 -= count1 929 | len1 -= count1 930 | copy(a[dest+1:dest+1+count1], a[cursor1+1:cursor1+1+count1]) 931 | if len1 == 0 { 932 | break outer 933 | } 934 | } 935 | a[dest] = tmp[cursor2] 936 | dest-- 937 | cursor2-- 938 | len2-- 939 | if len2 == 1 { 940 | break outer 941 | } 942 | 943 | if gl, err := gallopLeftI(a[cursor1], tmp, 0, len2, len2-1, lt); err == nil { 944 | count2 = len2 - gl 945 | } else { 946 | return err 947 | } 948 | if count2 != 0 { 949 | dest -= count2 950 | cursor2 -= count2 951 | len2 -= count2 952 | copy(a[dest+1:dest+1+count2], tmp[cursor2+1:cursor2+1+count2]) 953 | if len2 <= 1 { // len2 == 1 || len2 == 0 954 | break outer 955 | } 956 | } 957 | a[dest] = a[cursor1] 958 | dest-- 959 | cursor1-- 960 | len1-- 961 | if len1 == 0 { 962 | break outer 963 | } 964 | minGallop-- 965 | 966 | if count1 < minGallop && count2 < minGallop { 967 | break 968 | } 969 | } 970 | if minGallop < 0 { 971 | minGallop = 0 972 | } 973 | minGallop += 2 // Penalize for leaving gallop mode 974 | } // End of "outer" loop 975 | 976 | if minGallop < 1 { 977 | minGallop = 1 978 | } 979 | 980 | hi.minGallop = minGallop // Write back to field 981 | 982 | if len2 == 1 { 983 | if len1 <= 0 { 984 | return errors.New(" len1 > 0;") 985 | } 986 | dest -= len1 987 | cursor1 -= len1 988 | 989 | copy(a[dest+1:dest+1+len1], a[cursor1+1:cursor1+1+len1]) 990 | a[dest] = tmp[cursor2] // Move first elt of run2 to front of merge 991 | } else if len2 == 0 { 992 | return errors.New("comparison method violates its general contract") 993 | } else { 994 | if len1 != 0 { 995 | return errors.New("len1 == 0;") 996 | } 997 | 998 | if len2 <= 0 { 999 | return errors.New(" len2 > 0;") 1000 | } 1001 | 1002 | copy(a[dest-(len2-1):dest+1], tmp) 1003 | } 1004 | return 1005 | } 1006 | 1007 | /** 1008 | * Ensures that the external array tmp has at least the specified 1009 | * number of elements, increasing its size if necessary. The size 1010 | * increases exponentially to ensure amortized linear time complexity. 1011 | * 1012 | * @param minCapacity the minimum required capacity of the tmp array 1013 | * @return tmp, whether or not it grew 1014 | */ 1015 | func (hi *timSortHandlerI) ensureCapacity(minCapacity int) []int { 1016 | if len(hi.tmp) < minCapacity { 1017 | // Compute smallest power of 2 > minCapacity 1018 | newSize := minCapacity 1019 | newSize |= newSize >> 1 1020 | newSize |= newSize >> 2 1021 | newSize |= newSize >> 4 1022 | newSize |= newSize >> 8 1023 | newSize |= newSize >> 16 1024 | newSize++ 1025 | 1026 | if newSize < 0 { // Not bloody likely! 1027 | newSize = minCapacity 1028 | } else { 1029 | ns := len(hi.a) / 2 1030 | if ns < newSize { 1031 | newSize = ns 1032 | } 1033 | } 1034 | 1035 | hi.tmp = make([]int, newSize) 1036 | } 1037 | 1038 | return hi.tmp 1039 | } 1040 | -------------------------------------------------------------------------------- /timsortint_test.go: -------------------------------------------------------------------------------- 1 | package timsort 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "testing" 7 | ) 8 | 9 | func makeTestArrayI(size int) []int { 10 | a := make([]int, size) 11 | 12 | for i := 0; i < size; i++ { 13 | a[i] = i & 0xeeeeee 14 | } 15 | 16 | return a 17 | } 18 | 19 | func IsSortedI(a []int, lessThan IntLessThan) bool { 20 | len := len(a) 21 | 22 | if len < 2 { 23 | return true 24 | } 25 | 26 | prev := a[0] 27 | for i := 1; i < len; i++ { 28 | if lessThan(a[i], prev) { 29 | fmt.Println("false") 30 | return false 31 | } 32 | } 33 | 34 | return true 35 | } 36 | 37 | // use this comparator for sorting 38 | func intLessThan(a, b int) bool { 39 | return a < b 40 | } 41 | 42 | func TestSmokeI(t *testing.T) { 43 | a := []int{3, 1, 2} 44 | 45 | err := Ints(a, intLessThan) 46 | if err != nil { 47 | t.Fatalf("sort: %v", err) 48 | } 49 | 50 | if !IsSortedI(a, intLessThan) { 51 | t.Error("not sorted") 52 | } 53 | } 54 | 55 | func Test1KI(t *testing.T) { 56 | a := makeTestArrayI(1024) 57 | 58 | err := Ints(a, intLessThan) 59 | if err != nil { 60 | fmt.Printf("sort: %v\n", err) 61 | t.Fatalf("sort: %v", err) 62 | } 63 | if !IsSortedI(a, intLessThan) { 64 | t.Error("not sorted") 65 | } 66 | } 67 | 68 | func Test1MI(t *testing.T) { 69 | a := makeTestArrayI(1024 * 1024) 70 | 71 | err := Ints(a, intLessThan) 72 | if err != nil { 73 | t.Fatalf("sort: %v", err) 74 | } 75 | if !IsSortedI(a, intLessThan) { 76 | t.Error("not sorted") 77 | } 78 | } 79 | 80 | func makeRandomArrayI(size int) []int { 81 | a := make([]int, size) 82 | 83 | for i := 0; i < size; i++ { 84 | a[i] = rand.Intn(100) 85 | } 86 | 87 | return a 88 | } 89 | 90 | func TestRandom1MI(t *testing.T) { 91 | size := 1024 * 1024 92 | 93 | a := makeRandomArrayI(size) 94 | b := make([]int, size) 95 | copy(b, a) 96 | 97 | err := Ints(a, intLessThan) 98 | if err != nil { 99 | t.Fatalf("sort: %v", err) 100 | } 101 | if !IsSortedI(a, intLessThan) { 102 | t.Error("not sorted") 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /timsortintf.go: -------------------------------------------------------------------------------- 1 | package timsort 2 | 3 | import ( 4 | "sort" 5 | ) 6 | 7 | // TimSort sorts the data defined by sort.Interface. 8 | func TimSort(a sort.Interface) (err error) { 9 | indexes := make([]int, a.Len()) 10 | for i := 0; i < len(indexes); i++ { 11 | indexes[i] = i 12 | } // for i 13 | 14 | err = Ints(indexes, func(i, j int) bool { 15 | return a.Less(i, j) 16 | }) 17 | 18 | if err != nil { 19 | return err 20 | } // if 21 | 22 | for i := 0; i < len(indexes); i++ { 23 | j := indexes[i] 24 | if j == 0 { 25 | continue 26 | } // if 27 | for k := i; j != i; { 28 | a.Swap(j, k) 29 | k, j, indexes[j] = j, indexes[j], 0 30 | } // for j 31 | } // for i 32 | 33 | return nil 34 | } 35 | -------------------------------------------------------------------------------- /timsortintf_test.go: -------------------------------------------------------------------------------- 1 | package timsort 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "sort" 7 | "testing" 8 | ) 9 | 10 | func TestSmokeTS(t *testing.T) { 11 | a := make([]interface{}, 3) 12 | a[0] = val{3, 0} 13 | a[1] = val{1, 1} 14 | a[2] = val{2, 2} 15 | 16 | err := TimSort(KeyLessThanSlice(a)) 17 | if err != nil { 18 | t.Fatalf("sort: %v", err) 19 | } 20 | 21 | if !IsSorted(a, KeyOrderLessThan) { 22 | t.Error("not sorted") 23 | } 24 | } 25 | 26 | func TestSmokeStabilityTS(t *testing.T) { 27 | a := make([]interface{}, 3) 28 | a[0] = val{3, 0} 29 | a[1] = val{2, 1} 30 | a[2] = val{2, 2} 31 | 32 | err := TimSort(KeyLessThanSlice(a)) 33 | if err != nil { 34 | t.Fatalf("sort: %v", err) 35 | } 36 | 37 | if !IsSorted(a, KeyOrderLessThan) { 38 | t.Error("not sorted") 39 | } 40 | } 41 | 42 | func Test1KTS(t *testing.T) { 43 | a := makeTestArray(1024) 44 | 45 | err := TimSort(KeyLessThanSlice(a)) 46 | if err != nil { 47 | t.Fatalf("sort: %v", err) 48 | } 49 | if !IsSorted(a, KeyOrderLessThan) { 50 | t.Error("not sorted") 51 | } 52 | } 53 | 54 | func Test1MTS(t *testing.T) { 55 | a := makeTestArray(1024 * 1024) 56 | 57 | err := TimSort(KeyLessThanSlice(a)) 58 | if err != nil { 59 | t.Fatalf("sort: %v", err) 60 | } 61 | if !IsSorted(a, KeyOrderLessThan) { 62 | t.Error("not sorted") 63 | } 64 | } 65 | 66 | func TestRandom1MTS(t *testing.T) { 67 | size := 1024 * 1024 68 | 69 | a := makeRandomArray(size) 70 | b := make([]interface{}, size) 71 | copy(b, a) 72 | 73 | err := TimSort(KeyLessThanSlice(a)) 74 | if err != nil { 75 | t.Fatalf("sort: %v", err) 76 | } 77 | if !IsSorted(a, KeyOrderLessThan) { 78 | t.Error("not sorted") 79 | } 80 | 81 | // sort by order 82 | err = TimSort(OrderLessThanSlice(a)) 83 | if err != nil { 84 | t.Fatalf("sort: %v", err) 85 | } 86 | for i := 0; i < len(b); i++ { 87 | if !Equals(b[i], a[i]) { 88 | t.Error("oops") 89 | } 90 | } 91 | } 92 | 93 | func TestBentleyMcIlroyTS(t *testing.T) { 94 | // sizes := []int{100, 1023, 1024, 1025, 1023 * 1023, 1024 * 1024, 1025 * 1025} 95 | sizes := []int{100, 1023, 1024, 1025} 96 | dists := []string{"sawtooth", "rand", "stagger", "plateau", "shuffle"} 97 | modes := []string{"copy", "reverse", "reverse1", "reverse2", "sort", "dither"} 98 | tmp1 := make([]interface{}, 1025*1025) 99 | tmp2 := make([]interface{}, 1025*1025) 100 | for ni := 0; ni < len(sizes); ni++ { 101 | n := sizes[ni] 102 | for m := 1; m < 2*n; m *= 2 { 103 | for dist := 0; dist < _NDist; dist++ { 104 | j := 0 105 | k := 1 106 | data := tmp1[0:n] 107 | for i := 0; i < n; i++ { 108 | switch dist { 109 | case _Sawtooth: 110 | data[i] = val{i % m, i} 111 | case _Rand: 112 | data[i] = val{rand.Intn(m), i} 113 | case _Stagger: 114 | data[i] = val{(i*m + i) % n, i} 115 | case _Plateau: 116 | if i < m { 117 | data[i] = val{i, i} 118 | } else { 119 | data[i] = val{m, i} 120 | } 121 | case _Shuffle: 122 | if rand.Intn(m) != 0 { 123 | j += 2 124 | data[i] = val{j, i} 125 | } else { 126 | k += 2 127 | data[i] = val{k, i} 128 | } 129 | } 130 | } 131 | 132 | mdata := tmp2[0:n] 133 | for mode := 0; mode < _NMode; mode++ { 134 | switch mode { 135 | case _Copy: 136 | for i := 0; i < n; i++ { 137 | mdata[i] = val{data[i].(val).key, i} 138 | } 139 | case _Reverse: 140 | for i := 0; i < n; i++ { 141 | mdata[i] = val{data[n-i-1].(val).key, i} 142 | } 143 | case _ReverseFirstHalf: 144 | for i := 0; i < n/2; i++ { 145 | mdata[i] = val{data[n/2-i-1].(val).key, i} 146 | } 147 | for i := n / 2; i < n; i++ { 148 | mdata[i] = val{data[i].(val).key, i} 149 | } 150 | case _ReverseSecondHalf: 151 | for i := 0; i < n/2; i++ { 152 | mdata[i] = val{data[i].(val).key, i} 153 | } 154 | for i := n / 2; i < n; i++ { 155 | mdata[i] = val{data[n-(i-n/2)-1].(val).key, i} 156 | } 157 | case _Sorted: 158 | for i := 0; i < n; i++ { 159 | mdata[i] = data[i] 160 | } 161 | // SortInts is known to be correct 162 | // because mode Sort runs after mode _Copy. 163 | err := Sort(mdata, KeyLessThan) 164 | if err != nil { 165 | t.Fatalf("Sort: %v", err) 166 | } 167 | case _Dither: 168 | for i := 0; i < n; i++ { 169 | mdata[i] = val{data[i].(val).key + i%5, i} 170 | } 171 | } 172 | 173 | desc := fmt.Sprintf("n=%d m=%d dist=%s mode=%s", n, m, dists[dist], modes[mode]) 174 | 175 | for i := 0; i < len(mdata); i++ { 176 | mdata[i] = val{mdata[i].(val).key, i} 177 | } 178 | 179 | gdata := make([]interface{}, len(mdata)) 180 | copy(gdata, mdata) 181 | 182 | err := TimSort(KeyLessThanSlice(mdata)) 183 | if err != nil { 184 | t.Fatalf("sort: %v", err) 185 | } 186 | 187 | // If we were testing C qsort, we'd have to make a copy 188 | // of the array and sort it ourselves and then compare 189 | // x against it, to ensure that qsort was only permuting 190 | // the data, not (for example) overwriting it with zeros. 191 | // 192 | // In go, we don't have to be so paranoid: since the only 193 | // mutating method Sort can call is TestingData.swap, 194 | // it suffices here just to check that the final array is sorted. 195 | if !IsSorted(mdata, KeyOrderLessThan) { 196 | t.Errorf("%s: ints not sorted", desc) 197 | t.Errorf("\t%v", mdata) 198 | t.FailNow() 199 | } 200 | 201 | err = TimSort(OrderLessThanSlice(mdata)) 202 | if err != nil { 203 | t.Fatalf("sort: %v", err) 204 | } 205 | for i := 0; i < len(data); i++ { 206 | if !Equals(gdata[i], mdata[i]) { 207 | t.Error("restore sort failed") 208 | t.Errorf("gdata=%v", gdata) 209 | t.Errorf("mdata=%v", mdata) 210 | t.Errorf("bad index: %v\n", i) 211 | t.FailNow() 212 | } 213 | } 214 | } 215 | } 216 | } 217 | } 218 | } 219 | 220 | func TestStrings1TS(t *testing.T) { 221 | a := []string{ 222 | "ef", 223 | "abc", 224 | "aaa", 225 | "de", 226 | "ed", 227 | } 228 | if err := TimSort(sort.StringSlice(a)); err != nil { 229 | t.Fatalf("TimSort: %v", err) 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /v2/bench_test.go: -------------------------------------------------------------------------------- 1 | package timsort 2 | 3 | import ( 4 | "math/rand" 5 | "sort" 6 | "testing" 7 | ) 8 | 9 | type record struct { 10 | key, order int 11 | } 12 | 13 | type records []interface{} 14 | 15 | func LessThanByKey(a, b interface{}) bool { 16 | return a.(*record).key < b.(*record).key 17 | } 18 | 19 | type RecordSlice []record 20 | 21 | func (s *RecordSlice) Len() int { 22 | return len(*s) 23 | } 24 | 25 | func (s *RecordSlice) Swap(i, j int) { 26 | (*s)[i], (*s)[j] = (*s)[j], (*s)[i] 27 | } 28 | 29 | func (s *RecordSlice) Less(i, j int) bool { 30 | return (*s)[i].key < (*s)[j].key 31 | } 32 | 33 | func makeVector(size int, shape string) (v records) { 34 | v = make(records, size) 35 | switch shape { 36 | 37 | case "xor": 38 | for i := 0; i < size; i++ { 39 | v[i] = &record{0xff & (i ^ 0xab), i} 40 | } 41 | 42 | case "sorted": 43 | for i := 0; i < size; i++ { 44 | v[i] = &record{i, i} 45 | } 46 | 47 | case "revsorted": 48 | for i := 0; i < size; i++ { 49 | v[i] = &record{size - i, i} 50 | } 51 | 52 | case "random": 53 | rand.Seed(1) 54 | 55 | for i := 0; i < size; i++ { 56 | v[i] = &record{rand.Int(), i} 57 | } 58 | 59 | default: 60 | panic(shape) 61 | } 62 | 63 | return v 64 | } 65 | 66 | func makeRecords(size int, shape string) (v RecordSlice) { 67 | v = make(RecordSlice, size) 68 | switch shape { 69 | 70 | case "xor": 71 | for i := 0; i < size; i++ { 72 | v[i] = record{0xff & (i ^ 0xab), i} 73 | } 74 | 75 | case "sorted": 76 | for i := 0; i < size; i++ { 77 | v[i] = record{i, i} 78 | } 79 | 80 | case "revsorted": 81 | for i := 0; i < size; i++ { 82 | v[i] = record{size - i, i} 83 | } 84 | 85 | case "random": 86 | rand.Seed(1) 87 | 88 | for i := 0; i < size; i++ { 89 | v[i] = record{rand.Int(), i} 90 | } 91 | 92 | default: 93 | panic(shape) 94 | } 95 | 96 | return v 97 | } 98 | 99 | func benchmarkTimsort(b *testing.B, size int, shape string) { 100 | b.StopTimer() 101 | 102 | for j := 0; j < b.N; j++ { 103 | v := makeVector(size, shape) 104 | 105 | b.StartTimer() 106 | Sort(v, LessThanByKey) 107 | b.StopTimer() 108 | } 109 | } 110 | 111 | func benchmarkTimsortInterface(b *testing.B, size int, shape string) { 112 | b.StopTimer() 113 | 114 | for j := 0; j < b.N; j++ { 115 | v := makeRecords(size, shape) 116 | 117 | b.StartTimer() 118 | TimSort(&v) 119 | b.StopTimer() 120 | } 121 | } 122 | 123 | func benchmarkStandardSort(b *testing.B, size int, shape string) { 124 | b.StopTimer() 125 | 126 | for j := 0; j < b.N; j++ { 127 | v := makeRecords(size, shape) 128 | 129 | b.StartTimer() 130 | sort.Stable(&v) 131 | b.StopTimer() 132 | } 133 | } 134 | 135 | func BenchmarkTimsortXor100(b *testing.B) { 136 | benchmarkTimsort(b, 100, "xor") 137 | } 138 | 139 | func BenchmarkTimsortInterXor100(b *testing.B) { 140 | benchmarkTimsortInterface(b, 100, "xor") 141 | } 142 | 143 | func BenchmarkStandardSortXor100(b *testing.B) { 144 | benchmarkStandardSort(b, 100, "xor") 145 | } 146 | 147 | func BenchmarkTimsortSorted100(b *testing.B) { 148 | benchmarkTimsort(b, 100, "sorted") 149 | } 150 | 151 | func BenchmarkTimsortInterSorted100(b *testing.B) { 152 | benchmarkTimsortInterface(b, 100, "sorted") 153 | } 154 | 155 | func BenchmarkStandardSortSorted100(b *testing.B) { 156 | benchmarkStandardSort(b, 100, "sorted") 157 | } 158 | 159 | func BenchmarkTimsortRevSorted100(b *testing.B) { 160 | benchmarkTimsort(b, 100, "revsorted") 161 | } 162 | 163 | func BenchmarkTimsortInterRevSorted100(b *testing.B) { 164 | benchmarkTimsortInterface(b, 100, "revsorted") 165 | } 166 | 167 | func BenchmarkStandardSortRevSorted100(b *testing.B) { 168 | benchmarkStandardSort(b, 100, "revsorted") 169 | } 170 | 171 | func BenchmarkTimsortRandom100(b *testing.B) { 172 | benchmarkTimsort(b, 100, "random") 173 | } 174 | 175 | func BenchmarkTimsortInterRandom100(b *testing.B) { 176 | benchmarkTimsortInterface(b, 100, "random") 177 | } 178 | 179 | func BenchmarkStandardSortRandom100(b *testing.B) { 180 | benchmarkStandardSort(b, 100, "random") 181 | } 182 | 183 | func BenchmarkTimsortXor1K(b *testing.B) { 184 | benchmarkTimsort(b, 1024, "xor") 185 | } 186 | 187 | func BenchmarkTimsortInterXor1K(b *testing.B) { 188 | benchmarkTimsortInterface(b, 1024, "xor") 189 | } 190 | 191 | func BenchmarkStandardSortXor1K(b *testing.B) { 192 | benchmarkStandardSort(b, 1024, "xor") 193 | } 194 | 195 | func BenchmarkTimsortSorted1K(b *testing.B) { 196 | benchmarkTimsort(b, 1024, "sorted") 197 | } 198 | 199 | func BenchmarkTimsortInterSorted1K(b *testing.B) { 200 | benchmarkTimsortInterface(b, 1024, "sorted") 201 | } 202 | 203 | func BenchmarkStandardSortSorted1K(b *testing.B) { 204 | benchmarkStandardSort(b, 1024, "sorted") 205 | } 206 | 207 | func BenchmarkTimsortRevSorted1K(b *testing.B) { 208 | benchmarkTimsort(b, 1024, "revsorted") 209 | } 210 | 211 | func BenchmarkTimsortInterRevSorted1K(b *testing.B) { 212 | benchmarkTimsortInterface(b, 1024, "revsorted") 213 | } 214 | 215 | func BenchmarkStandardSortRevSorted1K(b *testing.B) { 216 | benchmarkStandardSort(b, 1024, "revsorted") 217 | } 218 | 219 | func BenchmarkTimsortRandom1K(b *testing.B) { 220 | benchmarkTimsort(b, 1024, "random") 221 | } 222 | 223 | func BenchmarkTimsortInterRandom1K(b *testing.B) { 224 | benchmarkTimsortInterface(b, 1024, "random") 225 | } 226 | 227 | func BenchmarkStandardSortRandom1K(b *testing.B) { 228 | benchmarkStandardSort(b, 1024, "random") 229 | } 230 | 231 | func BenchmarkTimsortXor1M(b *testing.B) { 232 | benchmarkTimsort(b, 1024*1024, "xor") 233 | } 234 | 235 | func BenchmarkTimsortInterXor1M(b *testing.B) { 236 | benchmarkTimsortInterface(b, 1024*1024, "xor") 237 | } 238 | 239 | func BenchmarkStandardSortXor1M(b *testing.B) { 240 | benchmarkStandardSort(b, 1024*1024, "xor") 241 | } 242 | 243 | func BenchmarkTimsortSorted1M(b *testing.B) { 244 | benchmarkTimsort(b, 1024*1024, "sorted") 245 | } 246 | 247 | func BenchmarkTimsortInterSorted1M(b *testing.B) { 248 | benchmarkTimsortInterface(b, 1024*1024, "sorted") 249 | } 250 | 251 | func BenchmarkStandardSortSorted1M(b *testing.B) { 252 | benchmarkStandardSort(b, 1024*1024, "sorted") 253 | } 254 | 255 | func BenchmarkTimsortRevSorted1M(b *testing.B) { 256 | benchmarkTimsort(b, 1024*1024, "revsorted") 257 | } 258 | 259 | func BenchmarkTimsortInterRevSorted1M(b *testing.B) { 260 | benchmarkTimsortInterface(b, 1024*1024, "revsorted") 261 | } 262 | 263 | func BenchmarkStandardSortRevSorted1M(b *testing.B) { 264 | benchmarkStandardSort(b, 1024*1024, "revsorted") 265 | } 266 | 267 | func BenchmarkTimsortRandom1M(b *testing.B) { 268 | benchmarkTimsort(b, 1024*1024, "random") 269 | } 270 | 271 | func BenchmarkTimsortInterRandom1M(b *testing.B) { 272 | benchmarkTimsortInterface(b, 1024*1024, "random") 273 | } 274 | 275 | func BenchmarkStandardSortRandom1M(b *testing.B) { 276 | benchmarkStandardSort(b, 1024*1024, "random") 277 | } 278 | -------------------------------------------------------------------------------- /v2/benchint_test.go: -------------------------------------------------------------------------------- 1 | package timsort 2 | 3 | import ( 4 | "math/rand" 5 | "sort" 6 | "testing" 7 | ) 8 | 9 | type ints []int 10 | 11 | func (p *ints) Len() int { return len(*p) } 12 | func (p *ints) Less(i, j int) bool { return (*p)[i] < (*p)[j] } 13 | func (p *ints) Swap(i, j int) { (*p)[i], (*p)[j] = (*p)[j], (*p)[i] } 14 | 15 | func LessThanInt(a, b int) bool { 16 | return a < b 17 | } 18 | 19 | func makeInts(size int, shape string) (v ints) { 20 | v = make(ints, 0, size) 21 | switch shape { 22 | 23 | case "xor": 24 | for i := 0; i < size; i++ { 25 | v = append(v, 0xff&(i^0xab)) 26 | } 27 | 28 | case "sorted": 29 | for i := 0; i < size; i++ { 30 | v = append(v, i) 31 | } 32 | 33 | case "revsorted": 34 | for i := 0; i < size; i++ { 35 | v = append(v, size-i) 36 | } 37 | 38 | case "random": 39 | rand.Seed(1) 40 | 41 | for i := 0; i < size; i++ { 42 | v = append(v, rand.Int()) 43 | } 44 | 45 | default: 46 | panic(shape) 47 | } 48 | 49 | return v 50 | } 51 | 52 | func benchmarkTimsortI(b *testing.B, size int, shape string) { 53 | b.StopTimer() 54 | 55 | for j := 0; j < b.N; j++ { 56 | v := makeInts(size, shape) 57 | 58 | b.StartTimer() 59 | Ints(v, LessThanInt) 60 | b.StopTimer() 61 | } 62 | } 63 | 64 | func benchmarkStandardSortI(b *testing.B, size int, shape string) { 65 | b.StopTimer() 66 | 67 | for j := 0; j < b.N; j++ { 68 | v := makeInts(size, shape) 69 | 70 | b.StartTimer() 71 | sort.Sort(&v) 72 | b.StopTimer() 73 | } 74 | } 75 | 76 | func BenchmarkTimsortIXor100(b *testing.B) { 77 | benchmarkTimsortI(b, 100, "xor") 78 | } 79 | 80 | func BenchmarkStandardSortIXor100(b *testing.B) { 81 | benchmarkStandardSortI(b, 100, "xor") 82 | } 83 | 84 | func BenchmarkTimsortISorted100(b *testing.B) { 85 | benchmarkTimsortI(b, 100, "sorted") 86 | } 87 | 88 | func BenchmarkStandardSortISorted100(b *testing.B) { 89 | benchmarkStandardSortI(b, 100, "sorted") 90 | } 91 | 92 | func BenchmarkTimsortIRevSorted100(b *testing.B) { 93 | benchmarkTimsortI(b, 100, "revsorted") 94 | } 95 | 96 | func BenchmarkStandardSortIRevSorted100(b *testing.B) { 97 | benchmarkStandardSortI(b, 100, "revsorted") 98 | } 99 | 100 | func BenchmarkTimsortIRandom100(b *testing.B) { 101 | benchmarkTimsortI(b, 100, "random") 102 | } 103 | 104 | func BenchmarkStandardSortIRandom100(b *testing.B) { 105 | benchmarkStandardSortI(b, 100, "random") 106 | } 107 | 108 | func BenchmarkTimsortIXor1K(b *testing.B) { 109 | benchmarkTimsortI(b, 1024, "xor") 110 | } 111 | 112 | func BenchmarkStandardSortIXor1K(b *testing.B) { 113 | benchmarkStandardSortI(b, 1024, "xor") 114 | } 115 | 116 | func BenchmarkTimsortISorted1K(b *testing.B) { 117 | benchmarkTimsortI(b, 1024, "sorted") 118 | } 119 | 120 | func BenchmarkStandardSortISorted1K(b *testing.B) { 121 | benchmarkStandardSortI(b, 1024, "sorted") 122 | } 123 | 124 | func BenchmarkTimsortIRevSorted1K(b *testing.B) { 125 | benchmarkTimsortI(b, 1024, "revsorted") 126 | } 127 | 128 | func BenchmarkStandardSortIRevSorted1K(b *testing.B) { 129 | benchmarkStandardSortI(b, 1024, "revsorted") 130 | } 131 | 132 | func BenchmarkTimsortIRandom1K(b *testing.B) { 133 | benchmarkTimsortI(b, 1024, "random") 134 | } 135 | 136 | func BenchmarkStandardSortIRandom1K(b *testing.B) { 137 | benchmarkStandardSortI(b, 1024, "random") 138 | } 139 | 140 | func BenchmarkTimsortIXor1M(b *testing.B) { 141 | benchmarkTimsortI(b, 1024*1024, "xor") 142 | } 143 | 144 | func BenchmarkStandardSortIXor1M(b *testing.B) { 145 | benchmarkStandardSortI(b, 1024*1024, "xor") 146 | } 147 | 148 | func BenchmarkTimsortISorted1M(b *testing.B) { 149 | benchmarkTimsortI(b, 1024*1024, "sorted") 150 | } 151 | 152 | func BenchmarkStandardSortISorted1M(b *testing.B) { 153 | benchmarkStandardSortI(b, 1024*1024, "sorted") 154 | } 155 | 156 | func BenchmarkTimsortIRevSorted1M(b *testing.B) { 157 | benchmarkTimsortI(b, 1024*1024, "revsorted") 158 | } 159 | 160 | func BenchmarkStandardSortIRevSorted1M(b *testing.B) { 161 | benchmarkStandardSortI(b, 1024*1024, "revsorted") 162 | } 163 | 164 | func BenchmarkTimsortIRandom1M(b *testing.B) { 165 | benchmarkTimsortI(b, 1024*1024, "random") 166 | } 167 | 168 | func BenchmarkStandardSortIRandom1M(b *testing.B) { 169 | benchmarkStandardSortI(b, 1024*1024, "random") 170 | } 171 | -------------------------------------------------------------------------------- /v2/benchstring_test.go: -------------------------------------------------------------------------------- 1 | package timsort 2 | 3 | import ( 4 | "math/rand" 5 | "sort" 6 | "strconv" 7 | "testing" 8 | ) 9 | 10 | func makeStrings(size int, shape string) (v sort.StringSlice) { 11 | v = make(sort.StringSlice, 0, size) 12 | switch shape { 13 | 14 | case "xor": 15 | for i := 0; i < size; i++ { 16 | v = append(v, strconv.Itoa(0xff&(i^0xab))) 17 | } 18 | 19 | case "sorted": 20 | for i := 0; i < size; i++ { 21 | v = append(v, strconv.Itoa(i)) 22 | } 23 | 24 | case "revsorted": 25 | for i := 0; i < size; i++ { 26 | v = append(v, strconv.Itoa(size-i)) 27 | } 28 | 29 | case "random": 30 | rand.Seed(1) 31 | 32 | for i := 0; i < size; i++ { 33 | v = append(v, strconv.Itoa(rand.Int())) 34 | } 35 | 36 | default: 37 | panic(shape) 38 | } 39 | 40 | return v 41 | } 42 | 43 | func benchmarkTimsortStr(b *testing.B, size int, shape string) { 44 | b.StopTimer() 45 | 46 | for j := 0; j < b.N; j++ { 47 | v := makeStrings(size, shape) 48 | 49 | b.StartTimer() 50 | TimSort(v) 51 | b.StopTimer() 52 | } 53 | } 54 | 55 | func benchmarkStandardSortStr(b *testing.B, size int, shape string) { 56 | b.StopTimer() 57 | 58 | for j := 0; j < b.N; j++ { 59 | v := makeStrings(size, shape) 60 | 61 | b.StartTimer() 62 | sort.Sort(&v) 63 | b.StopTimer() 64 | } 65 | } 66 | 67 | func BenchmarkTimsortStrXor100(b *testing.B) { 68 | benchmarkTimsortStr(b, 100, "xor") 69 | } 70 | 71 | func BenchmarkStandardSortStrXor100(b *testing.B) { 72 | benchmarkStandardSortStr(b, 100, "xor") 73 | } 74 | 75 | func BenchmarkTimsortStrSorted100(b *testing.B) { 76 | benchmarkTimsortStr(b, 100, "sorted") 77 | } 78 | 79 | func BenchmarkStandardSortStrSorted100(b *testing.B) { 80 | benchmarkStandardSortStr(b, 100, "sorted") 81 | } 82 | 83 | func BenchmarkTimsortStrRevSorted100(b *testing.B) { 84 | benchmarkTimsortStr(b, 100, "revsorted") 85 | } 86 | 87 | func BenchmarkStandardSortStrRevSorted100(b *testing.B) { 88 | benchmarkStandardSortStr(b, 100, "revsorted") 89 | } 90 | 91 | func BenchmarkTimsortStrRandom100(b *testing.B) { 92 | benchmarkTimsortStr(b, 100, "random") 93 | } 94 | 95 | func BenchmarkStandardSortStrRandom100(b *testing.B) { 96 | benchmarkStandardSortStr(b, 100, "random") 97 | } 98 | 99 | func BenchmarkTimsortStrXor1K(b *testing.B) { 100 | benchmarkTimsortStr(b, 1024, "xor") 101 | } 102 | 103 | func BenchmarkStandardSortStrXor1K(b *testing.B) { 104 | benchmarkStandardSortStr(b, 1024, "xor") 105 | } 106 | 107 | func BenchmarkTimsortStrSorted1K(b *testing.B) { 108 | benchmarkTimsortStr(b, 1024, "sorted") 109 | } 110 | 111 | func BenchmarkStandardSortStrSorted1K(b *testing.B) { 112 | benchmarkStandardSortStr(b, 1024, "sorted") 113 | } 114 | 115 | func BenchmarkTimsortStrRevSorted1K(b *testing.B) { 116 | benchmarkTimsortStr(b, 1024, "revsorted") 117 | } 118 | 119 | func BenchmarkStandardSortStrRevSorted1K(b *testing.B) { 120 | benchmarkStandardSortStr(b, 1024, "revsorted") 121 | } 122 | 123 | func BenchmarkTimsortStrRandom1K(b *testing.B) { 124 | benchmarkTimsortStr(b, 1024, "random") 125 | } 126 | 127 | func BenchmarkStandardSortStrRandom1K(b *testing.B) { 128 | benchmarkStandardSortStr(b, 1024, "random") 129 | } 130 | 131 | func BenchmarkTimsortStrXor1M(b *testing.B) { 132 | benchmarkTimsortStr(b, 1024*1024, "xor") 133 | } 134 | 135 | func BenchmarkStandardSortStrXor1M(b *testing.B) { 136 | benchmarkStandardSortStr(b, 1024*1024, "xor") 137 | } 138 | 139 | func BenchmarkTimsortStrSorted1M(b *testing.B) { 140 | benchmarkTimsortStr(b, 1024*1024, "sorted") 141 | } 142 | 143 | func BenchmarkStandardSortStrSorted1M(b *testing.B) { 144 | benchmarkStandardSortStr(b, 1024*1024, "sorted") 145 | } 146 | 147 | func BenchmarkTimsortStrRevSorted1M(b *testing.B) { 148 | benchmarkTimsortStr(b, 1024*1024, "revsorted") 149 | } 150 | 151 | func BenchmarkStandardSortStrRevSorted1M(b *testing.B) { 152 | benchmarkStandardSortStr(b, 1024*1024, "revsorted") 153 | } 154 | 155 | func BenchmarkTimsortStrRandom1M(b *testing.B) { 156 | benchmarkTimsortStr(b, 1024*1024, "random") 157 | } 158 | 159 | func BenchmarkStandardSortStrRandom1M(b *testing.B) { 160 | benchmarkStandardSortStr(b, 1024*1024, "random") 161 | } 162 | -------------------------------------------------------------------------------- /v2/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/psilva261/timsort/v2 2 | 3 | go 1.14 4 | -------------------------------------------------------------------------------- /v2/timsort.go: -------------------------------------------------------------------------------- 1 | // Package timsort provides fast stable sort, uses external comparator. 2 | // 3 | // A stable, adaptive, iterative mergesort that requires far fewer than 4 | // n lg(n) comparisons when running on partially sorted arrays, while 5 | // offering performance comparable to a traditional mergesort when run 6 | // on random arrays. Like all proper mergesorts, this sort is stable and 7 | // runs O(n log n) time (worst case). In the worst case, this sort requires 8 | // temporary storage space for n/2 object references; in the best case, 9 | // it requires only a small constant amount of space. 10 | // 11 | // This implementation was derived from Java's TimSort object by Josh Bloch, 12 | // which, in turn, was based on the original code by Tim Peters: 13 | // 14 | // http://svn.python.org/projects/python/trunk/Objects/listsort.txt 15 | // 16 | // Mike K. 17 | package timsort 18 | 19 | const ( 20 | /** 21 | * This is the minimum sized sequence that will be merged. Shorter 22 | * sequences will be lengthened by calling binarySort. If the entire 23 | * array is less than this length, no merges will be performed. 24 | * 25 | * This constant should be a power of two. It was 64 in Tim Peter's C 26 | * implementation, but 32 was empirically determined to work better in 27 | * this implementation. In the unlikely event that you set this constant 28 | * to be a number that's not a power of two, you'll need to change the 29 | * {@link #minRunLength} computation. 30 | * 31 | * If you decrease this constant, you must change the stackLen 32 | * computation in the TimSort constructor, or you risk an 33 | * ArrayOutOfBounds exception. See listsort.txt for a discussion 34 | * of the minimum stack length required as a function of the length 35 | * of the array being sorted and the minimum merge sequence length. 36 | */ 37 | minMerge = 32 38 | // mk: tried higher MIN_MERGE and got slower sorting (348->375) 39 | // c_MIN_MERGE = 64 40 | 41 | /** 42 | * When we get into galloping mode, we stay there until both runs win less 43 | * often than cminGallop consecutive times. 44 | */ 45 | minGallop = 7 46 | 47 | /** 48 | * Maximum initial size of tmp array, which is used for merging. The array 49 | * can grow to accommodate demand. 50 | * 51 | * Unlike Tim's original C version, we do not allocate this much storage 52 | * when sorting smaller arrays. This change was required for performance. 53 | */ 54 | initialTmpStorageLength = 256 55 | ) 56 | 57 | // LessThan is Delegate type that sorting uses as a comparator 58 | type LessThan func(a, b interface{}) bool 59 | 60 | type timSortHandler struct { 61 | 62 | /** 63 | * The array being sorted. 64 | */ 65 | a []interface{} 66 | 67 | /** 68 | * The comparator for this sort. 69 | */ 70 | lt LessThan 71 | 72 | /** 73 | * This controls when we get *into* galloping mode. It is initialized 74 | * to cminGallop. The mergeLo and mergeHi methods nudge it higher for 75 | * random data, and lower for highly structured data. 76 | */ 77 | minGallop int 78 | 79 | /** 80 | * Temp storage for merges. 81 | */ 82 | tmp []interface{} // Actual runtime type will be Object[], regardless of T 83 | 84 | /** 85 | * A stack of pending runs yet to be merged. Run i starts at 86 | * address base[i] and extends for len[i] elements. It's always 87 | * true (so long as the indices are in bounds) that: 88 | * 89 | * runBase[i] + runLen[i] == runBase[i + 1] 90 | * 91 | * so we could cut the storage for this, but it's a minor amount, 92 | * and keeping all the info explicit simplifies the code. 93 | */ 94 | stackSize int // Number of pending runs on stack 95 | runBase []int 96 | runLen []int 97 | } 98 | 99 | /** 100 | * Creates a TimSort instance to maintain the state of an ongoing sort. 101 | * 102 | * @param a the array to be sorted 103 | * @param c the comparator to determine the order of the sort 104 | */ 105 | func newTimSort(a []interface{}, lt LessThan) (h *timSortHandler) { 106 | h = new(timSortHandler) 107 | 108 | h.a = a 109 | h.lt = lt 110 | h.minGallop = minGallop 111 | h.stackSize = 0 112 | 113 | // Allocate temp storage (which may be increased later if necessary) 114 | len := len(a) 115 | 116 | tmpSize := initialTmpStorageLength 117 | if len < 2*tmpSize { 118 | tmpSize = len / 2 119 | } 120 | 121 | h.tmp = make([]interface{}, tmpSize) 122 | 123 | /* 124 | * Allocate runs-to-be-merged stack (which cannot be expanded). The 125 | * stack length requirements are described in listsort.txt. The C 126 | * version always uses the same stack length (85), but this was 127 | * measured to be too expensive when sorting "mid-sized" arrays (e.g., 128 | * 100 elements) in Java. Therefore, we use smaller (but sufficiently 129 | * large) stack lengths for smaller arrays. The "magic numbers" in the 130 | * computation below must be changed if c_MIN_MERGE is decreased. See 131 | * the c_MIN_MERGE declaration above for more information. 132 | */ 133 | // mk: confirmed that for small sorts this optimization gives measurable (albeit small) 134 | // performance enhancement 135 | stackLen := 40 136 | if len < 120 { 137 | stackLen = 5 138 | } else if len < 1542 { 139 | stackLen = 10 140 | } else if len < 119151 { 141 | stackLen = 19 142 | } 143 | 144 | h.runBase = make([]int, stackLen) 145 | h.runLen = make([]int, stackLen) 146 | 147 | return h 148 | } 149 | 150 | // Sort an array using the provided comparator 151 | func Sort(a []interface{}, lt LessThan) { 152 | lo := 0 153 | hi := len(a) 154 | nRemaining := hi 155 | 156 | if nRemaining < 2 { 157 | return // Arrays of size 0 and 1 are always sorted 158 | } 159 | 160 | // If array is small, do a "mini-TimSort" with no merges 161 | if nRemaining < minMerge { 162 | initRunLen := countRunAndMakeAscending(a, lo, hi, lt) 163 | 164 | binarySort(a, lo, hi, lo+initRunLen, lt) 165 | return 166 | } 167 | 168 | /** 169 | * March over the array once, left to right, finding natural runs, 170 | * extending short natural runs to minRun elements, and merging runs 171 | * to maintain stack invariant. 172 | */ 173 | 174 | ts := newTimSort(a, lt) 175 | minRun := minRunLength(nRemaining) 176 | for { 177 | // Identify next run 178 | runLen := countRunAndMakeAscending(a, lo, hi, lt) 179 | 180 | // If run is short, extend to min(minRun, nRemaining) 181 | if runLen < minRun { 182 | force := minRun 183 | if nRemaining <= minRun { 184 | force = nRemaining 185 | } 186 | binarySort(a, lo, lo+force, lo+runLen, lt) 187 | runLen = force 188 | } 189 | 190 | // Push run onto pending-run stack, and maybe merge 191 | ts.pushRun(lo, runLen) 192 | ts.mergeCollapse() 193 | 194 | // Advance to find next run 195 | lo += runLen 196 | nRemaining -= runLen 197 | if nRemaining == 0 { 198 | break 199 | } 200 | } 201 | 202 | ts.mergeForceCollapse() 203 | } 204 | 205 | /** 206 | * Sorts the specified portion of the specified array using a binary 207 | * insertion sort. This is the best method for sorting small numbers 208 | * of elements. It requires O(n log n) compares, but O(n^2) data 209 | * movement (worst case). 210 | * 211 | * If the initial part of the specified range is already sorted, 212 | * this method can take advantage of it: the method assumes that the 213 | * elements from index {@code lo}, inclusive, to {@code start}, 214 | * exclusive are already sorted. 215 | * 216 | * @param a the array in which a range is to be sorted 217 | * @param lo the index of the first element in the range to be sorted 218 | * @param hi the index after the last element in the range to be sorted 219 | * @param start the index of the first element in the range that is 220 | * not already known to be sorted (@code lo <= start <= hi} 221 | * @param c comparator to used for the sort 222 | */ 223 | func binarySort(a []interface{}, lo, hi, start int, lt LessThan) { 224 | if start == lo { 225 | start++ 226 | } 227 | 228 | for ; start < hi; start++ { 229 | pivot := a[start] 230 | 231 | // Set left (and right) to the index where a[start] (pivot) belongs 232 | left := lo 233 | right := start 234 | 235 | /* 236 | * Invariants: 237 | * pivot >= all in [lo, left). 238 | * pivot < all in [right, start). 239 | */ 240 | for left < right { 241 | mid := int(uint(left+right) >> 1) 242 | if lt(pivot, a[mid]) { 243 | right = mid 244 | } else { 245 | left = mid + 1 246 | } 247 | } 248 | 249 | /* 250 | * The invariants still hold: pivot >= all in [lo, left) and 251 | * pivot < all in [left, start), so pivot belongs at left. Note 252 | * that if there are elements equal to pivot, left points to the 253 | * first slot after them -- that's why this sort is stable. 254 | * Slide elements over to make room to make room for pivot. 255 | */ 256 | n := start - left // The number of elements to move 257 | // just an optimization for copy in default case 258 | if n <= 2 { 259 | if n == 2 { 260 | a[left+2] = a[left+1] 261 | } 262 | if n > 0 { 263 | a[left+1] = a[left] 264 | } 265 | } else { 266 | copy(a[left+1:], a[left:left+n]) 267 | } 268 | a[left] = pivot 269 | } 270 | } 271 | 272 | /** 273 | * Returns the length of the run beginning at the specified position in 274 | * the specified array and reverses the run if it is descending (ensuring 275 | * that the run will always be ascending when the method returns). 276 | * 277 | * A run is the longest ascending sequence with: 278 | * 279 | * a[lo] <= a[lo + 1] <= a[lo + 2] <= ... 280 | * 281 | * or the longest descending sequence with: 282 | * 283 | * a[lo] > a[lo + 1] > a[lo + 2] > ... 284 | * 285 | * For its intended use in a stable mergesort, the strictness of the 286 | * definition of "descending" is needed so that the call can safely 287 | * reverse a descending sequence without violating stability. 288 | * 289 | * @param a the array in which a run is to be counted and possibly reversed 290 | * @param lo index of the first element in the run 291 | * @param hi index after the last element that may be contained in the run. 292 | It is required that @code{lo < hi}. 293 | * @param c the comparator to used for the sort 294 | * @return the length of the run beginning at the specified position in 295 | * the specified array 296 | */ 297 | func countRunAndMakeAscending(a []interface{}, lo, hi int, lt LessThan) int { 298 | runHi := lo + 1 299 | if runHi == hi { 300 | return 1 301 | } 302 | 303 | // Find end of run, and reverse range if descending 304 | if lt(a[runHi], a[lo]) { // Descending 305 | runHi++ 306 | 307 | for runHi < hi && lt(a[runHi], a[runHi-1]) { 308 | runHi++ 309 | } 310 | reverseRange(a, lo, runHi) 311 | } else { // Ascending 312 | for runHi < hi && !lt(a[runHi], a[runHi-1]) { 313 | runHi++ 314 | } 315 | } 316 | 317 | return runHi - lo 318 | } 319 | 320 | /** 321 | * Reverse the specified range of the specified array. 322 | * 323 | * @param a the array in which a range is to be reversed 324 | * @param lo the index of the first element in the range to be reversed 325 | * @param hi the index after the last element in the range to be reversed 326 | */ 327 | func reverseRange(a []interface{}, lo, hi int) { 328 | hi-- 329 | for lo < hi { 330 | a[lo], a[hi] = a[hi], a[lo] 331 | lo++ 332 | hi-- 333 | } 334 | } 335 | 336 | /** 337 | * Returns the minimum acceptable run length for an array of the specified 338 | * length. Natural runs shorter than this will be extended with 339 | * {@link #binarySort}. 340 | * 341 | * Roughly speaking, the computation is: 342 | * 343 | * If n < c_MIN_MERGE, return n (it's too small to bother with fancy stuff). 344 | * Else if n is an exact power of 2, return c_MIN_MERGE/2. 345 | * Else return an int k, c_MIN_MERGE/2 <= k <= c_MIN_MERGE, such that n/k 346 | * is close to, but strictly less than, an exact power of 2. 347 | * 348 | * For the rationale, see listsort.txt. 349 | * 350 | * @param n the length of the array to be sorted 351 | * @return the length of the minimum run to be merged 352 | */ 353 | func minRunLength(n int) int { 354 | r := 0 // Becomes 1 if any 1 bits are shifted off 355 | for n >= minMerge { 356 | r |= (n & 1) 357 | n >>= 1 358 | } 359 | return n + r 360 | } 361 | 362 | /** 363 | * Pushes the specified run onto the pending-run stack. 364 | * 365 | * @param runBase index of the first element in the run 366 | * @param runLen the number of elements in the run 367 | */ 368 | func (h *timSortHandler) pushRun(runBase, runLen int) { 369 | h.runBase[h.stackSize] = runBase 370 | h.runLen[h.stackSize] = runLen 371 | h.stackSize++ 372 | } 373 | 374 | /** 375 | * Examines the stack of runs waiting to be merged and merges adjacent runs 376 | * until the stack invariants are reestablished: 377 | * 378 | * 1. runLen[i - 3] > runLen[i - 2] + runLen[i - 1] 379 | * 2. runLen[i - 2] > runLen[i - 1] 380 | * 381 | * This method is called each time a new run is pushed onto the stack, 382 | * so the invariants are guaranteed to hold for i < stackSize upon 383 | * entry to the method. 384 | */ 385 | func (h *timSortHandler) mergeCollapse() { 386 | for h.stackSize > 1 { 387 | n := h.stackSize - 2 388 | if (n > 0 && h.runLen[n-1] <= h.runLen[n]+h.runLen[n+1]) || 389 | (n > 1 && h.runLen[n-2] <= h.runLen[n-1]+h.runLen[n]) { 390 | if h.runLen[n-1] < h.runLen[n+1] { 391 | n-- 392 | } 393 | h.mergeAt(n) 394 | } else if h.runLen[n] <= h.runLen[n+1] { 395 | h.mergeAt(n) 396 | } else { 397 | break // Invariant is established 398 | } 399 | } 400 | } 401 | 402 | /** 403 | * Merges all runs on the stack until only one remains. This method is 404 | * called once, to complete the sort. 405 | */ 406 | func (h *timSortHandler) mergeForceCollapse() { 407 | for h.stackSize > 1 { 408 | n := h.stackSize - 2 409 | if n > 0 && h.runLen[n-1] < h.runLen[n+1] { 410 | n-- 411 | } 412 | h.mergeAt(n) 413 | } 414 | } 415 | 416 | /** 417 | * Merges the two runs at stack indices i and i+1. Run i must be 418 | * the penultimate or antepenultimate run on the stack. In other words, 419 | * i must be equal to stackSize-2 or stackSize-3. 420 | * 421 | * @param i stack index of the first of the two runs to merge 422 | */ 423 | func (h *timSortHandler) mergeAt(i int) { 424 | base1 := h.runBase[i] 425 | len1 := h.runLen[i] 426 | base2 := h.runBase[i+1] 427 | len2 := h.runLen[i+1] 428 | 429 | /* 430 | * Record the length of the combined runs; if i is the 3rd-last 431 | * run now, also slide over the last run (which isn't involved 432 | * in this merge). The current run (i+1) goes away in any case. 433 | */ 434 | h.runLen[i] = len1 + len2 435 | if i == h.stackSize-3 { 436 | h.runBase[i+1] = h.runBase[i+2] 437 | h.runLen[i+1] = h.runLen[i+2] 438 | } 439 | h.stackSize-- 440 | 441 | /* 442 | * Find where the first element of run2 goes in run1. Prior elements 443 | * in run1 can be ignored (because they're already in place). 444 | */ 445 | k := gallopRight(h.a[base2], h.a, base1, len1, 0, h.lt) 446 | base1 += k 447 | len1 -= k 448 | if len1 == 0 { 449 | return 450 | } 451 | 452 | /* 453 | * Find where the last element of run1 goes in run2. Subsequent elements 454 | * in run2 can be ignored (because they're already in place). 455 | */ 456 | len2 = gallopLeft(h.a[base1+len1-1], h.a, base2, len2, len2-1, h.lt) 457 | if len2 == 0 { 458 | return 459 | } 460 | 461 | // Merge remaining runs, using tmp array with min(len1, len2) elements 462 | if len1 <= len2 { 463 | h.mergeLo(base1, len1, base2, len2) 464 | } else { 465 | h.mergeHi(base1, len1, base2, len2) 466 | } 467 | } 468 | 469 | /** 470 | * Locates the position at which to insert the specified key into the 471 | * specified sorted range; if the range contains an element equal to key, 472 | * returns the index of the leftmost equal element. 473 | * 474 | * @param key the key whose insertion point to search for 475 | * @param a the array in which to search 476 | * @param base the index of the first element in the range 477 | * @param len the length of the range; must be > 0 478 | * @param hint the index at which to begin the search, 0 <= hint < n. 479 | * The closer hint is to the result, the faster this method will run. 480 | * @param c the comparator used to order the range, and to search 481 | * @return the int k, 0 <= k <= n such that a[b + k - 1] < key <= a[b + k], 482 | * pretending that a[b - 1] is minus infinity and a[b + n] is infinity. 483 | * In other words, key belongs at index b + k; or in other words, 484 | * the first k elements of a should precede key, and the last n - k 485 | * should follow it. 486 | */ 487 | func gallopLeft(key interface{}, a []interface{}, base, len, hint int, c LessThan) int { 488 | lastOfs := 0 489 | ofs := 1 490 | 491 | if c(a[base+hint], key) { 492 | // Gallop right until a[base+hint+lastOfs] < key <= a[base+hint+ofs] 493 | maxOfs := len - hint 494 | for ofs < maxOfs && c(a[base+hint+ofs], key) { 495 | lastOfs = ofs 496 | ofs = (ofs << 1) + 1 497 | if ofs <= 0 { // int overflow 498 | ofs = maxOfs 499 | } 500 | } 501 | if ofs > maxOfs { 502 | ofs = maxOfs 503 | } 504 | 505 | // Make offsets relative to base 506 | lastOfs += hint 507 | ofs += hint 508 | } else { // key <= a[base + hint] 509 | // Gallop left until a[base+hint-ofs] < key <= a[base+hint-lastOfs] 510 | maxOfs := hint + 1 511 | for ofs < maxOfs && !c(a[base+hint-ofs], key) { 512 | lastOfs = ofs 513 | ofs = (ofs << 1) + 1 514 | if ofs <= 0 { // int overflow 515 | ofs = maxOfs 516 | } 517 | } 518 | if ofs > maxOfs { 519 | ofs = maxOfs 520 | } 521 | 522 | // Make offsets relative to base 523 | tmp := lastOfs 524 | lastOfs = hint - ofs 525 | ofs = hint - tmp 526 | } 527 | 528 | /* 529 | * Now a[base+lastOfs] < key <= a[base+ofs], so key belongs somewhere 530 | * to the right of lastOfs but no farther right than ofs. Do a binary 531 | * search, with invariant a[base + lastOfs - 1] < key <= a[base + ofs]. 532 | */ 533 | lastOfs++ 534 | for lastOfs < ofs { 535 | m := lastOfs + (ofs-lastOfs)/2 536 | 537 | if c(a[base+m], key) { 538 | lastOfs = m + 1 // a[base + m] < key 539 | } else { 540 | ofs = m // key <= a[base + m] 541 | } 542 | } 543 | 544 | return ofs 545 | } 546 | 547 | /** 548 | * Like gallopLeft, except that if the range contains an element equal to 549 | * key, gallopRight returns the index after the rightmost equal element. 550 | * 551 | * @param key the key whose insertion point to search for 552 | * @param a the array in which to search 553 | * @param base the index of the first element in the range 554 | * @param len the length of the range; must be > 0 555 | * @param hint the index at which to begin the search, 0 <= hint < n. 556 | * The closer hint is to the result, the faster this method will run. 557 | * @param c the comparator used to order the range, and to search 558 | * @return the int k, 0 <= k <= n such that a[b + k - 1] <= key < a[b + k] 559 | */ 560 | func gallopRight(key interface{}, a []interface{}, base, len, hint int, c LessThan) int { 561 | ofs := 1 562 | lastOfs := 0 563 | if c(key, a[base+hint]) { 564 | // Gallop left until a[b+hint - ofs] <= key < a[b+hint - lastOfs] 565 | maxOfs := hint + 1 566 | for ofs < maxOfs && c(key, a[base+hint-ofs]) { 567 | lastOfs = ofs 568 | ofs = (ofs << 1) + 1 569 | if ofs <= 0 { // int overflow 570 | ofs = maxOfs 571 | } 572 | } 573 | if ofs > maxOfs { 574 | ofs = maxOfs 575 | } 576 | 577 | // Make offsets relative to b 578 | tmp := lastOfs 579 | lastOfs = hint - ofs 580 | ofs = hint - tmp 581 | } else { // a[b + hint] <= key 582 | // Gallop right until a[b+hint + lastOfs] <= key < a[b+hint + ofs] 583 | maxOfs := len - hint 584 | for ofs < maxOfs && !c(key, a[base+hint+ofs]) { 585 | lastOfs = ofs 586 | ofs = (ofs << 1) + 1 587 | if ofs <= 0 { // int overflow 588 | ofs = maxOfs 589 | } 590 | } 591 | if ofs > maxOfs { 592 | ofs = maxOfs 593 | } 594 | 595 | // Make offsets relative to b 596 | lastOfs += hint 597 | ofs += hint 598 | } 599 | 600 | /* 601 | * Now a[b + lastOfs] <= key < a[b + ofs], so key belongs somewhere to 602 | * the right of lastOfs but no farther right than ofs. Do a binary 603 | * search, with invariant a[b + lastOfs - 1] <= key < a[b + ofs]. 604 | */ 605 | lastOfs++ 606 | for lastOfs < ofs { 607 | m := lastOfs + (ofs-lastOfs)/2 608 | 609 | if c(key, a[base+m]) { 610 | ofs = m // key < a[b + m] 611 | } else { 612 | lastOfs = m + 1 // a[b + m] <= key 613 | } 614 | } 615 | return ofs 616 | } 617 | 618 | /** 619 | * Merges two adjacent runs in place, in a stable fashion. The first 620 | * element of the first run must be greater than the first element of the 621 | * second run (a[base1] > a[base2]), and the last element of the first run 622 | * (a[base1 + len1-1]) must be greater than all elements of the second run. 623 | * 624 | * For performance, this method should be called only when len1 <= len2; 625 | * its twin, mergeHi should be called if len1 >= len2. (Either method 626 | * may be called if len1 == len2.) 627 | * 628 | * @param base1 index of first element in first run to be merged 629 | * @param len1 length of first run to be merged (must be > 0) 630 | * @param base2 index of first element in second run to be merged 631 | * (must be aBase + aLen) 632 | * @param len2 length of second run to be merged (must be > 0) 633 | */ 634 | func (h *timSortHandler) mergeLo(base1, len1, base2, len2 int) { 635 | // Copy first run into temp array 636 | a := h.a // For performance 637 | tmp := h.ensureCapacity(len1) 638 | 639 | copy(tmp, a[base1:base1+len1]) 640 | 641 | cursor1 := 0 // Indexes into tmp array 642 | cursor2 := base2 // Indexes int a 643 | dest := base1 // Indexes int a 644 | 645 | // Move first element of second run and deal with degenerate cases 646 | a[dest] = a[cursor2] 647 | dest++ 648 | cursor2++ 649 | len2-- 650 | if len2 == 0 { 651 | copy(a[dest:dest+len1], tmp) 652 | return 653 | } 654 | if len1 == 1 { 655 | copy(a[dest:dest+len2], a[cursor2:cursor2+len2]) 656 | a[dest+len2] = tmp[cursor1] // Last elt of run 1 to end of merge 657 | return 658 | } 659 | 660 | lt := h.lt // Use local variable for performance 661 | minGallop := h.minGallop // " " " " " 662 | 663 | outer: 664 | for { 665 | count1 := 0 // Number of times in a row that first run won 666 | count2 := 0 // Number of times in a row that second run won 667 | 668 | /* 669 | * Do the straightforward thing until (if ever) one run starts 670 | * winning consistently. 671 | */ 672 | for { 673 | if lt(a[cursor2], tmp[cursor1]) { 674 | a[dest] = a[cursor2] 675 | dest++ 676 | cursor2++ 677 | count2++ 678 | count1 = 0 679 | len2-- 680 | if len2 == 0 { 681 | break outer 682 | } 683 | } else { 684 | a[dest] = tmp[cursor1] 685 | dest++ 686 | cursor1++ 687 | count1++ 688 | count2 = 0 689 | len1-- 690 | if len1 == 1 { 691 | break outer 692 | } 693 | } 694 | if (count1 | count2) >= minGallop { 695 | break 696 | } 697 | } 698 | 699 | /* 700 | * One run is winning so consistently that galloping may be a 701 | * huge win. So try that, and continue galloping until (if ever) 702 | * neither run appears to be winning consistently anymore. 703 | */ 704 | for { 705 | count1 = gallopRight(a[cursor2], tmp, cursor1, len1, 0, lt) 706 | if count1 != 0 { 707 | copy(a[dest:dest+count1], tmp[cursor1:cursor1+count1]) 708 | dest += count1 709 | cursor1 += count1 710 | len1 -= count1 711 | if len1 <= 1 { // len1 == 1 || len1 == 0 712 | break outer 713 | } 714 | } 715 | a[dest] = a[cursor2] 716 | dest++ 717 | cursor2++ 718 | len2-- 719 | if len2 == 0 { 720 | break outer 721 | } 722 | 723 | count2 = gallopLeft(tmp[cursor1], a, cursor2, len2, 0, lt) 724 | if count2 != 0 { 725 | copy(a[dest:dest+count2], a[cursor2:cursor2+count2]) 726 | dest += count2 727 | cursor2 += count2 728 | len2 -= count2 729 | if len2 == 0 { 730 | break outer 731 | } 732 | } 733 | a[dest] = tmp[cursor1] 734 | dest++ 735 | cursor1++ 736 | len1-- 737 | if len1 == 1 { 738 | break outer 739 | } 740 | minGallop-- 741 | if count1 < minGallop && count2 < minGallop { 742 | break 743 | } 744 | } 745 | if minGallop < 0 { 746 | minGallop = 0 747 | } 748 | minGallop += 2 // Penalize for leaving gallop mode 749 | } // End of "outer" loop 750 | 751 | if minGallop < 1 { 752 | minGallop = 1 753 | } 754 | h.minGallop = minGallop // Write back to field 755 | 756 | if len1 == 1 { 757 | 758 | copy(a[dest:dest+len2], a[cursor2:cursor2+len2]) 759 | a[dest+len2] = tmp[cursor1] // Last elt of run 1 to end of merge 760 | } else { 761 | copy(a[dest:dest+len1], tmp[cursor1:cursor1+len1]) 762 | } 763 | } 764 | 765 | /** 766 | * Like mergeLo, except that this method should be called only if 767 | * len1 >= len2; mergeLo should be called if len1 <= len2. (Either method 768 | * may be called if len1 == len2.) 769 | * 770 | * @param base1 index of first element in first run to be merged 771 | * @param len1 length of first run to be merged (must be > 0) 772 | * @param base2 index of first element in second run to be merged 773 | * (must be aBase + aLen) 774 | * @param len2 length of second run to be merged (must be > 0) 775 | */ 776 | func (h *timSortHandler) mergeHi(base1, len1, base2, len2 int) { 777 | // Copy second run into temp array 778 | a := h.a // For performance 779 | tmp := h.ensureCapacity(len2) 780 | 781 | copy(tmp, a[base2:base2+len2]) 782 | 783 | cursor1 := base1 + len1 - 1 // Indexes into a 784 | cursor2 := len2 - 1 // Indexes into tmp array 785 | dest := base2 + len2 - 1 // Indexes into a 786 | 787 | // Move last element of first run and deal with degenerate cases 788 | a[dest] = a[cursor1] 789 | dest-- 790 | cursor1-- 791 | len1-- 792 | if len1 == 0 { 793 | dest -= len2 - 1 794 | copy(a[dest:dest+len2], tmp) 795 | return 796 | } 797 | if len2 == 1 { 798 | dest -= len1 - 1 799 | cursor1 -= len1 - 1 800 | copy(a[dest:dest+len1], a[cursor1:cursor1+len1]) 801 | a[dest-1] = tmp[cursor2] 802 | return 803 | } 804 | 805 | lt := h.lt // Use local variable for performance 806 | minGallop := h.minGallop // " " " " " 807 | 808 | outer: 809 | for { 810 | count1 := 0 // Number of times in a row that first run won 811 | count2 := 0 // Number of times in a row that second run won 812 | 813 | /* 814 | * Do the straightforward thing until (if ever) one run 815 | * appears to win consistently. 816 | */ 817 | for { 818 | if lt(tmp[cursor2], a[cursor1]) { 819 | a[dest] = a[cursor1] 820 | dest-- 821 | cursor1-- 822 | count1++ 823 | count2 = 0 824 | len1-- 825 | if len1 == 0 { 826 | break outer 827 | } 828 | } else { 829 | a[dest] = tmp[cursor2] 830 | dest-- 831 | cursor2-- 832 | count2++ 833 | count1 = 0 834 | len2-- 835 | if len2 == 1 { 836 | break outer 837 | } 838 | } 839 | if (count1 | count2) >= minGallop { 840 | break 841 | } 842 | } 843 | 844 | /* 845 | * One run is winning so consistently that galloping may be a 846 | * huge win. So try that, and continue galloping until (if ever) 847 | * neither run appears to be winning consistently anymore. 848 | */ 849 | for { 850 | gr := gallopRight(tmp[cursor2], a, base1, len1, len1-1, lt) 851 | count1 = len1 - gr 852 | if count1 != 0 { 853 | dest -= count1 854 | cursor1 -= count1 855 | len1 -= count1 856 | copy(a[dest+1:dest+1+count1], a[cursor1+1:cursor1+1+count1]) 857 | if len1 == 0 { 858 | break outer 859 | } 860 | } 861 | a[dest] = tmp[cursor2] 862 | dest-- 863 | cursor2-- 864 | len2-- 865 | if len2 == 1 { 866 | break outer 867 | } 868 | 869 | gl := gallopLeft(a[cursor1], tmp, 0, len2, len2-1, lt) 870 | count2 = len2 - gl 871 | if count2 != 0 { 872 | dest -= count2 873 | cursor2 -= count2 874 | len2 -= count2 875 | copy(a[dest+1:dest+1+count2], tmp[cursor2+1:cursor2+1+count2]) 876 | if len2 <= 1 { // len2 == 1 || len2 == 0 877 | break outer 878 | } 879 | } 880 | a[dest] = a[cursor1] 881 | dest-- 882 | cursor1-- 883 | len1-- 884 | if len1 == 0 { 885 | break outer 886 | } 887 | minGallop-- 888 | 889 | if count1 < minGallop && count2 < minGallop { 890 | break 891 | } 892 | } 893 | if minGallop < 0 { 894 | minGallop = 0 895 | } 896 | minGallop += 2 // Penalize for leaving gallop mode 897 | } // End of "outer" loop 898 | 899 | if minGallop < 1 { 900 | minGallop = 1 901 | } 902 | 903 | h.minGallop = minGallop // Write back to field 904 | 905 | if len2 == 1 { 906 | dest -= len1 907 | cursor1 -= len1 908 | 909 | copy(a[dest+1:dest+1+len1], a[cursor1+1:cursor1+1+len1]) 910 | a[dest] = tmp[cursor2] // Move first elt of run2 to front of merge 911 | } else { 912 | copy(a[dest-(len2-1):dest+1], tmp) 913 | } 914 | } 915 | 916 | /** 917 | * Ensures that the external array tmp has at least the specified 918 | * number of elements, increasing its size if necessary. The size 919 | * increases exponentially to ensure amortized linear time complexity. 920 | * 921 | * @param minCapacity the minimum required capacity of the tmp array 922 | * @return tmp, whether or not it grew 923 | */ 924 | func (h *timSortHandler) ensureCapacity(minCapacity int) []interface{} { 925 | if len(h.tmp) < minCapacity { 926 | // Compute smallest power of 2 > minCapacity 927 | newSize := minCapacity 928 | newSize |= newSize >> 1 929 | newSize |= newSize >> 2 930 | newSize |= newSize >> 4 931 | newSize |= newSize >> 8 932 | newSize |= newSize >> 16 933 | newSize++ 934 | 935 | if newSize < 0 { // Not bloody likely! 936 | newSize = minCapacity 937 | } else { 938 | ns := len(h.a) / 2 939 | if ns < newSize { 940 | newSize = ns 941 | } 942 | } 943 | 944 | h.tmp = make([]interface{}, newSize) 945 | } 946 | 947 | return h.tmp 948 | } 949 | -------------------------------------------------------------------------------- /v2/timsort_test.go: -------------------------------------------------------------------------------- 1 | package timsort 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "testing" 7 | ) 8 | 9 | type val struct { 10 | key, order int 11 | } 12 | 13 | func makeTestArray(size int) []interface{} { 14 | a := make([]interface{}, size) 15 | 16 | for i := 0; i < size; i++ { 17 | a[i] = val{i & 0xeeeeee, i} 18 | } 19 | 20 | return a 21 | } 22 | 23 | func IsSorted(a []interface{}, lessThan LessThan) bool { 24 | len := len(a) 25 | 26 | if len < 2 { 27 | return true 28 | } 29 | 30 | prev := a[0] 31 | for i := 1; i < len; i++ { 32 | if lessThan(a[i], prev) { 33 | return false 34 | } 35 | prev = a[i] 36 | } 37 | 38 | return true 39 | } 40 | 41 | func TestIsSorted(t *testing.T) { 42 | a := make([]interface{}, 5) 43 | a[0] = val{3, 1} 44 | a[1] = val{1, 5} 45 | a[2] = val{2, 3} 46 | a[3] = val{3, 4} 47 | a[4] = val{4, 5} 48 | 49 | if IsSorted(a, OrderLessThan) { 50 | t.Error("Sorted") 51 | } 52 | 53 | } 54 | 55 | // use this comparator for sorting 56 | func KeyLessThan(a, b interface{}) bool { 57 | return a.(val).key < b.(val).key 58 | } 59 | 60 | type KeyLessThanSlice []interface{} 61 | 62 | func (s KeyLessThanSlice) Len() int { 63 | return len(s) 64 | } 65 | 66 | func (s KeyLessThanSlice) Swap(i, j int) { 67 | s[i], s[j] = s[j], s[i] 68 | } 69 | 70 | func (s KeyLessThanSlice) Less(i, j int) bool { 71 | return s[i].(val).key < s[j].(val).key 72 | } 73 | 74 | // use this comparator to validate sorted data (and prove its stable) 75 | func KeyOrderLessThan(a, b interface{}) bool { 76 | if a.(val).key < b.(val).key { 77 | return true 78 | } else if a.(val).key == b.(val).key { 79 | return a.(val).order < b.(val).order 80 | } 81 | 82 | return false 83 | } 84 | 85 | // use this comparator to restore the original order of elements (by sorting on order field) 86 | func OrderLessThan(a, b interface{}) bool { 87 | return a.(val).order < b.(val).order 88 | } 89 | 90 | type OrderLessThanSlice []interface{} 91 | 92 | func (s OrderLessThanSlice) Len() int { 93 | return len(s) 94 | } 95 | 96 | func (s OrderLessThanSlice) Swap(i, j int) { 97 | s[i], s[j] = s[j], s[i] 98 | } 99 | 100 | func (s OrderLessThanSlice) Less(i, j int) bool { 101 | return s[i].(val).order < s[j].(val).order 102 | } 103 | 104 | func TestSmoke(t *testing.T) { 105 | a := make([]interface{}, 3) 106 | a[0] = val{3, 0} 107 | a[1] = val{1, 1} 108 | a[2] = val{2, 2} 109 | 110 | Sort(a, KeyLessThan) 111 | 112 | if !IsSorted(a, KeyOrderLessThan) { 113 | t.Error("not sorted") 114 | } 115 | } 116 | 117 | func TestSmokeStability(t *testing.T) { 118 | a := make([]interface{}, 3) 119 | a[0] = val{3, 0} 120 | a[1] = val{2, 1} 121 | a[2] = val{2, 2} 122 | 123 | Sort(a, KeyLessThan) 124 | 125 | if !IsSorted(a, KeyOrderLessThan) { 126 | t.Error("not sorted") 127 | } 128 | } 129 | 130 | func Test0(t *testing.T) { 131 | a := makeTestArray(0) 132 | 133 | Sort(a, KeyLessThan) 134 | if !IsSorted(a, KeyOrderLessThan) { 135 | t.Error("not sorted") 136 | } 137 | } 138 | 139 | func Test1(t *testing.T) { 140 | a := makeTestArray(1) 141 | 142 | Sort(a, KeyLessThan) 143 | if !IsSorted(a, KeyOrderLessThan) { 144 | t.Error("not sorted") 145 | } 146 | } 147 | 148 | func Test1K(t *testing.T) { 149 | a := makeTestArray(1024) 150 | 151 | Sort(a, KeyLessThan) 152 | if !IsSorted(a, KeyOrderLessThan) { 153 | t.Error("not sorted") 154 | } 155 | } 156 | 157 | func Test100K(t *testing.T) { 158 | a := makeTestArray(100 * 1024) 159 | 160 | Sort(a, KeyLessThan) 161 | if !IsSorted(a, KeyOrderLessThan) { 162 | t.Error("not sorted") 163 | } 164 | } 165 | 166 | func Test1M(t *testing.T) { 167 | a := makeTestArray(1024 * 1024) 168 | 169 | Sort(a, KeyLessThan) 170 | if !IsSorted(a, KeyOrderLessThan) { 171 | t.Error("not sorted") 172 | } 173 | } 174 | 175 | func TestConst(t *testing.T) { 176 | a := []interface{}{val{1, 1}, val{1, 1}, val{1, 1}} 177 | 178 | Sort(a, KeyLessThan) 179 | if !IsSorted(a, KeyOrderLessThan) { 180 | t.Error("not sorted") 181 | } 182 | } 183 | 184 | func makeRandomArray(size int) []interface{} { 185 | a := make([]interface{}, size) 186 | 187 | for i := 0; i < size; i++ { 188 | a[i] = val{rand.Intn(100), i} 189 | } 190 | 191 | return a 192 | } 193 | 194 | func Equals(a, b interface{}) bool { 195 | return a.(val).key == b.(val).key && a.(val).order == b.(val).order 196 | } 197 | 198 | func TestRandom1M(t *testing.T) { 199 | size := 1024 * 1024 200 | 201 | a := makeRandomArray(size) 202 | b := make([]interface{}, size) 203 | copy(b, a) 204 | 205 | Sort(a, KeyLessThan) 206 | if !IsSorted(a, KeyOrderLessThan) { 207 | t.Error("not sorted") 208 | } 209 | 210 | // sort by order 211 | Sort(a, OrderLessThan) 212 | for i := 0; i < len(b); i++ { 213 | if !Equals(b[i], a[i]) { 214 | t.Error("oops") 215 | } 216 | } 217 | } 218 | 219 | const ( 220 | _Sawtooth = iota 221 | _Rand 222 | _Stagger 223 | _Plateau 224 | _Shuffle 225 | _NDist 226 | ) 227 | 228 | const ( 229 | _Copy = iota 230 | _Reverse 231 | _ReverseFirstHalf 232 | _ReverseSecondHalf 233 | _Sorted 234 | _Dither 235 | _NMode 236 | ) 237 | 238 | func TestBentleyMcIlroy(t *testing.T) { 239 | // sizes := []int{100, 1023, 1024, 1025, 1023 * 1023, 1024 * 1024, 1025 * 1025} 240 | sizes := []int{100, 1023, 1024, 1025} 241 | dists := []string{"sawtooth", "rand", "stagger", "plateau", "shuffle"} 242 | modes := []string{"copy", "reverse", "reverse1", "reverse2", "sort", "dither"} 243 | tmp1 := make([]interface{}, 1025*1025) 244 | tmp2 := make([]interface{}, 1025*1025) 245 | for ni := 0; ni < len(sizes); ni++ { 246 | n := sizes[ni] 247 | for m := 1; m < 2*n; m *= 2 { 248 | for dist := 0; dist < _NDist; dist++ { 249 | j := 0 250 | k := 1 251 | data := tmp1[0:n] 252 | for i := 0; i < n; i++ { 253 | switch dist { 254 | case _Sawtooth: 255 | data[i] = val{i % m, i} 256 | case _Rand: 257 | data[i] = val{rand.Intn(m), i} 258 | case _Stagger: 259 | data[i] = val{(i*m + i) % n, i} 260 | case _Plateau: 261 | if i < m { 262 | data[i] = val{i, i} 263 | } else { 264 | data[i] = val{m, i} 265 | } 266 | case _Shuffle: 267 | if rand.Intn(m) != 0 { 268 | j += 2 269 | data[i] = val{j, i} 270 | } else { 271 | k += 2 272 | data[i] = val{k, i} 273 | } 274 | } 275 | } 276 | 277 | mdata := tmp2[0:n] 278 | for mode := 0; mode < _NMode; mode++ { 279 | switch mode { 280 | case _Copy: 281 | for i := 0; i < n; i++ { 282 | mdata[i] = val{data[i].(val).key, i} 283 | } 284 | case _Reverse: 285 | for i := 0; i < n; i++ { 286 | mdata[i] = val{data[n-i-1].(val).key, i} 287 | } 288 | case _ReverseFirstHalf: 289 | for i := 0; i < n/2; i++ { 290 | mdata[i] = val{data[n/2-i-1].(val).key, i} 291 | } 292 | for i := n / 2; i < n; i++ { 293 | mdata[i] = val{data[i].(val).key, i} 294 | } 295 | case _ReverseSecondHalf: 296 | for i := 0; i < n/2; i++ { 297 | mdata[i] = val{data[i].(val).key, i} 298 | } 299 | for i := n / 2; i < n; i++ { 300 | mdata[i] = val{data[n-(i-n/2)-1].(val).key, i} 301 | } 302 | case _Sorted: 303 | for i := 0; i < n; i++ { 304 | mdata[i] = data[i] 305 | } 306 | // SortInts is known to be correct 307 | // because mode Sort runs after mode _Copy. 308 | Sort(mdata, KeyLessThan) 309 | case _Dither: 310 | for i := 0; i < n; i++ { 311 | mdata[i] = val{data[i].(val).key + i%5, i} 312 | } 313 | } 314 | 315 | desc := fmt.Sprintf("n=%d m=%d dist=%s mode=%s", n, m, dists[dist], modes[mode]) 316 | 317 | for i := 0; i < len(mdata); i++ { 318 | mdata[i] = val{mdata[i].(val).key, i} 319 | } 320 | 321 | gdata := make([]interface{}, len(mdata)) 322 | copy(gdata, mdata) 323 | 324 | Sort(mdata, KeyLessThan) 325 | 326 | // If we were testing C qsort, we'd have to make a copy 327 | // of the array and sort it ourselves and then compare 328 | // x against it, to ensure that qsort was only permuting 329 | // the data, not (for example) overwriting it with zeros. 330 | // 331 | // In go, we don't have to be so paranoid: since the only 332 | // mutating method Sort can call is TestingData.swap, 333 | // it suffices here just to check that the final array is sorted. 334 | if !IsSorted(mdata, KeyOrderLessThan) { 335 | t.Errorf("%s: ints not sorted", desc) 336 | t.Errorf("\t%v", mdata) 337 | t.FailNow() 338 | } 339 | 340 | Sort(mdata, OrderLessThan) 341 | for i := 0; i < len(data); i++ { 342 | if !Equals(gdata[i], mdata[i]) { 343 | t.Error("restore sort failed") 344 | t.Errorf("gdata=%v", gdata) 345 | t.Errorf("mdata=%v", mdata) 346 | t.Errorf("bad index: %v\n", i) 347 | t.FailNow() 348 | } 349 | } 350 | } 351 | } 352 | } 353 | } 354 | } 355 | -------------------------------------------------------------------------------- /v2/timsortint.go: -------------------------------------------------------------------------------- 1 | package timsort 2 | 3 | import () 4 | 5 | // IntLessThan is a Delegate type that sorting uses as a comparator 6 | type IntLessThan func(a, b int) bool 7 | 8 | type timSortHandlerI struct { 9 | 10 | /** 11 | * The array being sorted. 12 | */ 13 | a []int 14 | 15 | /** 16 | * The comparator for this sort. 17 | */ 18 | lt IntLessThan 19 | 20 | /** 21 | * This controls when we get *into* galloping mode. It is initialized 22 | * to c_MIN_GALLOP. The mergeLo and mergeHi methods nudge it higher for 23 | * random data, and lower for highly structured data. 24 | */ 25 | minGallop int 26 | 27 | /** 28 | * Temp storage for merges. 29 | */ 30 | tmp []int // Actual runtime type will be Object[], regardless of T 31 | 32 | /** 33 | * A stack of pending runs yet to be merged. Run i starts at 34 | * address base[i] and extends for len[i] elements. It's always 35 | * true (so long as the indices are in bounds) that: 36 | * 37 | * runBase[i] + runLen[i] == runBase[i + 1] 38 | * 39 | * so we could cut the storage for this, but it's a minor amount, 40 | * and keeping all the info explicit simplifies the code. 41 | */ 42 | stackSize int // Number of pending runs on stack 43 | runBase []int 44 | runLen []int 45 | } 46 | 47 | /** 48 | * Creates a TimSort instance to maintain the state of an ongoing sort. 49 | * 50 | * @param a the array to be sorted 51 | * @param c the comparator to determine the order of the sort 52 | */ 53 | func newTimSortI(a []int, lt IntLessThan) (hi *timSortHandlerI) { 54 | hi = &timSortHandlerI{ 55 | a: a, 56 | lt: lt, 57 | minGallop: minGallop} 58 | 59 | // Allocate temp storage (which may be increased later if necessary) 60 | len := len(a) 61 | 62 | tmpSize := initialTmpStorageLength 63 | if len < 2*tmpSize { 64 | tmpSize = len / 2 65 | } 66 | 67 | hi.tmp = make([]int, tmpSize) 68 | 69 | /* 70 | * Allocate runs-to-be-merged stack (which cannot be expanded). The 71 | * stack length requirements are described in listsort.txt. The C 72 | * version always uses the same stack length (85), but this was 73 | * measured to be too expensive when sorting "mid-sized" arrays (e.g., 74 | * 100 elements) in Java. Therefore, we use smaller (but sufficiently 75 | * large) stack lengths for smaller arrays. The "magic numbers" in the 76 | * computation below must be changed if c_MIN_MERGE is decreased. See 77 | * the c_MIN_MERGE declaration above for more information. 78 | */ 79 | // mk: confirmed that for small sorts this optimization gives measurable (albeit small) 80 | // performance enhancement 81 | stackLen := 40 82 | if len < 120 { 83 | stackLen = 5 84 | } else if len < 1542 { 85 | stackLen = 10 86 | } else if len < 119151 { 87 | stackLen = 19 88 | } 89 | 90 | hi.runBase = make([]int, stackLen) 91 | hi.runLen = make([]int, stackLen) 92 | 93 | return hi 94 | } 95 | 96 | // Ints sorts an interger array using the provided comparator 97 | func Ints(a []int, lt IntLessThan) { 98 | lo := 0 99 | hi := len(a) 100 | nRemaining := hi 101 | 102 | if nRemaining < 2 { 103 | return // Arrays of size 0 and 1 are always sorted 104 | } 105 | 106 | // If array is small, do a "mini-TimSort" with no merges 107 | if nRemaining < minMerge { 108 | initRunLen := countRunAndMakeAscendingI(a, lo, hi, lt) 109 | 110 | binarySortI(a, lo, hi, lo+initRunLen, lt) 111 | return 112 | } 113 | 114 | /** 115 | * March over the array once, left to right, finding natural runs, 116 | * extending short natural runs to minRun elements, and merging runs 117 | * to maintain stack invariant. 118 | */ 119 | 120 | ts := newTimSortI(a, lt) 121 | minRun := minRunLength(nRemaining) 122 | 123 | for { 124 | // Identify next run 125 | runLen := countRunAndMakeAscendingI(a, lo, hi, lt) 126 | 127 | // If run is short, extend to min(minRun, nRemaining) 128 | if runLen < minRun { 129 | force := minRun 130 | if nRemaining <= minRun { 131 | force = nRemaining 132 | } 133 | binarySortI(a, lo, lo+force, lo+runLen, lt) 134 | runLen = force 135 | } 136 | 137 | // Push run onto pending-run stack, and maybe merge 138 | ts.pushRun(lo, runLen) 139 | ts.mergeCollapse() 140 | 141 | // Advance to find next run 142 | lo += runLen 143 | nRemaining -= runLen 144 | if nRemaining == 0 { 145 | break 146 | } 147 | } 148 | 149 | ts.mergeForceCollapse() 150 | 151 | } 152 | 153 | /** 154 | * Sorts the specified portion of the specified array using a binary 155 | * insertion sort. This is the best method for sorting small numbers 156 | * of elements. It requires O(n log n) compares, but O(n^2) data 157 | * movement (worst case). 158 | * 159 | * If the initial part of the specified range is already sorted, 160 | * this method can take advantage of it: the method assumes that the 161 | * elements from index {@code lo}, inclusive, to {@code start}, 162 | * exclusive are already sorted. 163 | * 164 | * @param a the array in which a range is to be sorted 165 | * @param lo the index of the first element in the range to be sorted 166 | * @param hi the index after the last element in the range to be sorted 167 | * @param start the index of the first element in the range that is 168 | * not already known to be sorted (@code lo <= start <= hi} 169 | * @param c comparator to used for the sort 170 | */ 171 | func binarySortI(a []int, lo, hi, start int, lt IntLessThan) { 172 | if start == lo { 173 | start++ 174 | } 175 | 176 | for ; start < hi; start++ { 177 | pivot := a[start] 178 | 179 | // Set left (and right) to the index where a[start] (pivot) belongs 180 | left := lo 181 | right := start 182 | 183 | /* 184 | * Invariants: 185 | * pivot >= all in [lo, left). 186 | * pivot < all in [right, start). 187 | */ 188 | for left < right { 189 | mid := int(uint(left+right) >> 1) 190 | if lt(pivot, a[mid]) { 191 | right = mid 192 | } else { 193 | left = mid + 1 194 | } 195 | } 196 | 197 | /* 198 | * The invariants still hold: pivot >= all in [lo, left) and 199 | * pivot < all in [left, start), so pivot belongs at left. Note 200 | * that if there are elements equal to pivot, left points to the 201 | * first slot after them -- that's why this sort is stable. 202 | * Slide elements over to make room to make room for pivot. 203 | */ 204 | n := start - left // The number of elements to move 205 | // just an optimization for copy in default case 206 | if n <= 2 { 207 | if n == 2 { 208 | a[left+2] = a[left+1] 209 | } 210 | if n > 0 { 211 | a[left+1] = a[left] 212 | } 213 | } else { 214 | copy(a[left+1:], a[left:left+n]) 215 | } 216 | a[left] = pivot 217 | } 218 | } 219 | 220 | /** 221 | * Returns the length of the run beginning at the specified position in 222 | * the specified array and reverses the run if it is descending (ensuring 223 | * that the run will always be ascending when the method returns). 224 | * 225 | * A run is the longest ascending sequence with: 226 | * 227 | * a[lo] <= a[lo + 1] <= a[lo + 2] <= ... 228 | * 229 | * or the longest descending sequence with: 230 | * 231 | * a[lo] > a[lo + 1] > a[lo + 2] > ... 232 | * 233 | * For its intended use in a stable mergesort, the strictness of the 234 | * definition of "descending" is needed so that the call can safely 235 | * reverse a descending sequence without violating stability. 236 | * 237 | * @param a the array in which a run is to be counted and possibly reversed 238 | * @param lo index of the first element in the run 239 | * @param hi index after the last element that may be contained in the run. 240 | It is required that @code{lo < hi}. 241 | * @param c the comparator to used for the sort 242 | * @return the length of the run beginning at the specified position in 243 | * the specified array 244 | */ 245 | func countRunAndMakeAscendingI(a []int, lo, hi int, lt IntLessThan) int { 246 | runHi := lo + 1 247 | if runHi == hi { 248 | return 1 249 | } 250 | 251 | // Find end of run, and reverse range if descending 252 | if lt(a[runHi], a[lo]) { // Descending 253 | runHi++ 254 | 255 | for runHi < hi && lt(a[runHi], a[runHi-1]) { 256 | runHi++ 257 | } 258 | reverseRangeI(a, lo, runHi) 259 | } else { // Ascending 260 | for runHi < hi && !lt(a[runHi], a[runHi-1]) { 261 | runHi++ 262 | } 263 | } 264 | 265 | return runHi - lo 266 | } 267 | 268 | /** 269 | * Reverse the specified range of the specified array. 270 | * 271 | * @param a the array in which a range is to be reversed 272 | * @param lo the index of the first element in the range to be reversed 273 | * @param hi the index after the last element in the range to be reversed 274 | */ 275 | func reverseRangeI(a []int, lo, hi int) { 276 | hi-- 277 | for lo < hi { 278 | a[lo], a[hi] = a[hi], a[lo] 279 | lo++ 280 | hi-- 281 | } 282 | } 283 | 284 | /** 285 | * Pushes the specified run onto the pending-run stack. 286 | * 287 | * @param runBase index of the first element in the run 288 | * @param runLen the number of elements in the run 289 | */ 290 | func (hi *timSortHandlerI) pushRun(runBase, runLen int) { 291 | hi.runBase[hi.stackSize] = runBase 292 | hi.runLen[hi.stackSize] = runLen 293 | hi.stackSize++ 294 | } 295 | 296 | /** 297 | * Examines the stack of runs waiting to be merged and merges adjacent runs 298 | * until the stack invariants are reestablished: 299 | * 300 | * 1. runLen[i - 3] > runLen[i - 2] + runLen[i - 1] 301 | * 2. runLen[i - 2] > runLen[i - 1] 302 | * 303 | * This method is called each time a new run is pushed onto the stack, 304 | * so the invariants are guaranteed to hold for i < stackSize upon 305 | * entry to the method. 306 | */ 307 | func (hi *timSortHandlerI) mergeCollapse() { 308 | for hi.stackSize > 1 { 309 | n := hi.stackSize - 2 310 | if (n > 0 && hi.runLen[n-1] <= hi.runLen[n]+hi.runLen[n+1]) || 311 | (n > 1 && hi.runLen[n-2] <= hi.runLen[n-1]+hi.runLen[n]) { 312 | if hi.runLen[n-1] < hi.runLen[n+1] { 313 | n-- 314 | } 315 | hi.mergeAt(n) 316 | } else if hi.runLen[n] <= hi.runLen[n+1] { 317 | hi.mergeAt(n) 318 | } else { 319 | break // Invariant is established 320 | } 321 | } 322 | } 323 | 324 | /** 325 | * Merges all runs on the stack until only one remains. This method is 326 | * called once, to complete the sort. 327 | */ 328 | func (hi *timSortHandlerI) mergeForceCollapse() { 329 | for hi.stackSize > 1 { 330 | n := hi.stackSize - 2 331 | if n > 0 && hi.runLen[n-1] < hi.runLen[n+1] { 332 | n-- 333 | } 334 | hi.mergeAt(n) 335 | } 336 | } 337 | 338 | /** 339 | * Merges the two runs at stack indices i and i+1. Run i must be 340 | * the penultimate or antepenultimate run on the stack. In other words, 341 | * i must be equal to stackSize-2 or stackSize-3. 342 | * 343 | * @param i stack index of the first of the two runs to merge 344 | */ 345 | func (hi *timSortHandlerI) mergeAt(i int) { 346 | base1 := hi.runBase[i] 347 | len1 := hi.runLen[i] 348 | base2 := hi.runBase[i+1] 349 | len2 := hi.runLen[i+1] 350 | 351 | /* 352 | * Record the length of the combined runs; if i is the 3rd-last 353 | * run now, also slide over the last run (which isn't involved 354 | * in this merge). The current run (i+1) goes away in any case. 355 | */ 356 | hi.runLen[i] = len1 + len2 357 | if i == hi.stackSize-3 { 358 | hi.runBase[i+1] = hi.runBase[i+2] 359 | hi.runLen[i+1] = hi.runLen[i+2] 360 | } 361 | hi.stackSize-- 362 | 363 | /* 364 | * Find where the first element of run2 goes in run1. Prior elements 365 | * in run1 can be ignored (because they're already in place). 366 | */ 367 | k := gallopRightI(hi.a[base2], hi.a, base1, len1, 0, hi.lt) 368 | base1 += k 369 | len1 -= k 370 | if len1 == 0 { 371 | return 372 | } 373 | 374 | /* 375 | * Find where the last element of run1 goes in run2. Subsequent elements 376 | * in run2 can be ignored (because they're already in place). 377 | */ 378 | len2 = gallopLeftI(hi.a[base1+len1-1], hi.a, base2, len2, len2-1, hi.lt) 379 | if len2 == 0 { 380 | return 381 | } 382 | 383 | // Merge remaining runs, using tmp array with min(len1, len2) elements 384 | if len1 <= len2 { 385 | hi.mergeLo(base1, len1, base2, len2) 386 | } else { 387 | hi.mergeHi(base1, len1, base2, len2) 388 | } 389 | } 390 | 391 | /** 392 | * Locates the position at which to insert the specified key into the 393 | * specified sorted range; if the range contains an element equal to key, 394 | * returns the index of the leftmost equal element. 395 | * 396 | * @param key the key whose insertion point to search for 397 | * @param a the array in which to search 398 | * @param base the index of the first element in the range 399 | * @param len the length of the range; must be > 0 400 | * @param hint the index at which to begin the search, 0 <= hint < n. 401 | * The closer hint is to the result, the faster this method will run. 402 | * @param c the comparator used to order the range, and to search 403 | * @return the int k, 0 <= k <= n such that a[b + k - 1] < key <= a[b + k], 404 | * pretending that a[b - 1] is minus infinity and a[b + n] is infinity. 405 | * In other words, key belongs at index b + k; or in other words, 406 | * the first k elements of a should precede key, and the last n - k 407 | * should follow it. 408 | */ 409 | func gallopLeftI(key int, a []int, base, len, hint int, c IntLessThan) int { 410 | lastOfs := 0 411 | ofs := 1 412 | 413 | if c(a[base+hint], key) { 414 | // Gallop right until a[base+hint+lastOfs] < key <= a[base+hint+ofs] 415 | maxOfs := len - hint 416 | for ofs < maxOfs && c(a[base+hint+ofs], key) { 417 | lastOfs = ofs 418 | ofs = (ofs << 1) + 1 419 | if ofs <= 0 { // int overflow 420 | ofs = maxOfs 421 | } 422 | } 423 | if ofs > maxOfs { 424 | ofs = maxOfs 425 | } 426 | 427 | // Make offsets relative to base 428 | lastOfs += hint 429 | ofs += hint 430 | } else { // key <= a[base + hint] 431 | // Gallop left until a[base+hint-ofs] < key <= a[base+hint-lastOfs] 432 | maxOfs := hint + 1 433 | for ofs < maxOfs && !c(a[base+hint-ofs], key) { 434 | lastOfs = ofs 435 | ofs = (ofs << 1) + 1 436 | if ofs <= 0 { // int overflow 437 | ofs = maxOfs 438 | } 439 | } 440 | if ofs > maxOfs { 441 | ofs = maxOfs 442 | } 443 | 444 | // Make offsets relative to base 445 | tmp := lastOfs 446 | lastOfs = hint - ofs 447 | ofs = hint - tmp 448 | } 449 | 450 | /* 451 | * Now a[base+lastOfs] < key <= a[base+ofs], so key belongs somewhere 452 | * to the right of lastOfs but no farther right than ofs. Do a binary 453 | * search, with invariant a[base + lastOfs - 1] < key <= a[base + ofs]. 454 | */ 455 | lastOfs++ 456 | for lastOfs < ofs { 457 | m := lastOfs + (ofs-lastOfs)/2 458 | 459 | if c(a[base+m], key) { 460 | lastOfs = m + 1 // a[base + m] < key 461 | } else { 462 | ofs = m // key <= a[base + m] 463 | } 464 | } 465 | 466 | return ofs 467 | } 468 | 469 | /** 470 | * Like gallopLeft, except that if the range contains an element equal to 471 | * key, gallopRight returns the index after the rightmost equal element. 472 | * 473 | * @param key the key whose insertion point to search for 474 | * @param a the array in which to search 475 | * @param base the index of the first element in the range 476 | * @param len the length of the range; must be > 0 477 | * @param hint the index at which to begin the search, 0 <= hint < n. 478 | * The closer hint is to the result, the faster this method will run. 479 | * @param c the comparator used to order the range, and to search 480 | * @return the int k, 0 <= k <= n such that a[b + k - 1] <= key < a[b + k] 481 | */ 482 | func gallopRightI(key int, a []int, base, len, hint int, c IntLessThan) int { 483 | ofs := 1 484 | lastOfs := 0 485 | if c(key, a[base+hint]) { 486 | // Gallop left until a[b+hint - ofs] <= key < a[b+hint - lastOfs] 487 | maxOfs := hint + 1 488 | for ofs < maxOfs && c(key, a[base+hint-ofs]) { 489 | lastOfs = ofs 490 | ofs = (ofs << 1) + 1 491 | if ofs <= 0 { // int overflow 492 | ofs = maxOfs 493 | } 494 | } 495 | if ofs > maxOfs { 496 | ofs = maxOfs 497 | } 498 | 499 | // Make offsets relative to b 500 | tmp := lastOfs 501 | lastOfs = hint - ofs 502 | ofs = hint - tmp 503 | } else { // a[b + hint] <= key 504 | // Gallop right until a[b+hint + lastOfs] <= key < a[b+hint + ofs] 505 | maxOfs := len - hint 506 | for ofs < maxOfs && !c(key, a[base+hint+ofs]) { 507 | lastOfs = ofs 508 | ofs = (ofs << 1) + 1 509 | if ofs <= 0 { // int overflow 510 | ofs = maxOfs 511 | } 512 | } 513 | if ofs > maxOfs { 514 | ofs = maxOfs 515 | } 516 | 517 | // Make offsets relative to b 518 | lastOfs += hint 519 | ofs += hint 520 | } 521 | 522 | /* 523 | * Now a[b + lastOfs] <= key < a[b + ofs], so key belongs somewhere to 524 | * the right of lastOfs but no farther right than ofs. Do a binary 525 | * search, with invariant a[b + lastOfs - 1] <= key < a[b + ofs]. 526 | */ 527 | lastOfs++ 528 | for lastOfs < ofs { 529 | m := lastOfs + (ofs-lastOfs)/2 530 | 531 | if c(key, a[base+m]) { 532 | ofs = m // key < a[b + m] 533 | } else { 534 | lastOfs = m + 1 // a[b + m] <= key 535 | } 536 | } 537 | 538 | return ofs 539 | } 540 | 541 | /** 542 | * Merges two adjacent runs in place, in a stable fashion. The first 543 | * element of the first run must be greater than the first element of the 544 | * second run (a[base1] > a[base2]), and the last element of the first run 545 | * (a[base1 + len1-1]) must be greater than all elements of the second run. 546 | * 547 | * For performance, this method should be called only when len1 <= len2; 548 | * its twin, mergeHi should be called if len1 >= len2. (Either method 549 | * may be called if len1 == len2.) 550 | * 551 | * @param base1 index of first element in first run to be merged 552 | * @param len1 length of first run to be merged (must be > 0) 553 | * @param base2 index of first element in second run to be merged 554 | * (must be aBase + aLen) 555 | * @param len2 length of second run to be merged (must be > 0) 556 | */ 557 | func (hi *timSortHandlerI) mergeLo(base1, len1, base2, len2 int) { 558 | // Copy first run into temp array 559 | a := hi.a // For performance 560 | tmp := hi.ensureCapacity(len1) 561 | 562 | copy(tmp, a[base1:base1+len1]) 563 | 564 | cursor1 := 0 // Indexes into tmp array 565 | cursor2 := base2 // Indexes int a 566 | dest := base1 // Indexes int a 567 | 568 | // Move first element of second run and deal with degenerate cases 569 | a[dest] = a[cursor2] 570 | dest++ 571 | cursor2++ 572 | len2-- 573 | if len2 == 0 { 574 | copy(a[dest:dest+len1], tmp) 575 | return 576 | } 577 | if len1 == 1 { 578 | copy(a[dest:dest+len2], a[cursor2:cursor2+len2]) 579 | a[dest+len2] = tmp[cursor1] // Last elt of run 1 to end of merge 580 | return 581 | } 582 | 583 | lt := hi.lt // Use local variable for performance 584 | minGallop := hi.minGallop // " " " " " 585 | 586 | outer: 587 | for { 588 | count1 := 0 // Number of times in a row that first run won 589 | count2 := 0 // Number of times in a row that second run won 590 | 591 | /* 592 | * Do the straightforward thing until (if ever) one run starts 593 | * winning consistently. 594 | */ 595 | for { 596 | if lt(a[cursor2], tmp[cursor1]) { 597 | a[dest] = a[cursor2] 598 | dest++ 599 | cursor2++ 600 | count2++ 601 | count1 = 0 602 | len2-- 603 | if len2 == 0 { 604 | break outer 605 | } 606 | } else { 607 | a[dest] = tmp[cursor1] 608 | dest++ 609 | cursor1++ 610 | count1++ 611 | count2 = 0 612 | len1-- 613 | if len1 == 1 { 614 | break outer 615 | } 616 | } 617 | if (count1 | count2) >= minGallop { 618 | break 619 | } 620 | } 621 | 622 | /* 623 | * One run is winning so consistently that galloping may be a 624 | * huge win. So try that, and continue galloping until (if ever) 625 | * neither run appears to be winning consistently anymore. 626 | */ 627 | for { 628 | count1 = gallopRightI(a[cursor2], tmp, cursor1, len1, 0, lt) 629 | if count1 != 0 { 630 | copy(a[dest:dest+count1], tmp[cursor1:cursor1+count1]) 631 | dest += count1 632 | cursor1 += count1 633 | len1 -= count1 634 | if len1 <= 1 { // len1 == 1 || len1 == 0 635 | break outer 636 | } 637 | } 638 | a[dest] = a[cursor2] 639 | dest++ 640 | cursor2++ 641 | len2-- 642 | if len2 == 0 { 643 | break outer 644 | } 645 | 646 | count2 = gallopLeftI(tmp[cursor1], a, cursor2, len2, 0, lt) 647 | if count2 != 0 { 648 | copy(a[dest:dest+count2], a[cursor2:cursor2+count2]) 649 | dest += count2 650 | cursor2 += count2 651 | len2 -= count2 652 | if len2 == 0 { 653 | break outer 654 | } 655 | } 656 | a[dest] = tmp[cursor1] 657 | dest++ 658 | cursor1++ 659 | len1-- 660 | if len1 == 1 { 661 | break outer 662 | } 663 | minGallop-- 664 | if count1 < minGallop && count2 < minGallop { 665 | break 666 | } 667 | } 668 | if minGallop < 0 { 669 | minGallop = 0 670 | } 671 | minGallop += 2 // Penalize for leaving gallop mode 672 | } // End of "outer" loop 673 | 674 | if minGallop < 1 { 675 | minGallop = 1 676 | } 677 | hi.minGallop = minGallop // Write back to field 678 | 679 | if len1 == 1 { 680 | copy(a[dest:dest+len2], a[cursor2:cursor2+len2]) 681 | a[dest+len2] = tmp[cursor1] // Last elt of run 1 to end of merge 682 | } else { 683 | copy(a[dest:dest+len1], tmp[cursor1:cursor1+len1]) 684 | } 685 | } 686 | 687 | /** 688 | * Like mergeLo, except that this method should be called only if 689 | * len1 >= len2; mergeLo should be called if len1 <= len2. (Either method 690 | * may be called if len1 == len2.) 691 | * 692 | * @param base1 index of first element in first run to be merged 693 | * @param len1 length of first run to be merged (must be > 0) 694 | * @param base2 index of first element in second run to be merged 695 | * (must be aBase + aLen) 696 | * @param len2 length of second run to be merged (must be > 0) 697 | */ 698 | func (hi *timSortHandlerI) mergeHi(base1, len1, base2, len2 int) { 699 | // Copy second run into temp array 700 | a := hi.a // For performance 701 | tmp := hi.ensureCapacity(len2) 702 | 703 | copy(tmp, a[base2:base2+len2]) 704 | 705 | cursor1 := base1 + len1 - 1 // Indexes into a 706 | cursor2 := len2 - 1 // Indexes into tmp array 707 | dest := base2 + len2 - 1 // Indexes into a 708 | 709 | // Move last element of first run and deal with degenerate cases 710 | a[dest] = a[cursor1] 711 | dest-- 712 | cursor1-- 713 | len1-- 714 | if len1 == 0 { 715 | dest -= len2 - 1 716 | copy(a[dest:dest+len2], tmp) 717 | return 718 | } 719 | if len2 == 1 { 720 | dest -= len1 - 1 721 | cursor1 -= len1 - 1 722 | copy(a[dest:dest+len1], a[cursor1:cursor1+len1]) 723 | a[dest-1] = tmp[cursor2] 724 | return 725 | } 726 | 727 | lt := hi.lt // Use local variable for performance 728 | minGallop := hi.minGallop // " " " " " 729 | 730 | outer: 731 | for { 732 | count1 := 0 // Number of times in a row that first run won 733 | count2 := 0 // Number of times in a row that second run won 734 | 735 | /* 736 | * Do the straightforward thing until (if ever) one run 737 | * appears to win consistently. 738 | */ 739 | for { 740 | if lt(tmp[cursor2], a[cursor1]) { 741 | a[dest] = a[cursor1] 742 | dest-- 743 | cursor1-- 744 | count1++ 745 | count2 = 0 746 | len1-- 747 | if len1 == 0 { 748 | break outer 749 | } 750 | } else { 751 | a[dest] = tmp[cursor2] 752 | dest-- 753 | cursor2-- 754 | count2++ 755 | count1 = 0 756 | len2-- 757 | if len2 == 1 { 758 | break outer 759 | } 760 | } 761 | if (count1 | count2) >= minGallop { 762 | break 763 | } 764 | } 765 | 766 | /* 767 | * One run is winning so consistently that galloping may be a 768 | * huge win. So try that, and continue galloping until (if ever) 769 | * neither run appears to be winning consistently anymore. 770 | */ 771 | for { 772 | gr := gallopRightI(tmp[cursor2], a, base1, len1, len1-1, lt) 773 | count1 = len1 - gr 774 | if count1 != 0 { 775 | dest -= count1 776 | cursor1 -= count1 777 | len1 -= count1 778 | copy(a[dest+1:dest+1+count1], a[cursor1+1:cursor1+1+count1]) 779 | if len1 == 0 { 780 | break outer 781 | } 782 | } 783 | a[dest] = tmp[cursor2] 784 | dest-- 785 | cursor2-- 786 | len2-- 787 | if len2 == 1 { 788 | break outer 789 | } 790 | 791 | gl := gallopLeftI(a[cursor1], tmp, 0, len2, len2-1, lt) 792 | count2 = len2 - gl 793 | if count2 != 0 { 794 | dest -= count2 795 | cursor2 -= count2 796 | len2 -= count2 797 | copy(a[dest+1:dest+1+count2], tmp[cursor2+1:cursor2+1+count2]) 798 | if len2 <= 1 { // len2 == 1 || len2 == 0 799 | break outer 800 | } 801 | } 802 | a[dest] = a[cursor1] 803 | dest-- 804 | cursor1-- 805 | len1-- 806 | if len1 == 0 { 807 | break outer 808 | } 809 | minGallop-- 810 | 811 | if count1 < minGallop && count2 < minGallop { 812 | break 813 | } 814 | } 815 | if minGallop < 0 { 816 | minGallop = 0 817 | } 818 | minGallop += 2 // Penalize for leaving gallop mode 819 | } // End of "outer" loop 820 | 821 | if minGallop < 1 { 822 | minGallop = 1 823 | } 824 | 825 | hi.minGallop = minGallop // Write back to field 826 | 827 | if len2 == 1 { 828 | dest -= len1 829 | cursor1 -= len1 830 | 831 | copy(a[dest+1:dest+1+len1], a[cursor1+1:cursor1+1+len1]) 832 | a[dest] = tmp[cursor2] // Move first elt of run2 to front of merge 833 | } else { 834 | copy(a[dest-(len2-1):dest+1], tmp) 835 | } 836 | } 837 | 838 | /** 839 | * Ensures that the external array tmp has at least the specified 840 | * number of elements, increasing its size if necessary. The size 841 | * increases exponentially to ensure amortized linear time complexity. 842 | * 843 | * @param minCapacity the minimum required capacity of the tmp array 844 | * @return tmp, whether or not it grew 845 | */ 846 | func (hi *timSortHandlerI) ensureCapacity(minCapacity int) []int { 847 | if len(hi.tmp) < minCapacity { 848 | // Compute smallest power of 2 > minCapacity 849 | newSize := minCapacity 850 | newSize |= newSize >> 1 851 | newSize |= newSize >> 2 852 | newSize |= newSize >> 4 853 | newSize |= newSize >> 8 854 | newSize |= newSize >> 16 855 | newSize++ 856 | 857 | if newSize < 0 { // Not bloody likely! 858 | newSize = minCapacity 859 | } else { 860 | ns := len(hi.a) / 2 861 | if ns < newSize { 862 | newSize = ns 863 | } 864 | } 865 | 866 | hi.tmp = make([]int, newSize) 867 | } 868 | 869 | return hi.tmp 870 | } 871 | -------------------------------------------------------------------------------- /v2/timsortint_test.go: -------------------------------------------------------------------------------- 1 | package timsort 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "testing" 7 | ) 8 | 9 | func makeTestArrayI(size int) []int { 10 | a := make([]int, size) 11 | 12 | for i := 0; i < size; i++ { 13 | a[i] = i & 0xeeeeee 14 | } 15 | 16 | return a 17 | } 18 | 19 | func IsSortedI(a []int, lessThan IntLessThan) bool { 20 | len := len(a) 21 | 22 | if len < 2 { 23 | return true 24 | } 25 | 26 | prev := a[0] 27 | for i := 1; i < len; i++ { 28 | if lessThan(a[i], prev) { 29 | fmt.Println("false") 30 | return false 31 | } 32 | } 33 | 34 | return true 35 | } 36 | 37 | // use this comparator for sorting 38 | func intLessThan(a, b int) bool { 39 | return a < b 40 | } 41 | 42 | func TestSmokeI(t *testing.T) { 43 | a := []int{3, 1, 2} 44 | 45 | Ints(a, intLessThan) 46 | 47 | if !IsSortedI(a, intLessThan) { 48 | t.Error("not sorted") 49 | } 50 | } 51 | 52 | func Test0I(t *testing.T) { 53 | a := makeTestArrayI(1) 54 | 55 | Ints(a, intLessThan) 56 | if !IsSortedI(a, intLessThan) { 57 | t.Error("not sorted") 58 | } 59 | } 60 | 61 | func Test1I(t *testing.T) { 62 | a := makeTestArrayI(1) 63 | 64 | Ints(a, intLessThan) 65 | if !IsSortedI(a, intLessThan) { 66 | t.Error("not sorted") 67 | } 68 | } 69 | 70 | func Test1KI(t *testing.T) { 71 | a := makeTestArrayI(1024) 72 | 73 | Ints(a, intLessThan) 74 | if !IsSortedI(a, intLessThan) { 75 | t.Error("not sorted") 76 | } 77 | } 78 | 79 | func Test100KI(t *testing.T) { 80 | a := makeTestArrayI(100 * 1024) 81 | 82 | Ints(a, intLessThan) 83 | if !IsSortedI(a, intLessThan) { 84 | t.Error("not sorted") 85 | } 86 | } 87 | 88 | func Test1MI(t *testing.T) { 89 | a := makeTestArrayI(1024 * 1024) 90 | 91 | Ints(a, intLessThan) 92 | if !IsSortedI(a, intLessThan) { 93 | t.Error("not sorted") 94 | } 95 | } 96 | 97 | func makeRandomArrayI(size int) []int { 98 | a := make([]int, size) 99 | 100 | for i := 0; i < size; i++ { 101 | a[i] = rand.Intn(100) 102 | } 103 | 104 | return a 105 | } 106 | 107 | func TestRandom1MI(t *testing.T) { 108 | size := 1024 * 1024 109 | 110 | a := makeRandomArrayI(size) 111 | b := make([]int, size) 112 | copy(b, a) 113 | 114 | Ints(a, intLessThan) 115 | if !IsSortedI(a, intLessThan) { 116 | t.Error("not sorted") 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /v2/timsortintf.go: -------------------------------------------------------------------------------- 1 | package timsort 2 | 3 | import ( 4 | "sort" 5 | ) 6 | 7 | // TimSort sorts the data defined by sort.Interface. 8 | func TimSort(a sort.Interface) { 9 | indexes := make([]int, a.Len()) 10 | for i := 0; i < len(indexes); i++ { 11 | indexes[i] = i 12 | } 13 | 14 | Ints(indexes, func(i, j int) bool { 15 | return a.Less(i, j) 16 | }) 17 | 18 | for i := 0; i < len(indexes); i++ { 19 | j := indexes[i] 20 | if j == 0 { 21 | continue 22 | } 23 | for k := i; j != i; { 24 | a.Swap(j, k) 25 | k, j, indexes[j] = j, indexes[j], 0 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /v2/timsortintf_test.go: -------------------------------------------------------------------------------- 1 | package timsort 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "sort" 7 | "testing" 8 | ) 9 | 10 | func TestSmokeTS(t *testing.T) { 11 | a := make([]interface{}, 3) 12 | a[0] = val{3, 0} 13 | a[1] = val{1, 1} 14 | a[2] = val{2, 2} 15 | 16 | TimSort(KeyLessThanSlice(a)) 17 | 18 | if !IsSorted(a, KeyOrderLessThan) { 19 | t.Error("not sorted") 20 | } 21 | } 22 | 23 | func TestSmokeStabilityTS(t *testing.T) { 24 | a := make([]interface{}, 3) 25 | a[0] = val{3, 0} 26 | a[1] = val{2, 1} 27 | a[2] = val{2, 2} 28 | 29 | TimSort(KeyLessThanSlice(a)) 30 | 31 | if !IsSorted(a, KeyOrderLessThan) { 32 | t.Error("not sorted") 33 | } 34 | } 35 | 36 | func Test1KTS(t *testing.T) { 37 | a := makeTestArray(1024) 38 | 39 | TimSort(KeyLessThanSlice(a)) 40 | if !IsSorted(a, KeyOrderLessThan) { 41 | t.Error("not sorted") 42 | } 43 | } 44 | 45 | func Test1MTS(t *testing.T) { 46 | a := makeTestArray(1024 * 1024) 47 | 48 | TimSort(KeyLessThanSlice(a)) 49 | if !IsSorted(a, KeyOrderLessThan) { 50 | t.Error("not sorted") 51 | } 52 | } 53 | 54 | func TestRandom1MTS(t *testing.T) { 55 | size := 1024 * 1024 56 | 57 | a := makeRandomArray(size) 58 | b := make([]interface{}, size) 59 | copy(b, a) 60 | 61 | TimSort(KeyLessThanSlice(a)) 62 | if !IsSorted(a, KeyOrderLessThan) { 63 | t.Error("not sorted") 64 | } 65 | 66 | // sort by order 67 | TimSort(OrderLessThanSlice(a)) 68 | for i := 0; i < len(b); i++ { 69 | if !Equals(b[i], a[i]) { 70 | t.Error("oops") 71 | } 72 | } 73 | } 74 | 75 | func TestBentleyMcIlroyTS(t *testing.T) { 76 | // sizes := []int{100, 1023, 1024, 1025, 1023 * 1023, 1024 * 1024, 1025 * 1025} 77 | sizes := []int{100, 1023, 1024, 1025} 78 | dists := []string{"sawtooth", "rand", "stagger", "plateau", "shuffle"} 79 | modes := []string{"copy", "reverse", "reverse1", "reverse2", "sort", "dither"} 80 | tmp1 := make([]interface{}, 1025*1025) 81 | tmp2 := make([]interface{}, 1025*1025) 82 | for ni := 0; ni < len(sizes); ni++ { 83 | n := sizes[ni] 84 | for m := 1; m < 2*n; m *= 2 { 85 | for dist := 0; dist < _NDist; dist++ { 86 | j := 0 87 | k := 1 88 | data := tmp1[0:n] 89 | for i := 0; i < n; i++ { 90 | switch dist { 91 | case _Sawtooth: 92 | data[i] = val{i % m, i} 93 | case _Rand: 94 | data[i] = val{rand.Intn(m), i} 95 | case _Stagger: 96 | data[i] = val{(i*m + i) % n, i} 97 | case _Plateau: 98 | if i < m { 99 | data[i] = val{i, i} 100 | } else { 101 | data[i] = val{m, i} 102 | } 103 | case _Shuffle: 104 | if rand.Intn(m) != 0 { 105 | j += 2 106 | data[i] = val{j, i} 107 | } else { 108 | k += 2 109 | data[i] = val{k, i} 110 | } 111 | } 112 | } 113 | 114 | mdata := tmp2[0:n] 115 | for mode := 0; mode < _NMode; mode++ { 116 | switch mode { 117 | case _Copy: 118 | for i := 0; i < n; i++ { 119 | mdata[i] = val{data[i].(val).key, i} 120 | } 121 | case _Reverse: 122 | for i := 0; i < n; i++ { 123 | mdata[i] = val{data[n-i-1].(val).key, i} 124 | } 125 | case _ReverseFirstHalf: 126 | for i := 0; i < n/2; i++ { 127 | mdata[i] = val{data[n/2-i-1].(val).key, i} 128 | } 129 | for i := n / 2; i < n; i++ { 130 | mdata[i] = val{data[i].(val).key, i} 131 | } 132 | case _ReverseSecondHalf: 133 | for i := 0; i < n/2; i++ { 134 | mdata[i] = val{data[i].(val).key, i} 135 | } 136 | for i := n / 2; i < n; i++ { 137 | mdata[i] = val{data[n-(i-n/2)-1].(val).key, i} 138 | } 139 | case _Sorted: 140 | for i := 0; i < n; i++ { 141 | mdata[i] = data[i] 142 | } 143 | // SortInts is known to be correct 144 | // because mode Sort runs after mode _Copy. 145 | Sort(mdata, KeyLessThan) 146 | case _Dither: 147 | for i := 0; i < n; i++ { 148 | mdata[i] = val{data[i].(val).key + i%5, i} 149 | } 150 | } 151 | 152 | desc := fmt.Sprintf("n=%d m=%d dist=%s mode=%s", n, m, dists[dist], modes[mode]) 153 | 154 | for i := 0; i < len(mdata); i++ { 155 | mdata[i] = val{mdata[i].(val).key, i} 156 | } 157 | 158 | gdata := make([]interface{}, len(mdata)) 159 | copy(gdata, mdata) 160 | 161 | TimSort(KeyLessThanSlice(mdata)) 162 | 163 | // If we were testing C qsort, we'd have to make a copy 164 | // of the array and sort it ourselves and then compare 165 | // x against it, to ensure that qsort was only permuting 166 | // the data, not (for example) overwriting it with zeros. 167 | // 168 | // In go, we don't have to be so paranoid: since the only 169 | // mutating method Sort can call is TestingData.swap, 170 | // it suffices here just to check that the final array is sorted. 171 | if !IsSorted(mdata, KeyOrderLessThan) { 172 | t.Errorf("%s: ints not sorted", desc) 173 | t.Errorf("\t%v", mdata) 174 | t.FailNow() 175 | } 176 | 177 | TimSort(OrderLessThanSlice(mdata)) 178 | for i := 0; i < len(data); i++ { 179 | if !Equals(gdata[i], mdata[i]) { 180 | t.Error("restore sort failed") 181 | t.Errorf("gdata=%v", gdata) 182 | t.Errorf("mdata=%v", mdata) 183 | t.Errorf("bad index: %v\n", i) 184 | t.FailNow() 185 | } 186 | } 187 | } 188 | } 189 | } 190 | } 191 | } 192 | 193 | func TestStrings1TS(t *testing.T) { 194 | a := []string{ 195 | "ef", 196 | "abc", 197 | "aaa", 198 | "de", 199 | "ed", 200 | } 201 | TimSort(sort.StringSlice(a)) 202 | } 203 | --------------------------------------------------------------------------------