sort_test.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package sort_test
  5. import (
  6. "fmt"
  7. "internal/testenv"
  8. "math"
  9. "math/rand"
  10. . "sort"
  11. "strconv"
  12. stringspkg "strings"
  13. "testing"
  14. )
  15. var ints = [...]int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586}
  16. var float64s = [...]float64{74.3, 59.0, math.Inf(1), 238.2, -784.0, 2.3, math.NaN(), math.NaN(), math.Inf(-1), 9845.768, -959.7485, 905, 7.8, 7.8}
  17. var strings = [...]string{"", "Hello", "foo", "bar", "foo", "f00", "%*&^*&^&", "***"}
  18. func TestSortIntSlice(t *testing.T) {
  19. data := ints
  20. a := IntSlice(data[0:])
  21. Sort(a)
  22. if !IsSorted(a) {
  23. t.Errorf("sorted %v", ints)
  24. t.Errorf(" got %v", data)
  25. }
  26. }
  27. func TestSortFloat64Slice(t *testing.T) {
  28. data := float64s
  29. a := Float64Slice(data[0:])
  30. Sort(a)
  31. if !IsSorted(a) {
  32. t.Errorf("sorted %v", float64s)
  33. t.Errorf(" got %v", data)
  34. }
  35. }
  36. func TestSortStringSlice(t *testing.T) {
  37. data := strings
  38. a := StringSlice(data[0:])
  39. Sort(a)
  40. if !IsSorted(a) {
  41. t.Errorf("sorted %v", strings)
  42. t.Errorf(" got %v", data)
  43. }
  44. }
  45. func TestInts(t *testing.T) {
  46. data := ints
  47. Ints(data[0:])
  48. if !IntsAreSorted(data[0:]) {
  49. t.Errorf("sorted %v", ints)
  50. t.Errorf(" got %v", data)
  51. }
  52. }
  53. func TestFloat64s(t *testing.T) {
  54. data := float64s
  55. Float64s(data[0:])
  56. if !Float64sAreSorted(data[0:]) {
  57. t.Errorf("sorted %v", float64s)
  58. t.Errorf(" got %v", data)
  59. }
  60. }
  61. func TestStrings(t *testing.T) {
  62. data := strings
  63. Strings(data[0:])
  64. if !StringsAreSorted(data[0:]) {
  65. t.Errorf("sorted %v", strings)
  66. t.Errorf(" got %v", data)
  67. }
  68. }
  69. func TestSlice(t *testing.T) {
  70. data := strings
  71. Slice(data[:], func(i, j int) bool {
  72. return data[i] < data[j]
  73. })
  74. if !SliceIsSorted(data[:], func(i, j int) bool { return data[i] < data[j] }) {
  75. t.Errorf("sorted %v", strings)
  76. t.Errorf(" got %v", data)
  77. }
  78. }
  79. func TestSortLarge_Random(t *testing.T) {
  80. n := 1000000
  81. if testing.Short() {
  82. n /= 100
  83. }
  84. data := make([]int, n)
  85. for i := 0; i < len(data); i++ {
  86. data[i] = rand.Intn(100)
  87. }
  88. if IntsAreSorted(data) {
  89. t.Fatalf("terrible rand.rand")
  90. }
  91. Ints(data)
  92. if !IntsAreSorted(data) {
  93. t.Errorf("sort didn't sort - 1M ints")
  94. }
  95. }
  96. func TestReverseSortIntSlice(t *testing.T) {
  97. data := ints
  98. data1 := ints
  99. a := IntSlice(data[0:])
  100. Sort(a)
  101. r := IntSlice(data1[0:])
  102. Sort(Reverse(r))
  103. for i := 0; i < len(data); i++ {
  104. if a[i] != r[len(data)-1-i] {
  105. t.Errorf("reverse sort didn't sort")
  106. }
  107. if i > len(data)/2 {
  108. break
  109. }
  110. }
  111. }
  112. type nonDeterministicTestingData struct {
  113. r *rand.Rand
  114. }
  115. func (t *nonDeterministicTestingData) Len() int {
  116. return 500
  117. }
  118. func (t *nonDeterministicTestingData) Less(i, j int) bool {
  119. if i < 0 || j < 0 || i >= t.Len() || j >= t.Len() {
  120. panic("nondeterministic comparison out of bounds")
  121. }
  122. return t.r.Float32() < 0.5
  123. }
  124. func (t *nonDeterministicTestingData) Swap(i, j int) {
  125. if i < 0 || j < 0 || i >= t.Len() || j >= t.Len() {
  126. panic("nondeterministic comparison out of bounds")
  127. }
  128. }
  129. func TestNonDeterministicComparison(t *testing.T) {
  130. // Ensure that sort.Sort does not panic when Less returns inconsistent results.
  131. // See https://golang.org/issue/14377.
  132. defer func() {
  133. if r := recover(); r != nil {
  134. t.Error(r)
  135. }
  136. }()
  137. td := &nonDeterministicTestingData{
  138. r: rand.New(rand.NewSource(0)),
  139. }
  140. for i := 0; i < 10; i++ {
  141. Sort(td)
  142. }
  143. }
  144. func BenchmarkSortString1K(b *testing.B) {
  145. b.StopTimer()
  146. unsorted := make([]string, 1<<10)
  147. for i := range unsorted {
  148. unsorted[i] = strconv.Itoa(i ^ 0x2cc)
  149. }
  150. data := make([]string, len(unsorted))
  151. for i := 0; i < b.N; i++ {
  152. copy(data, unsorted)
  153. b.StartTimer()
  154. Strings(data)
  155. b.StopTimer()
  156. }
  157. }
  158. func BenchmarkSortString1K_Slice(b *testing.B) {
  159. b.StopTimer()
  160. unsorted := make([]string, 1<<10)
  161. for i := range unsorted {
  162. unsorted[i] = strconv.Itoa(i ^ 0x2cc)
  163. }
  164. data := make([]string, len(unsorted))
  165. for i := 0; i < b.N; i++ {
  166. copy(data, unsorted)
  167. b.StartTimer()
  168. Slice(data, func(i, j int) bool { return data[i] < data[j] })
  169. b.StopTimer()
  170. }
  171. }
  172. func BenchmarkStableString1K(b *testing.B) {
  173. b.StopTimer()
  174. unsorted := make([]string, 1<<10)
  175. for i := range unsorted {
  176. unsorted[i] = strconv.Itoa(i ^ 0x2cc)
  177. }
  178. data := make([]string, len(unsorted))
  179. for i := 0; i < b.N; i++ {
  180. copy(data, unsorted)
  181. b.StartTimer()
  182. Stable(StringSlice(data))
  183. b.StopTimer()
  184. }
  185. }
  186. func BenchmarkSortInt1K(b *testing.B) {
  187. b.StopTimer()
  188. for i := 0; i < b.N; i++ {
  189. data := make([]int, 1<<10)
  190. for i := 0; i < len(data); i++ {
  191. data[i] = i ^ 0x2cc
  192. }
  193. b.StartTimer()
  194. Ints(data)
  195. b.StopTimer()
  196. }
  197. }
  198. func BenchmarkStableInt1K(b *testing.B) {
  199. b.StopTimer()
  200. unsorted := make([]int, 1<<10)
  201. for i := range unsorted {
  202. unsorted[i] = i ^ 0x2cc
  203. }
  204. data := make([]int, len(unsorted))
  205. for i := 0; i < b.N; i++ {
  206. copy(data, unsorted)
  207. b.StartTimer()
  208. Stable(IntSlice(data))
  209. b.StopTimer()
  210. }
  211. }
  212. func BenchmarkStableInt1K_Slice(b *testing.B) {
  213. b.StopTimer()
  214. unsorted := make([]int, 1<<10)
  215. for i := range unsorted {
  216. unsorted[i] = i ^ 0x2cc
  217. }
  218. data := make([]int, len(unsorted))
  219. for i := 0; i < b.N; i++ {
  220. copy(data, unsorted)
  221. b.StartTimer()
  222. SliceStable(data, func(i, j int) bool { return data[i] < data[j] })
  223. b.StopTimer()
  224. }
  225. }
  226. func BenchmarkSortInt64K(b *testing.B) {
  227. b.StopTimer()
  228. for i := 0; i < b.N; i++ {
  229. data := make([]int, 1<<16)
  230. for i := 0; i < len(data); i++ {
  231. data[i] = i ^ 0xcccc
  232. }
  233. b.StartTimer()
  234. Ints(data)
  235. b.StopTimer()
  236. }
  237. }
  238. func BenchmarkSortInt64K_Slice(b *testing.B) {
  239. b.StopTimer()
  240. for i := 0; i < b.N; i++ {
  241. data := make([]int, 1<<16)
  242. for i := 0; i < len(data); i++ {
  243. data[i] = i ^ 0xcccc
  244. }
  245. b.StartTimer()
  246. Slice(data, func(i, j int) bool { return data[i] < data[j] })
  247. b.StopTimer()
  248. }
  249. }
  250. func BenchmarkStableInt64K(b *testing.B) {
  251. b.StopTimer()
  252. for i := 0; i < b.N; i++ {
  253. data := make([]int, 1<<16)
  254. for i := 0; i < len(data); i++ {
  255. data[i] = i ^ 0xcccc
  256. }
  257. b.StartTimer()
  258. Stable(IntSlice(data))
  259. b.StopTimer()
  260. }
  261. }
  262. const (
  263. _Sawtooth = iota
  264. _Rand
  265. _Stagger
  266. _Plateau
  267. _Shuffle
  268. _NDist
  269. )
  270. const (
  271. _Copy = iota
  272. _Reverse
  273. _ReverseFirstHalf
  274. _ReverseSecondHalf
  275. _Sorted
  276. _Dither
  277. _NMode
  278. )
  279. type testingData struct {
  280. desc string
  281. t *testing.T
  282. data []int
  283. maxswap int // number of swaps allowed
  284. ncmp, nswap int
  285. }
  286. func (d *testingData) Len() int { return len(d.data) }
  287. func (d *testingData) Less(i, j int) bool {
  288. d.ncmp++
  289. return d.data[i] < d.data[j]
  290. }
  291. func (d *testingData) Swap(i, j int) {
  292. if d.nswap >= d.maxswap {
  293. d.t.Fatalf("%s: used %d swaps sorting slice of %d", d.desc, d.nswap, len(d.data))
  294. }
  295. d.nswap++
  296. d.data[i], d.data[j] = d.data[j], d.data[i]
  297. }
  298. func min(a, b int) int {
  299. if a < b {
  300. return a
  301. }
  302. return b
  303. }
  304. func lg(n int) int {
  305. i := 0
  306. for 1<<uint(i) < n {
  307. i++
  308. }
  309. return i
  310. }
  311. func testBentleyMcIlroy(t *testing.T, sort func(Interface), maxswap func(int) int) {
  312. sizes := []int{100, 1023, 1024, 1025}
  313. if testing.Short() {
  314. sizes = []int{100, 127, 128, 129}
  315. }
  316. dists := []string{"sawtooth", "rand", "stagger", "plateau", "shuffle"}
  317. modes := []string{"copy", "reverse", "reverse1", "reverse2", "sort", "dither"}
  318. var tmp1, tmp2 [1025]int
  319. for _, n := range sizes {
  320. for m := 1; m < 2*n; m *= 2 {
  321. for dist := 0; dist < _NDist; dist++ {
  322. j := 0
  323. k := 1
  324. data := tmp1[0:n]
  325. for i := 0; i < n; i++ {
  326. switch dist {
  327. case _Sawtooth:
  328. data[i] = i % m
  329. case _Rand:
  330. data[i] = rand.Intn(m)
  331. case _Stagger:
  332. data[i] = (i*m + i) % n
  333. case _Plateau:
  334. data[i] = min(i, m)
  335. case _Shuffle:
  336. if rand.Intn(m) != 0 {
  337. j += 2
  338. data[i] = j
  339. } else {
  340. k += 2
  341. data[i] = k
  342. }
  343. }
  344. }
  345. mdata := tmp2[0:n]
  346. for mode := 0; mode < _NMode; mode++ {
  347. switch mode {
  348. case _Copy:
  349. for i := 0; i < n; i++ {
  350. mdata[i] = data[i]
  351. }
  352. case _Reverse:
  353. for i := 0; i < n; i++ {
  354. mdata[i] = data[n-i-1]
  355. }
  356. case _ReverseFirstHalf:
  357. for i := 0; i < n/2; i++ {
  358. mdata[i] = data[n/2-i-1]
  359. }
  360. for i := n / 2; i < n; i++ {
  361. mdata[i] = data[i]
  362. }
  363. case _ReverseSecondHalf:
  364. for i := 0; i < n/2; i++ {
  365. mdata[i] = data[i]
  366. }
  367. for i := n / 2; i < n; i++ {
  368. mdata[i] = data[n-(i-n/2)-1]
  369. }
  370. case _Sorted:
  371. for i := 0; i < n; i++ {
  372. mdata[i] = data[i]
  373. }
  374. // Ints is known to be correct
  375. // because mode Sort runs after mode _Copy.
  376. Ints(mdata)
  377. case _Dither:
  378. for i := 0; i < n; i++ {
  379. mdata[i] = data[i] + i%5
  380. }
  381. }
  382. desc := fmt.Sprintf("n=%d m=%d dist=%s mode=%s", n, m, dists[dist], modes[mode])
  383. d := &testingData{desc: desc, t: t, data: mdata[0:n], maxswap: maxswap(n)}
  384. sort(d)
  385. // Uncomment if you are trying to improve the number of compares/swaps.
  386. //t.Logf("%s: ncmp=%d, nswp=%d", desc, d.ncmp, d.nswap)
  387. // If we were testing C qsort, we'd have to make a copy
  388. // of the slice and sort it ourselves and then compare
  389. // x against it, to ensure that qsort was only permuting
  390. // the data, not (for example) overwriting it with zeros.
  391. //
  392. // In go, we don't have to be so paranoid: since the only
  393. // mutating method Sort can call is TestingData.swap,
  394. // it suffices here just to check that the final slice is sorted.
  395. if !IntsAreSorted(mdata) {
  396. t.Fatalf("%s: ints not sorted\n\t%v", desc, mdata)
  397. }
  398. }
  399. }
  400. }
  401. }
  402. }
  403. func TestSortBM(t *testing.T) {
  404. testBentleyMcIlroy(t, Sort, func(n int) int { return n * lg(n) * 12 / 10 })
  405. }
  406. func TestHeapsortBM(t *testing.T) {
  407. testBentleyMcIlroy(t, Heapsort, func(n int) int { return n * lg(n) * 12 / 10 })
  408. }
  409. func TestStableBM(t *testing.T) {
  410. testBentleyMcIlroy(t, Stable, func(n int) int { return n * lg(n) * lg(n) / 3 })
  411. }
  412. // This is based on the "antiquicksort" implementation by M. Douglas McIlroy.
  413. // See https://www.cs.dartmouth.edu/~doug/mdmspe.pdf for more info.
  414. type adversaryTestingData struct {
  415. t *testing.T
  416. data []int // item values, initialized to special gas value and changed by Less
  417. maxcmp int // number of comparisons allowed
  418. ncmp int // number of comparisons (calls to Less)
  419. nsolid int // number of elements that have been set to non-gas values
  420. candidate int // guess at current pivot
  421. gas int // special value for unset elements, higher than everything else
  422. }
  423. func (d *adversaryTestingData) Len() int { return len(d.data) }
  424. func (d *adversaryTestingData) Less(i, j int) bool {
  425. if d.ncmp >= d.maxcmp {
  426. d.t.Fatalf("used %d comparisons sorting adversary data with size %d", d.ncmp, len(d.data))
  427. }
  428. d.ncmp++
  429. if d.data[i] == d.gas && d.data[j] == d.gas {
  430. if i == d.candidate {
  431. // freeze i
  432. d.data[i] = d.nsolid
  433. d.nsolid++
  434. } else {
  435. // freeze j
  436. d.data[j] = d.nsolid
  437. d.nsolid++
  438. }
  439. }
  440. if d.data[i] == d.gas {
  441. d.candidate = i
  442. } else if d.data[j] == d.gas {
  443. d.candidate = j
  444. }
  445. return d.data[i] < d.data[j]
  446. }
  447. func (d *adversaryTestingData) Swap(i, j int) {
  448. d.data[i], d.data[j] = d.data[j], d.data[i]
  449. }
  450. func newAdversaryTestingData(t *testing.T, size int, maxcmp int) *adversaryTestingData {
  451. gas := size - 1
  452. data := make([]int, size)
  453. for i := 0; i < size; i++ {
  454. data[i] = gas
  455. }
  456. return &adversaryTestingData{t: t, data: data, maxcmp: maxcmp, gas: gas}
  457. }
  458. func TestAdversary(t *testing.T) {
  459. const size = 10000 // large enough to distinguish between O(n^2) and O(n*log(n))
  460. maxcmp := size * lg(size) * 4 // the factor 4 was found by trial and error
  461. d := newAdversaryTestingData(t, size, maxcmp)
  462. Sort(d) // This should degenerate to heapsort.
  463. // Check data is fully populated and sorted.
  464. for i, v := range d.data {
  465. if v != i {
  466. t.Fatalf("adversary data not fully sorted")
  467. }
  468. }
  469. }
  470. func TestStableInts(t *testing.T) {
  471. data := ints
  472. Stable(IntSlice(data[0:]))
  473. if !IntsAreSorted(data[0:]) {
  474. t.Errorf("nsorted %v\n got %v", ints, data)
  475. }
  476. }
  477. type intPairs []struct {
  478. a, b int
  479. }
  480. // IntPairs compare on a only.
  481. func (d intPairs) Len() int { return len(d) }
  482. func (d intPairs) Less(i, j int) bool { return d[i].a < d[j].a }
  483. func (d intPairs) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
  484. // Record initial order in B.
  485. func (d intPairs) initB() {
  486. for i := range d {
  487. d[i].b = i
  488. }
  489. }
  490. // InOrder checks if a-equal elements were not reordered.
  491. func (d intPairs) inOrder() bool {
  492. lastA, lastB := -1, 0
  493. for i := 0; i < len(d); i++ {
  494. if lastA != d[i].a {
  495. lastA = d[i].a
  496. lastB = d[i].b
  497. continue
  498. }
  499. if d[i].b <= lastB {
  500. return false
  501. }
  502. lastB = d[i].b
  503. }
  504. return true
  505. }
  506. func TestStability(t *testing.T) {
  507. n, m := 100000, 1000
  508. if testing.Short() {
  509. n, m = 1000, 100
  510. }
  511. data := make(intPairs, n)
  512. // random distribution
  513. for i := 0; i < len(data); i++ {
  514. data[i].a = rand.Intn(m)
  515. }
  516. if IsSorted(data) {
  517. t.Fatalf("terrible rand.rand")
  518. }
  519. data.initB()
  520. Stable(data)
  521. if !IsSorted(data) {
  522. t.Errorf("Stable didn't sort %d ints", n)
  523. }
  524. if !data.inOrder() {
  525. t.Errorf("Stable wasn't stable on %d ints", n)
  526. }
  527. // already sorted
  528. data.initB()
  529. Stable(data)
  530. if !IsSorted(data) {
  531. t.Errorf("Stable shuffled sorted %d ints (order)", n)
  532. }
  533. if !data.inOrder() {
  534. t.Errorf("Stable shuffled sorted %d ints (stability)", n)
  535. }
  536. // sorted reversed
  537. for i := 0; i < len(data); i++ {
  538. data[i].a = len(data) - i
  539. }
  540. data.initB()
  541. Stable(data)
  542. if !IsSorted(data) {
  543. t.Errorf("Stable didn't sort %d ints", n)
  544. }
  545. if !data.inOrder() {
  546. t.Errorf("Stable wasn't stable on %d ints", n)
  547. }
  548. }
  549. var countOpsSizes = []int{1e2, 3e2, 1e3, 3e3, 1e4, 3e4, 1e5, 3e5, 1e6}
  550. func countOps(t *testing.T, algo func(Interface), name string) {
  551. sizes := countOpsSizes
  552. if testing.Short() {
  553. sizes = sizes[:5]
  554. }
  555. if !testing.Verbose() {
  556. t.Skip("Counting skipped as non-verbose mode.")
  557. }
  558. for _, n := range sizes {
  559. td := testingData{
  560. desc: name,
  561. t: t,
  562. data: make([]int, n),
  563. maxswap: 1<<31 - 1,
  564. }
  565. for i := 0; i < n; i++ {
  566. td.data[i] = rand.Intn(n / 5)
  567. }
  568. algo(&td)
  569. t.Logf("%s %8d elements: %11d Swap, %10d Less", name, n, td.nswap, td.ncmp)
  570. }
  571. }
  572. func TestCountStableOps(t *testing.T) { countOps(t, Stable, "Stable") }
  573. func TestCountSortOps(t *testing.T) { countOps(t, Sort, "Sort ") }
  574. func bench(b *testing.B, size int, algo func(Interface), name string) {
  575. if stringspkg.HasSuffix(testenv.Builder(), "-race") && size > 1e4 {
  576. b.Skip("skipping slow benchmark on race builder")
  577. }
  578. b.StopTimer()
  579. data := make(intPairs, size)
  580. x := ^uint32(0)
  581. for i := 0; i < b.N; i++ {
  582. for n := size - 3; n <= size+3; n++ {
  583. for i := 0; i < len(data); i++ {
  584. x += x
  585. x ^= 1
  586. if int32(x) < 0 {
  587. x ^= 0x88888eef
  588. }
  589. data[i].a = int(x % uint32(n/5))
  590. }
  591. data.initB()
  592. b.StartTimer()
  593. algo(data)
  594. b.StopTimer()
  595. if !IsSorted(data) {
  596. b.Errorf("%s did not sort %d ints", name, n)
  597. }
  598. if name == "Stable" && !data.inOrder() {
  599. b.Errorf("%s unstable on %d ints", name, n)
  600. }
  601. }
  602. }
  603. }
  604. func BenchmarkSort1e2(b *testing.B) { bench(b, 1e2, Sort, "Sort") }
  605. func BenchmarkStable1e2(b *testing.B) { bench(b, 1e2, Stable, "Stable") }
  606. func BenchmarkSort1e4(b *testing.B) { bench(b, 1e4, Sort, "Sort") }
  607. func BenchmarkStable1e4(b *testing.B) { bench(b, 1e4, Stable, "Stable") }
  608. func BenchmarkSort1e6(b *testing.B) { bench(b, 1e6, Sort, "Sort") }
  609. func BenchmarkStable1e6(b *testing.B) { bench(b, 1e6, Stable, "Stable") }