178 lines
3.8 KiB
Go
178 lines
3.8 KiB
Go
package math
|
|
|
|
import (
|
|
"math"
|
|
|
|
"golang.org/x/exp/constraints"
|
|
)
|
|
|
|
// Various useful constants.
|
|
var (
|
|
MinNormal = float32(1.1754943508222875e-38) // 1 / 2**(127 - 1)
|
|
MinValue = float32(math.SmallestNonzeroFloat32)
|
|
MaxValue = float32(math.MaxFloat32)
|
|
|
|
InfPos = float32(math.Inf(1))
|
|
InfNeg = float32(math.Inf(-1))
|
|
NaN = float32(math.NaN())
|
|
|
|
E = float32(math.E)
|
|
Pi = float32(math.Pi)
|
|
PiOver2 = Pi / 2
|
|
PiOver4 = Pi / 4
|
|
Sqrt2 = float32(math.Sqrt2)
|
|
|
|
Epsilon = float32(1e-10)
|
|
)
|
|
|
|
// Abs returns the absolute value of a number
|
|
func Abs[T constraints.Float | constraints.Integer](v T) T {
|
|
if v < 0 {
|
|
return -v
|
|
}
|
|
return v
|
|
}
|
|
|
|
// Min returns the smaller of two numbers
|
|
func Min[T constraints.Ordered](a, b T) T {
|
|
if a < b {
|
|
return a
|
|
}
|
|
return b
|
|
}
|
|
|
|
// Max returns the greater of two numbers
|
|
func Max[T constraints.Ordered](a, b T) T {
|
|
if a > b {
|
|
return a
|
|
}
|
|
return b
|
|
}
|
|
|
|
// Clamp a value between a minimum and a maximum value
|
|
func Clamp[T constraints.Ordered](v, min, max T) T {
|
|
if v > max {
|
|
return max
|
|
}
|
|
if v < min {
|
|
return min
|
|
}
|
|
return v
|
|
}
|
|
|
|
// Ceil a number to the closest integer
|
|
func Ceil(x float32) float32 {
|
|
return float32(math.Ceil(float64(x)))
|
|
}
|
|
|
|
// Floor a number to the closest integer
|
|
func Floor(x float32) float32 {
|
|
return float32(math.Floor(float64(x)))
|
|
}
|
|
|
|
// Mod returns the remainder of a floating point division
|
|
func Mod(x, y float32) float32 {
|
|
return float32(math.Mod(float64(x), float64(y)))
|
|
}
|
|
|
|
// Sqrt returns the square root of a number
|
|
func Sqrt(x float32) float32 {
|
|
return float32(math.Sqrt(float64(x)))
|
|
}
|
|
|
|
// Sin computes the sine of x
|
|
func Sin(x float32) float32 {
|
|
return float32(math.Sin(float64(x)))
|
|
}
|
|
|
|
// Cos computes the cosine of x
|
|
func Cos(x float32) float32 {
|
|
return float32(math.Cos(float64(x)))
|
|
}
|
|
|
|
// Tan computes the tangent of x
|
|
func Tan(x float32) float32 {
|
|
return float32(math.Tan(float64(x)))
|
|
}
|
|
|
|
func Sincos(x float32) (float32, float32) {
|
|
sin, cos := math.Sincos(float64(x))
|
|
return float32(sin), float32(cos)
|
|
}
|
|
|
|
func Acos(x float32) float32 {
|
|
return float32(math.Acos(float64(x)))
|
|
}
|
|
|
|
func Asin(x float32) float32 {
|
|
return float32(math.Asin(float64(x)))
|
|
}
|
|
|
|
func Atan2(y, x float32) float32 {
|
|
return float32(math.Atan2(float64(y), float64(x)))
|
|
}
|
|
|
|
// Sign returns the sign of x (-1 or 1)
|
|
func Sign(x float32) float32 {
|
|
if x > 0 {
|
|
return 1
|
|
}
|
|
return -1
|
|
}
|
|
|
|
func Copysign(f, sign float32) float32 {
|
|
return float32(math.Copysign(float64(f), float64(sign)))
|
|
}
|
|
|
|
// DegToRad converts degrees to radians
|
|
func DegToRad(deg float32) float32 {
|
|
return Pi * deg / 180.0
|
|
}
|
|
|
|
// RadToDeg converts radians to degrees
|
|
func RadToDeg(rad float32) float32 {
|
|
return 180.0 * rad / Pi
|
|
}
|
|
|
|
// Equal checks two floats for (approximate) equality
|
|
func Equal(a, b float32) bool {
|
|
return EqualThreshold(a, b, Epsilon)
|
|
}
|
|
|
|
// EqualThreshold 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.
|
|
//
|
|
// 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 EqualThreshold(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
|
|
}
|
|
|
|
diff := Abs(a - b)
|
|
if a*b == 0 || diff < MinNormal { // If a or b are 0 or both are extremely close to it
|
|
return diff < epsilon*epsilon
|
|
}
|
|
|
|
// Else compare difference
|
|
return diff/(Abs(a)+Abs(b)) < epsilon
|
|
}
|
|
|
|
// Lerp performs linear interpolation between a and b
|
|
func Lerp(a, b, f float32) float32 {
|
|
return a + f*(b-a)
|
|
}
|
|
|
|
func Round(f float32) float32 {
|
|
return float32(math.Round(float64(f)))
|
|
}
|
|
|
|
func Snap(f, multiple float32) float32 {
|
|
return Ceil(f/multiple) * multiple
|
|
}
|
|
|
|
func Pow(f, x float32) float32 {
|
|
return float32(math.Pow(float64(f), float64(x)))
|
|
}
|