forked from go-gl/mathgl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
util.go
142 lines (116 loc) · 3.64 KB
/
util.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package mathgl
import "math"
// Epsilon is some tiny value that determines how precisely equal we want our floats to be
const epsilon float64 = 1e-15
// FloatEqual is a safe utility function to compare floats.
// It's Taken from http://floating-point-gui.de/errors/comparison/
//
// It is slightly altered to not call Abs when not needed.
// Keep in mind that it expects float32s to be converted to float64s before being passed in, because they have to be converted for Abs anyway
func FloatEqual(a, b float64) bool {
if a == b { // Handles the case of inf or shortcuts the loop when no significant error has accumulated
return true
} else if a*b == 0 { // If a or b are 0
return math.Abs(a-b) < epsilon*epsilon
}
// Else compare difference
return math.Abs(a-b)/(math.Abs(a)+math.Abs(b)) < epsilon
}
func FloatEqual32(a, b float32) bool {
if a == b { // Handles the case of inf or shortcuts the loop when no significant error has accumulated
return true
} else if a*b == 0 { // If a or b is 0
return math.Abs(float64(a-b)) < epsilon*epsilon
}
// Else compare difference
return math.Abs(float64(a-b))/(math.Abs(float64(a))+math.Abs(float64(b))) < epsilon
}
func FloatEqualFunc(epsilon float64) func(float64, float64) bool {
return func(a, b float64) bool {
return FloatEqualThreshold(a, b, epsilon)
}
}
func FloatEqual32Func(epsilon float32) func(float32, float32) bool {
return func(a, b float32) bool {
return FloatEqualThreshold32(a, b, epsilon)
}
}
// FloatEqualThreshold is a utility function to compare floats.
// It's Taken from http://floating-point-gui.de/errors/comparison/
//
// It is slightly altered to not call Abs when not needed.
// Keep in mind that it expects float32s to be converted to float64s before being passed in, because they have to be converted for Abs anyway
//
// This differs from FloatEqual in that it lets you pass in your comparison threshold, so that you can adjust the comparison value to your specific needs
func FloatEqualThreshold(a, b, epsilon float64) bool {
if a == b { // Handles the case of inf or shortcuts the loop when no significant error has accumulated
return true
} else if a*b == 0 { // If a or b is 0
return math.Abs(a-b) < epsilon*epsilon
}
// Else compare difference
return math.Abs(a-b)/(math.Abs(a)+math.Abs(b)) < epsilon
}
func FloatEqualThreshold32(a, b, epsilon float32) bool {
if a == b { // Handles the case of inf or shortcuts the loop when no significant error has accumulated
return true
} else if a*b == 0 { // If a or b is 0
return math.Abs(float64(a-b)) < float64(epsilon*epsilon)
}
// Else compare difference
return math.Abs(float64(a-b))/(math.Abs(float64(a))+math.Abs(float64(b))) < float64(epsilon)
}
func Clampf(a, t1, t2 float32) float32 {
if a < t1 {
return t1
} else if a > t2 {
return t2
}
return a
}
func ClampfFunc(t1, t2 float32) func(float32) {
return func(a float32) {
Clampf(a, t1, t2)
}
}
func ClampdFunc(t1, t2 float64) func(float64) {
return func(a float64) {
Clampd(a, t1, t2)
}
}
func Clampd(a, t1, t2 float64) float64 {
if a < t1 {
return t1
} else if a > t2 {
return t2
}
return a
}
/* The IsClamped functions use strict equality (meaning: not the FloatEqual function)
there shouldn't be any major issues with this since clamp is often used to fix minor errors*/
func IsClampedf(a, t1, t2 float32) bool {
return a >= t1 && a <= t2
}
func IsClampedd(a, t1, t2 float64) bool {
return a >= t1 && a <= t2
}
func SetMinf(a, b *float32) {
if *b < *a {
*a = *b
}
}
func SetMaxf(a, b *float32) {
if *a < *b {
*a = *b
}
}
func SetMind(a, b *float64) {
if *b < *a {
*a = *b
}
}
func SetMaxd(a, b *float64) {
if *a < *b {
*a = *b
}
}