Skip to content

Commit 06b1c36

Browse files
committed
Replace Mid and MidInt with one generic function Mid
This new function accepts integers, floats and even strings
1 parent b1592d6 commit 06b1c36

File tree

6 files changed

+37
-78
lines changed

6 files changed

+37
-78
lines changed

devtools/internal/lib/github_com-elgopher-pi.go

+1-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/ROADMAP.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@
2121
* [ ] map API
2222
* [ ] math API
2323
* [x] Cos, Sin, Atan2
24-
* [x] Mid for integers
25-
* [x] Mid for float64
24+
* [x] Generic Mid for float64 and integers
2625
* [x] Game controller support: gamepad and keyboard
2726
* [x] Mouse support
2827
* [ ] Add mouse wheel support

internal/bench/math_bench_test.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ func BenchmarkMidInt(b *testing.B) {
1515

1616
for i := 0; i < b.N; i++ {
1717
for j := 0; j < 20; j++ {
18-
pi.MidInt(j, j+1, j+2) // y
19-
pi.MidInt(j+2, j+1, j) // y
20-
pi.MidInt(j+1, j, j+2) // x
21-
pi.MidInt(j+1, j+2, j) // x
22-
pi.MidInt(j, j+2, j+1) // z
23-
pi.MidInt(j+2, j, j+1) // z
18+
pi.Mid(j, j+1, j+2) // y
19+
pi.Mid(j+2, j+1, j) // y
20+
pi.Mid(j+1, j, j+2) // x
21+
pi.Mid(j+1, j+2, j) // x
22+
pi.Mid(j, j+2, j+1) // z
23+
pi.Mid(j+2, j, j+1) // z
2424
}
2525
}
2626
}

internal/fuzz/math_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313

1414
func FuzzMidInt(f *testing.F) {
1515
f.Fuzz(func(t *testing.T, x, y, z int) {
16-
pi.MidInt(x, y, z)
16+
pi.Mid(x, y, z)
1717
})
1818
}
1919

math.go

+9-37
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33

44
package pi
55

6-
import "math"
6+
import (
7+
"cmp"
8+
"math"
9+
)
710

811
// Sin returns the sine of angle which is in the range of 0.0-1.0 measured clockwise.
912
//
@@ -36,42 +39,11 @@ func Atan2(dx, dy float64) float64 {
3639
return math.Mod(0.75+v/(math.Pi*2), 1)
3740
}
3841

39-
// Int is a generic type for all integer types
40-
type Int interface {
41-
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
42-
}
43-
44-
// MidInt returns the middle of three integer numbers. Very useful for clamping.
45-
func MidInt[T Int](x, y, z T) T {
46-
if x > y {
47-
x, y = y, x
48-
}
49-
50-
if y > z {
51-
y = z
52-
}
53-
54-
if x > y {
55-
y = x
56-
}
57-
58-
return y
59-
}
60-
61-
// Mid returns the middle of three float64 numbers. Very useful for clamping.
62-
// NaNs are always put at the beginning (are the smallest ones).
63-
func Mid(x, y, z float64) float64 {
64-
if x > y || math.IsNaN(y) {
65-
x, y = y, x
66-
}
67-
68-
if y > z || math.IsNaN(z) {
69-
y = z
70-
}
71-
72-
if x > y || math.IsNaN(y) {
73-
y = x
74-
}
42+
// Mid returns the middle of three ordered values (numbers or strings). Very useful for clamping.
43+
func Mid[T cmp.Ordered](x, y, z T) T {
44+
x, y = min(x, y), max(x, y)
45+
y = min(y, z)
46+
y = max(x, y)
7547

7648
return y
7749
}

math_test.go

+19-21
Original file line numberDiff line numberDiff line change
@@ -114,33 +114,31 @@ func TestAtan2(t *testing.T) {
114114
}
115115
}
116116

117-
func TestMidInt(t *testing.T) {
118-
assert.Equal(t, 0, pi.MidInt(0, 0, 0))
119-
assert.Equal(t, 1, pi.MidInt(0, 1, 2))
120-
assert.Equal(t, 1, pi.MidInt(2, 1, 0))
121-
assert.Equal(t, 1, pi.MidInt(1, 0, 2))
122-
assert.Equal(t, 1, pi.MidInt(1, 2, 0))
123-
assert.Equal(t, 1, pi.MidInt(2, 0, 1))
124-
assert.Equal(t, 1, pi.MidInt(0, 2, 1))
125-
assert.Equal(t, -1, pi.MidInt(0, -1, -2))
126-
}
127-
128117
func TestMid(t *testing.T) {
129-
assert.Equal(t, 0.0, pi.Mid(0, 0, 0))
130-
assert.Equal(t, 1.0, pi.Mid(0, 1, 2))
131-
assert.Equal(t, 1.0, pi.Mid(2, 1, 0))
132-
assert.Equal(t, 1.0, pi.Mid(1, 0, 2))
133-
assert.Equal(t, 1.0, pi.Mid(1, 2, 0))
134-
assert.Equal(t, 1.0, pi.Mid(2, 0, 1))
135-
assert.Equal(t, 1.0, pi.Mid(0, 2, 1))
136-
assert.Equal(t, -1.0, pi.Mid(0, -1, -2))
118+
assert.Equal(t, 0, pi.Mid(0, 0, 0))
119+
assert.Equal(t, 1, pi.Mid(0, 1, 2))
120+
assert.Equal(t, 1, pi.Mid(2, 1, 0))
121+
assert.Equal(t, 1, pi.Mid(1, 0, 2))
122+
assert.Equal(t, 1, pi.Mid(1, 2, 0))
123+
assert.Equal(t, 1, pi.Mid(2, 0, 1))
124+
assert.Equal(t, 1, pi.Mid(0, 2, 1))
125+
assert.Equal(t, -1, pi.Mid(0, -1, -2))
126+
127+
assert.Equal(t, 0.0, pi.Mid(0.0, 0.0, 0.0))
128+
assert.Equal(t, 1.0, pi.Mid(0.0, 1.0, 2.0))
129+
assert.Equal(t, 1.0, pi.Mid(2.0, 1.0, 0.0))
130+
assert.Equal(t, 1.0, pi.Mid(1.0, 0.0, 2.0))
131+
assert.Equal(t, 1.0, pi.Mid(1.0, 2.0, 0.0))
132+
assert.Equal(t, 1.0, pi.Mid(2.0, 0.0, 1.0))
133+
assert.Equal(t, 1.0, pi.Mid(0.0, 2.0, 1.0))
134+
assert.Equal(t, -1.0, pi.Mid(0.0, -1.0, -2.0))
137135

138136
assertNaN(t, pi.Mid(math.NaN(), math.NaN(), math.NaN()))
139137
assertInf(t, pi.Mid(math.Inf(1), math.Inf(1), math.Inf(1)), 1)
140-
assert.Equal(t, 1.0, pi.Mid(1.0, math.NaN(), 2.0)) // NaNs always go to the beginning
138+
assertNaN(t, pi.Mid(1.0, math.NaN(), 2.0))
141139
assertNaN(t, pi.Mid(math.NaN(), math.NaN(), 1.0))
142140
assertNaN(t, pi.Mid(1.0, math.NaN(), math.NaN()))
143-
assert.Equal(t, 1.0, pi.Mid(1.0, 2.0, math.NaN()))
141+
assertNaN(t, pi.Mid(1.0, 2.0, math.NaN()))
144142
assert.Equal(t, 1.0, pi.Mid(math.Inf(1), math.Inf(-1), 1.0))
145143
}
146144

0 commit comments

Comments
 (0)