Source file
src/runtime/minmax_test.go
1
2
3
4
5 package runtime_test
6
7 import (
8 "math"
9 "strings"
10 "testing"
11 "unsafe"
12 )
13
14 var (
15 zero = math.Copysign(0, +1)
16 negZero = math.Copysign(0, -1)
17 inf = math.Inf(+1)
18 negInf = math.Inf(-1)
19 nan = math.NaN()
20 )
21
22 var tests = []struct{ min, max float64 }{
23 {1, 2},
24 {-2, 1},
25 {negZero, zero},
26 {zero, inf},
27 {negInf, zero},
28 {negInf, inf},
29 {1, inf},
30 {negInf, 1},
31 }
32
33 var all = []float64{1, 2, -1, -2, zero, negZero, inf, negInf, nan}
34
35 func eq(x, y float64) bool {
36 return x == y && math.Signbit(x) == math.Signbit(y)
37 }
38
39 func TestMinFloat(t *testing.T) {
40 for _, tt := range tests {
41 if z := min(tt.min, tt.max); !eq(z, tt.min) {
42 t.Errorf("min(%v, %v) = %v, want %v", tt.min, tt.max, z, tt.min)
43 }
44 if z := min(tt.max, tt.min); !eq(z, tt.min) {
45 t.Errorf("min(%v, %v) = %v, want %v", tt.max, tt.min, z, tt.min)
46 }
47 }
48 for _, x := range all {
49 if z := min(nan, x); !math.IsNaN(z) {
50 t.Errorf("min(%v, %v) = %v, want %v", nan, x, z, nan)
51 }
52 if z := min(x, nan); !math.IsNaN(z) {
53 t.Errorf("min(%v, %v) = %v, want %v", nan, x, z, nan)
54 }
55 }
56 }
57
58 func TestMaxFloat(t *testing.T) {
59 for _, tt := range tests {
60 if z := max(tt.min, tt.max); !eq(z, tt.max) {
61 t.Errorf("max(%v, %v) = %v, want %v", tt.min, tt.max, z, tt.max)
62 }
63 if z := max(tt.max, tt.min); !eq(z, tt.max) {
64 t.Errorf("max(%v, %v) = %v, want %v", tt.max, tt.min, z, tt.max)
65 }
66 }
67 for _, x := range all {
68 if z := max(nan, x); !math.IsNaN(z) {
69 t.Errorf("max(%v, %v) = %v, want %v", nan, x, z, nan)
70 }
71 if z := max(x, nan); !math.IsNaN(z) {
72 t.Errorf("max(%v, %v) = %v, want %v", nan, x, z, nan)
73 }
74 }
75 }
76
77
78
79
80
81 func testMinMax[T int | uint8 | string](t *testing.T, vals ...T) {
82 for i, x := range vals {
83 for _, y := range vals[i+1:] {
84 if !(x < y) {
85 t.Fatalf("values out of order: !(%v < %v)", x, y)
86 }
87
88 if z := min(x, y); z != x {
89 t.Errorf("min(%v, %v) = %v, want %v", x, y, z, x)
90 }
91 if z := min(y, x); z != x {
92 t.Errorf("min(%v, %v) = %v, want %v", y, x, z, x)
93 }
94
95 if z := max(x, y); z != y {
96 t.Errorf("max(%v, %v) = %v, want %v", x, y, z, y)
97 }
98 if z := max(y, x); z != y {
99 t.Errorf("max(%v, %v) = %v, want %v", y, x, z, y)
100 }
101 }
102 }
103 }
104
105 func TestMinMaxInt(t *testing.T) { testMinMax[int](t, -7, 0, 9) }
106 func TestMinMaxUint8(t *testing.T) { testMinMax[uint8](t, 0, 1, 2, 4, 7) }
107 func TestMinMaxString(t *testing.T) { testMinMax[string](t, "a", "b", "c") }
108
109
110 func TestMinMaxStringTies(t *testing.T) {
111 s := "xxx"
112 x := strings.Split(s, "")
113
114 test := func(i, j, k int) {
115 if z := min(x[i], x[j], x[k]); unsafe.StringData(z) != unsafe.StringData(x[i]) {
116 t.Errorf("min(x[%v], x[%v], x[%v]) = %p, want %p", i, j, k, unsafe.StringData(z), unsafe.StringData(x[i]))
117 }
118 if z := max(x[i], x[j], x[k]); unsafe.StringData(z) != unsafe.StringData(x[i]) {
119 t.Errorf("max(x[%v], x[%v], x[%v]) = %p, want %p", i, j, k, unsafe.StringData(z), unsafe.StringData(x[i]))
120 }
121 }
122
123 test(0, 1, 2)
124 test(0, 2, 1)
125 test(1, 0, 2)
126 test(1, 2, 0)
127 test(2, 0, 1)
128 test(2, 1, 0)
129 }
130
131 func BenchmarkMinFloat(b *testing.B) {
132 var m float64 = 0
133 for i := 0; i < b.N; i++ {
134 for _, f := range all {
135 m = min(m, f)
136 }
137 }
138 }
139
140 func BenchmarkMaxFloat(b *testing.B) {
141 var m float64 = 0
142 for i := 0; i < b.N; i++ {
143 for _, f := range all {
144 m = max(m, f)
145 }
146 }
147 }
148
View as plain text