diff options
Diffstat (limited to 'src/pkg/sort/sort_test.go')
-rw-r--r-- | src/pkg/sort/sort_test.go | 553 |
1 files changed, 0 insertions, 553 deletions
diff --git a/src/pkg/sort/sort_test.go b/src/pkg/sort/sort_test.go deleted file mode 100644 index 6c36f30e0..000000000 --- a/src/pkg/sort/sort_test.go +++ /dev/null @@ -1,553 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package sort_test - -import ( - "fmt" - "math" - "math/rand" - . "sort" - "strconv" - "testing" -) - -var ints = [...]int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586} -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} -var strings = [...]string{"", "Hello", "foo", "bar", "foo", "f00", "%*&^*&^&", "***"} - -func TestSortIntSlice(t *testing.T) { - data := ints - a := IntSlice(data[0:]) - Sort(a) - if !IsSorted(a) { - t.Errorf("sorted %v", ints) - t.Errorf(" got %v", data) - } -} - -func TestSortFloat64Slice(t *testing.T) { - data := float64s - a := Float64Slice(data[0:]) - Sort(a) - if !IsSorted(a) { - t.Errorf("sorted %v", float64s) - t.Errorf(" got %v", data) - } -} - -func TestSortStringSlice(t *testing.T) { - data := strings - a := StringSlice(data[0:]) - Sort(a) - if !IsSorted(a) { - t.Errorf("sorted %v", strings) - t.Errorf(" got %v", data) - } -} - -func TestInts(t *testing.T) { - data := ints - Ints(data[0:]) - if !IntsAreSorted(data[0:]) { - t.Errorf("sorted %v", ints) - t.Errorf(" got %v", data) - } -} - -func TestFloat64s(t *testing.T) { - data := float64s - Float64s(data[0:]) - if !Float64sAreSorted(data[0:]) { - t.Errorf("sorted %v", float64s) - t.Errorf(" got %v", data) - } -} - -func TestStrings(t *testing.T) { - data := strings - Strings(data[0:]) - if !StringsAreSorted(data[0:]) { - t.Errorf("sorted %v", strings) - t.Errorf(" got %v", data) - } -} - -func TestSortLarge_Random(t *testing.T) { - n := 1000000 - if testing.Short() { - n /= 100 - } - data := make([]int, n) - for i := 0; i < len(data); i++ { - data[i] = rand.Intn(100) - } - if IntsAreSorted(data) { - t.Fatalf("terrible rand.rand") - } - Ints(data) - if !IntsAreSorted(data) { - t.Errorf("sort didn't sort - 1M ints") - } -} - -func TestReverseSortIntSlice(t *testing.T) { - data := ints - data1 := ints - a := IntSlice(data[0:]) - Sort(a) - r := IntSlice(data1[0:]) - Sort(Reverse(r)) - for i := 0; i < len(data); i++ { - if a[i] != r[len(data)-1-i] { - t.Errorf("reverse sort didn't sort") - } - if i > len(data)/2 { - break - } - } -} - -func BenchmarkSortString1K(b *testing.B) { - b.StopTimer() - for i := 0; i < b.N; i++ { - data := make([]string, 1<<10) - for i := 0; i < len(data); i++ { - data[i] = strconv.Itoa(i ^ 0x2cc) - } - b.StartTimer() - Strings(data) - b.StopTimer() - } -} - -func BenchmarkStableString1K(b *testing.B) { - b.StopTimer() - for i := 0; i < b.N; i++ { - data := make([]string, 1<<10) - for i := 0; i < len(data); i++ { - data[i] = strconv.Itoa(i ^ 0x2cc) - } - b.StartTimer() - Stable(StringSlice(data)) - b.StopTimer() - } -} - -func BenchmarkSortInt1K(b *testing.B) { - b.StopTimer() - for i := 0; i < b.N; i++ { - data := make([]int, 1<<10) - for i := 0; i < len(data); i++ { - data[i] = i ^ 0x2cc - } - b.StartTimer() - Ints(data) - b.StopTimer() - } -} - -func BenchmarkStableInt1K(b *testing.B) { - b.StopTimer() - for i := 0; i < b.N; i++ { - data := make([]int, 1<<10) - for i := 0; i < len(data); i++ { - data[i] = i ^ 0x2cc - } - b.StartTimer() - Stable(IntSlice(data)) - b.StopTimer() - } -} - -func BenchmarkSortInt64K(b *testing.B) { - b.StopTimer() - for i := 0; i < b.N; i++ { - data := make([]int, 1<<16) - for i := 0; i < len(data); i++ { - data[i] = i ^ 0xcccc - } - b.StartTimer() - Ints(data) - b.StopTimer() - } -} - -func BenchmarkStableInt64K(b *testing.B) { - b.StopTimer() - for i := 0; i < b.N; i++ { - data := make([]int, 1<<16) - for i := 0; i < len(data); i++ { - data[i] = i ^ 0xcccc - } - b.StartTimer() - Stable(IntSlice(data)) - b.StopTimer() - } -} - -const ( - _Sawtooth = iota - _Rand - _Stagger - _Plateau - _Shuffle - _NDist -) - -const ( - _Copy = iota - _Reverse - _ReverseFirstHalf - _ReverseSecondHalf - _Sorted - _Dither - _NMode -) - -type testingData struct { - desc string - t *testing.T - data []int - maxswap int // number of swaps allowed - ncmp, nswap int -} - -func (d *testingData) Len() int { return len(d.data) } -func (d *testingData) Less(i, j int) bool { - d.ncmp++ - return d.data[i] < d.data[j] -} -func (d *testingData) Swap(i, j int) { - if d.nswap >= d.maxswap { - d.t.Errorf("%s: used %d swaps sorting slice of %d", d.desc, d.nswap, len(d.data)) - d.t.FailNow() - } - d.nswap++ - d.data[i], d.data[j] = d.data[j], d.data[i] -} - -func min(a, b int) int { - if a < b { - return a - } - return b -} - -func lg(n int) int { - i := 0 - for 1<<uint(i) < n { - i++ - } - return i -} - -func testBentleyMcIlroy(t *testing.T, sort func(Interface), maxswap func(int) int) { - sizes := []int{100, 1023, 1024, 1025} - if testing.Short() { - sizes = []int{100, 127, 128, 129} - } - dists := []string{"sawtooth", "rand", "stagger", "plateau", "shuffle"} - modes := []string{"copy", "reverse", "reverse1", "reverse2", "sort", "dither"} - var tmp1, tmp2 [1025]int - for _, n := range sizes { - for m := 1; m < 2*n; m *= 2 { - for dist := 0; dist < _NDist; dist++ { - j := 0 - k := 1 - data := tmp1[0:n] - for i := 0; i < n; i++ { - switch dist { - case _Sawtooth: - data[i] = i % m - case _Rand: - data[i] = rand.Intn(m) - case _Stagger: - data[i] = (i*m + i) % n - case _Plateau: - data[i] = min(i, m) - case _Shuffle: - if rand.Intn(m) != 0 { - j += 2 - data[i] = j - } else { - k += 2 - data[i] = k - } - } - } - - mdata := tmp2[0:n] - for mode := 0; mode < _NMode; mode++ { - switch mode { - case _Copy: - for i := 0; i < n; i++ { - mdata[i] = data[i] - } - case _Reverse: - for i := 0; i < n; i++ { - mdata[i] = data[n-i-1] - } - case _ReverseFirstHalf: - for i := 0; i < n/2; i++ { - mdata[i] = data[n/2-i-1] - } - for i := n / 2; i < n; i++ { - mdata[i] = data[i] - } - case _ReverseSecondHalf: - for i := 0; i < n/2; i++ { - mdata[i] = data[i] - } - for i := n / 2; i < n; i++ { - mdata[i] = data[n-(i-n/2)-1] - } - case _Sorted: - for i := 0; i < n; i++ { - mdata[i] = data[i] - } - // Ints is known to be correct - // because mode Sort runs after mode _Copy. - Ints(mdata) - case _Dither: - for i := 0; i < n; i++ { - mdata[i] = data[i] + i%5 - } - } - - desc := fmt.Sprintf("n=%d m=%d dist=%s mode=%s", n, m, dists[dist], modes[mode]) - d := &testingData{desc: desc, t: t, data: mdata[0:n], maxswap: maxswap(n)} - sort(d) - // Uncomment if you are trying to improve the number of compares/swaps. - //t.Logf("%s: ncmp=%d, nswp=%d", desc, d.ncmp, d.nswap) - - // If we were testing C qsort, we'd have to make a copy - // of the slice and sort it ourselves and then compare - // x against it, to ensure that qsort was only permuting - // the data, not (for example) overwriting it with zeros. - // - // In go, we don't have to be so paranoid: since the only - // mutating method Sort can call is TestingData.swap, - // it suffices here just to check that the final slice is sorted. - if !IntsAreSorted(mdata) { - t.Errorf("%s: ints not sorted", desc) - t.Errorf("\t%v", mdata) - t.FailNow() - } - } - } - } - } -} - -func TestSortBM(t *testing.T) { - testBentleyMcIlroy(t, Sort, func(n int) int { return n * lg(n) * 12 / 10 }) -} - -func TestHeapsortBM(t *testing.T) { - testBentleyMcIlroy(t, Heapsort, func(n int) int { return n * lg(n) * 12 / 10 }) -} - -func TestStableBM(t *testing.T) { - testBentleyMcIlroy(t, Stable, func(n int) int { return n * lg(n) * lg(n) / 3 }) -} - -// This is based on the "antiquicksort" implementation by M. Douglas McIlroy. -// See http://www.cs.dartmouth.edu/~doug/mdmspe.pdf for more info. -type adversaryTestingData struct { - data []int - keys map[int]int - candidate int -} - -func (d *adversaryTestingData) Len() int { return len(d.data) } - -func (d *adversaryTestingData) Less(i, j int) bool { - if _, present := d.keys[i]; !present { - if _, present := d.keys[j]; !present { - if i == d.candidate { - d.keys[i] = len(d.keys) - } else { - d.keys[j] = len(d.keys) - } - } - } - - if _, present := d.keys[i]; !present { - d.candidate = i - return false - } - if _, present := d.keys[j]; !present { - d.candidate = j - return true - } - - return d.keys[i] >= d.keys[j] -} - -func (d *adversaryTestingData) Swap(i, j int) { - d.data[i], d.data[j] = d.data[j], d.data[i] -} - -func TestAdversary(t *testing.T) { - const size = 100 - data := make([]int, size) - for i := 0; i < size; i++ { - data[i] = i - } - - d := &adversaryTestingData{data, make(map[int]int), 0} - Sort(d) // This should degenerate to heapsort. -} - -func TestStableInts(t *testing.T) { - data := ints - Stable(IntSlice(data[0:])) - if !IntsAreSorted(data[0:]) { - t.Errorf("nsorted %v\n got %v", ints, data) - } -} - -type intPairs []struct { - a, b int -} - -// IntPairs compare on a only. -func (d intPairs) Len() int { return len(d) } -func (d intPairs) Less(i, j int) bool { return d[i].a < d[j].a } -func (d intPairs) Swap(i, j int) { d[i], d[j] = d[j], d[i] } - -// Record initial order in B. -func (d intPairs) initB() { - for i := range d { - d[i].b = i - } -} - -// InOrder checks if a-equal elements were not reordered. -func (d intPairs) inOrder() bool { - lastA, lastB := -1, 0 - for i := 0; i < len(d); i++ { - if lastA != d[i].a { - lastA = d[i].a - lastB = d[i].b - continue - } - if d[i].b <= lastB { - return false - } - lastB = d[i].b - } - return true -} - -func TestStability(t *testing.T) { - n, m := 100000, 1000 - if testing.Short() { - n, m = 1000, 100 - } - data := make(intPairs, n) - - // random distribution - for i := 0; i < len(data); i++ { - data[i].a = rand.Intn(m) - } - if IsSorted(data) { - t.Fatalf("terrible rand.rand") - } - data.initB() - Stable(data) - if !IsSorted(data) { - t.Errorf("Stable didn't sort %d ints", n) - } - if !data.inOrder() { - t.Errorf("Stable wasn't stable on %d ints", n) - } - - // already sorted - data.initB() - Stable(data) - if !IsSorted(data) { - t.Errorf("Stable shuffeled sorted %d ints (order)", n) - } - if !data.inOrder() { - t.Errorf("Stable shuffeled sorted %d ints (stability)", n) - } - - // sorted reversed - for i := 0; i < len(data); i++ { - data[i].a = len(data) - i - } - data.initB() - Stable(data) - if !IsSorted(data) { - t.Errorf("Stable didn't sort %d ints", n) - } - if !data.inOrder() { - t.Errorf("Stable wasn't stable on %d ints", n) - } -} - -var countOpsSizes = []int{1e2, 3e2, 1e3, 3e3, 1e4, 3e4, 1e5, 3e5, 1e6} - -func countOps(t *testing.T, algo func(Interface), name string) { - sizes := countOpsSizes - if testing.Short() { - sizes = sizes[:5] - } - if !testing.Verbose() { - t.Skip("Counting skipped as non-verbose mode.") - } - for _, n := range sizes { - td := testingData{ - desc: name, - t: t, - data: make([]int, n), - maxswap: 1<<31 - 1, - } - for i := 0; i < n; i++ { - td.data[i] = rand.Intn(n / 5) - } - algo(&td) - t.Logf("%s %8d elements: %11d Swap, %10d Less", name, n, td.nswap, td.ncmp) - } -} - -func TestCountStableOps(t *testing.T) { countOps(t, Stable, "Stable") } -func TestCountSortOps(t *testing.T) { countOps(t, Sort, "Sort ") } - -func bench(b *testing.B, size int, algo func(Interface), name string) { - b.StopTimer() - data := make(intPairs, size) - x := ^uint32(0) - for i := 0; i < b.N; i++ { - for n := size - 3; n <= size+3; n++ { - for i := 0; i < len(data); i++ { - x += x - x ^= 1 - if int32(x) < 0 { - x ^= 0x88888eef - } - data[i].a = int(x % uint32(n/5)) - } - data.initB() - b.StartTimer() - algo(data) - b.StopTimer() - if !IsSorted(data) { - b.Errorf("%s did not sort %d ints", name, n) - } - if name == "Stable" && !data.inOrder() { - b.Errorf("%s unstable on %d ints", name, n) - } - } - } -} - -func BenchmarkSort1e2(b *testing.B) { bench(b, 1e2, Sort, "Sort") } -func BenchmarkStable1e2(b *testing.B) { bench(b, 1e2, Stable, "Stable") } -func BenchmarkSort1e4(b *testing.B) { bench(b, 1e4, Sort, "Sort") } -func BenchmarkStable1e4(b *testing.B) { bench(b, 1e4, Stable, "Stable") } -func BenchmarkSort1e6(b *testing.B) { bench(b, 1e6, Sort, "Sort") } -func BenchmarkStable1e6(b *testing.B) { bench(b, 1e6, Stable, "Stable") } |