-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathmath.go
100 lines (85 loc) · 1.88 KB
/
math.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package toolbelt
import (
"math"
"math/rand"
"github.com/chewxy/math32"
)
type Float interface {
~float32 | ~float64
}
type Integer interface {
~int | ~uint8 | ~int8 | ~uint16 | ~int16 | ~uint32 | ~int32 | ~uint64 | ~int64
}
func Fit[T Float](
x T,
oldMin T,
oldMax T,
newMin T,
newMax T,
) T {
return newMin + ((x-oldMin)*(newMax-newMin))/(oldMax-oldMin)
}
func Fit01[T Float](x T, newMin T, newMax T) T {
return Fit(x, 0, 1, newMin, newMax)
}
func RoundFit01[T Float](x T, newMin T, newMax T) T {
switch any(x).(type) {
case float32:
f := float32(x)
nmin := float32(newMin)
nmax := float32(newMax)
return T(math32.Round(Fit01(f, nmin, nmax)))
case float64:
f := float64(x)
nmin := float64(newMin)
nmax := float64(newMax)
return T(math.Round(Fit01(f, nmin, nmax)))
default:
panic("unsupported type")
}
}
func FitMax[T Float](x T, newMax T) T {
return Fit01(x, 0, newMax)
}
func Clamp[T Float](v T, minimum T, maximum T) T {
realMin := minimum
realMax := maximum
if maximum < realMin {
realMin = maximum
realMax = minimum
}
return max(realMin, min(realMax, v))
}
func ClampFit[T Float](
x T,
oldMin T,
oldMax T,
newMin T,
newMax T,
) T {
f := Fit(x, oldMin, oldMax, newMin, newMax)
return Clamp(f, newMin, newMax)
}
func ClampFit01[T Float](x T, newMin T, newMax T) T {
f := Fit01(x, newMin, newMax)
return Clamp(f, newMin, newMax)
}
func Clamp01[T Float](v T) T {
return Clamp(v, 0, 1)
}
func RandNegOneToOneClamped[T Float](r *rand.Rand) T {
switch any(*new(T)).(type) {
case float32:
return T(ClampFit(r.Float32(), 0, 1, -1, 1))
case float64:
return T(ClampFit(r.Float64(), 0, 1, -1, 1))
default:
panic("unsupported type")
}
}
func RandIntRange[T Integer](r *rand.Rand, min, max T) T {
return T(Fit(r.Float32(), 0, 1, float32(min), float32(max)))
}
func RandSliceItem[T any](r *rand.Rand, slice []T) T {
return slice[r.Intn(len(slice))]
}