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))) }