LEFT | RIGHT |
1 // Copyright 2010 The Go Authors. All rights reserved. | 1 // Copyright 2010 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package sort | 5 package sort |
6 | 6 |
7 import "testing" | 7 import "testing" |
8 | 8 |
9 | 9 |
10 func f(a []int, x int) func(int) bool { | 10 func f(a []int, x int) func(int) bool { |
11 return func(i int) bool { | 11 return func(i int) bool { |
12 return a[i] < x | 12 return a[i] < x |
13 } | 13 } |
14 } | 14 } |
15 | 15 |
16 | 16 |
17 var data = []int{0: -10, 1: -5, 2: 0, 3: 1, 4: 2, 5: 3, 6: 5, 7: 7, 8: 11, 9: 10
0, 10: 100, 11: 100, 12: 1000, 13: 10000} | 17 var data = []int{0: -10, 1: -5, 2: 0, 3: 1, 4: 2, 5: 3, 6: 5, 7: 7, 8: 11, 9: 10
0, 10: 100, 11: 100, 12: 1000, 13: 10000} |
18 | 18 |
19 var tests = []struct { | 19 var tests = []struct { |
20 name string | 20 name string |
21 n int | 21 n int |
22 f func(int) bool | 22 f func(int) bool |
23 i int | 23 i int |
24 }{ | 24 }{ |
25 {"empty", 0, nil, 0}, | 25 {"empty", 0, nil, 0}, |
26 {"1 1", 1, func(i int) bool { return i < 1 }, 1}, | 26 {"1 1", 1, func(i int) bool { return i < 1 }, 1}, |
27 » {"1 true", 1, func(i int) bool { return false }, 0}, | 27 » {"1 false", 1, func(i int) bool { return false }, 0}, |
28 » {"1 false", 1, func(i int) bool { return true }, 1}, | 28 » {"1 true", 1, func(i int) bool { return true }, 1}, |
29 {"1e9 991", 1e9, func(i int) bool { return i < 991 }, 991}, | 29 {"1e9 991", 1e9, func(i int) bool { return i < 991 }, 991}, |
30 » {"1e9 true", 1e9, func(i int) bool { return false }, 0}, | 30 » {"1e9 false", 1e9, func(i int) bool { return false }, 0}, |
31 » {"1e9 false", 1e9, func(i int) bool { return true }, 1e9}, | 31 » {"1e9 true", 1e9, func(i int) bool { return true }, 1e9}, |
32 {"data -20", len(data), f(data, -20), 0}, | 32 {"data -20", len(data), f(data, -20), 0}, |
33 {"data -10", len(data), f(data, -10), 0}, | 33 {"data -10", len(data), f(data, -10), 0}, |
34 {"data -9", len(data), f(data, -9), 1}, | 34 {"data -9", len(data), f(data, -9), 1}, |
35 {"data -6", len(data), f(data, -6), 1}, | 35 {"data -6", len(data), f(data, -6), 1}, |
36 {"data -5", len(data), f(data, -5), 1}, | 36 {"data -5", len(data), f(data, -5), 1}, |
37 {"data 3", len(data), f(data, 3), 5}, | 37 {"data 3", len(data), f(data, 3), 5}, |
38 {"data 11", len(data), f(data, 11), 8}, | 38 {"data 11", len(data), f(data, 11), 8}, |
39 {"data 99", len(data), f(data, 99), 9}, | 39 {"data 99", len(data), f(data, 99), 9}, |
40 {"data 100", len(data), f(data, 100), 9}, | 40 {"data 100", len(data), f(data, 100), 9}, |
41 {"data 101", len(data), f(data, 101), 12}, | 41 {"data 101", len(data), f(data, 101), 12}, |
42 {"data 10000", len(data), f(data, 10000), 13}, | 42 {"data 10000", len(data), f(data, 10000), 13}, |
43 {"data 10001", len(data), f(data, 10001), 14}, | 43 {"data 10001", len(data), f(data, 10001), 14}, |
44 {"descending a", 7, func(i int) bool { return []int{99, 99, 59, 42, 7, 0
, -1, -1}[i] > 7 }, 4}, | 44 {"descending a", 7, func(i int) bool { return []int{99, 99, 59, 42, 7, 0
, -1, -1}[i] > 7 }, 4}, |
45 {"descending 7", 1e9, func(i int) bool { return 1e9-i > 7 }, 1e9 - 7}, | 45 {"descending 7", 1e9, func(i int) bool { return 1e9-i > 7 }, 1e9 - 7}, |
46 } | 46 } |
47 | 47 |
48 | 48 |
49 func TestSearch(t *testing.T) { | 49 func TestSearch(t *testing.T) { |
50 for _, e := range tests { | 50 for _, e := range tests { |
51 i := Search(e.n, e.f) | 51 i := Search(e.n, e.f) |
52 if i != e.i { | 52 if i != e.i { |
53 t.Errorf("%s: expected index %d; got %d", e.name, e.i, i
) | 53 t.Errorf("%s: expected index %d; got %d", e.name, e.i, i
) |
54 } | 54 } |
| 55 } |
| 56 } |
| 57 |
| 58 |
| 59 // log2 computes the binary logarithm of x, rounded up to the next integer. |
| 60 // (log2(0) == 0, log2(1) == 0, log2(2) == 1, log2(3) == 2, etc.) |
| 61 // |
| 62 func log2(x int) int { |
| 63 n := 0 |
| 64 for p := 1; p < x; p += p { |
| 65 // p == 2**n |
| 66 n++ |
| 67 } |
| 68 // p/2 < x <= p == 2**n |
| 69 return n |
| 70 } |
| 71 |
| 72 |
| 73 func TestSearchEfficiency(t *testing.T) { |
| 74 n := 100 |
| 75 step := 1 |
| 76 for exp := 2; exp < 10; exp++ { |
| 77 // n == 10**exp |
| 78 // step == 10**(exp-2) |
| 79 max := log2(n) |
| 80 for x := 0; x < n; x += step { |
| 81 count := 0 |
| 82 i := Search(n, func(i int) bool { count++; return i < x
}) |
| 83 if i != x { |
| 84 t.Errorf("n = %d: expected index %d; got %d", n,
x, i) |
| 85 } |
| 86 if count > max { |
| 87 t.Errorf("n = %d, x = %d: expected <= %d calls;
got %d", n, x, max, count) |
| 88 } |
| 89 } |
| 90 n *= 10 |
| 91 step *= 10 |
55 } | 92 } |
56 } | 93 } |
57 | 94 |
58 | 95 |
59 // Smoke tests for convenience wrappers - not comprehensive. | 96 // Smoke tests for convenience wrappers - not comprehensive. |
60 | 97 |
61 var fdata = []float{0: -3.14, 1: 0, 2: 1, 3: 2, 4: 1000.7} | 98 var fdata = []float{0: -3.14, 1: 0, 2: 1, 3: 2, 4: 1000.7} |
62 var sdata = []string{0: "f", 1: "foo", 2: "foobar", 3: "x"} | 99 var sdata = []string{0: "f", 1: "foo", 2: "foobar", 3: "x"} |
63 | 100 |
64 var wrappertests = []struct { | 101 var wrappertests = []struct { |
(...skipping 10 matching lines...) Expand all Loading... |
75 } | 112 } |
76 | 113 |
77 | 114 |
78 func TestSearchWrappers(t *testing.T) { | 115 func TestSearchWrappers(t *testing.T) { |
79 for _, e := range wrappertests { | 116 for _, e := range wrappertests { |
80 if e.result != e.i { | 117 if e.result != e.i { |
81 t.Errorf("%s: expected index %d; got %d", e.name, e.i, e
.result) | 118 t.Errorf("%s: expected index %d; got %d", e.name, e.i, e
.result) |
82 } | 119 } |
83 } | 120 } |
84 } | 121 } |
LEFT | RIGHT |