mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-20 07:27:19 -05:00
Benchmark d2math (#595)
* Vector and tests reviewed. * Tests and benchmarks for d2math.math. Also docs/comments.
This commit is contained in:
parent
dcb0c087b9
commit
54ff33c552
5
d2common/d2math/d2vector/doc.go
Normal file
5
d2common/d2math/d2vector/doc.go
Normal file
@ -0,0 +1,5 @@
|
||||
// Package d2vector provides an implementation of a 2D Euclidean vector using float64 to store the two values.
|
||||
/*
|
||||
Vector uses d2math.Epsilon for approximate equality and comparison. Note: SetLength and Rotate do not (per the unit
|
||||
tests) return exact values but ones within Epsilon range of the expected value.*/
|
||||
package d2vector
|
@ -1,4 +1,3 @@
|
||||
// Package d2vector provides an implementation of a 2D Euclidean vector using float64 to store the two values.
|
||||
package d2vector
|
||||
|
||||
import (
|
||||
@ -38,15 +37,14 @@ func (v *Vector) Equals(o Vector) bool {
|
||||
// EqualsApprox returns true if the values of this Vector are approximately equal to those of the given Vector. If the
|
||||
// difference between either of the value pairs is smaller than d2math.Epsilon, they will be considered equal.
|
||||
func (v *Vector) EqualsApprox(o Vector) bool {
|
||||
x, y := v.CompareApprox(o)
|
||||
return x == 0 && y == 0
|
||||
return d2math.EqualsApprox(v.x, o.x) && d2math.EqualsApprox(v.y, o.y)
|
||||
}
|
||||
|
||||
// CompareApprox returns 2 ints describing the difference between the vectors. If the difference between either of the
|
||||
// value pairs is smaller than d2math.Epsilon, they will be considered equal.
|
||||
func (v *Vector) CompareApprox(o Vector) (x, y int) {
|
||||
return d2math.CompareFloat64Fuzzy(v.x, o.x),
|
||||
d2math.CompareFloat64Fuzzy(v.y, o.y)
|
||||
return d2math.CompareApprox(v.x, o.x),
|
||||
d2math.CompareApprox(v.y, o.y)
|
||||
}
|
||||
|
||||
// IsZero returns true if this vector's values are both exactly zero.
|
||||
@ -86,8 +84,8 @@ func (v *Vector) Floor() *Vector {
|
||||
// Clamp limits the values of v to those of a and b. If the values of v are between those of a and b they will be
|
||||
// unchanged.
|
||||
func (v *Vector) Clamp(a, b *Vector) *Vector {
|
||||
v.x = d2math.ClampFloat64(v.x, a.x, b.x)
|
||||
v.y = d2math.ClampFloat64(v.y, a.y, b.y)
|
||||
v.x = d2math.Clamp(v.x, a.x, b.x)
|
||||
v.y = d2math.Clamp(v.y, a.y, b.y)
|
||||
|
||||
return v
|
||||
}
|
||||
@ -245,7 +243,7 @@ func (v *Vector) Angle(o Vector) float64 {
|
||||
to.Normalize()
|
||||
|
||||
denominator := math.Sqrt(from.Length() * to.Length())
|
||||
dotClamped := d2math.ClampFloat64(from.Dot(&to)/denominator, -1, 1)
|
||||
dotClamped := d2math.Clamp(from.Dot(&to)/denominator, -1, 1)
|
||||
|
||||
return math.Acos(dotClamped)
|
||||
}
|
||||
@ -276,8 +274,7 @@ func (v *Vector) Reflect(normal Vector) *Vector {
|
||||
return v
|
||||
}
|
||||
|
||||
// ReflectSurface does the same thing as Reflect, except the given vector describes,
|
||||
// the surface line, not it's normal.
|
||||
// ReflectSurface does the same thing as Reflect, except the given vector describes the surface line, not it's normal.
|
||||
func (v *Vector) ReflectSurface(surface Vector) *Vector {
|
||||
v.Reflect(surface).Negate()
|
||||
|
||||
|
@ -602,7 +602,7 @@ func BenchmarkVector_Normalize(b *testing.B) {
|
||||
v := NewVector(1, 1)
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
v.Normalize()
|
||||
outFloat = v.Normalize()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,2 +1,7 @@
|
||||
// Package d2math provides mathematical functions not included in Golang's standard math library.
|
||||
/*
|
||||
The decimal numeric type used is float64.
|
||||
|
||||
Math also dictates the threshold for approximate equality (d2math.Epsilon). This is currently used both for moving
|
||||
entities and for approximate floating point equality in vector functions. See d2vector.*/
|
||||
package d2math
|
||||
|
@ -17,10 +17,9 @@ func EqualsApprox(a, b float64) bool {
|
||||
return Abs(a-b) < Epsilon
|
||||
}
|
||||
|
||||
// CompareFloat64Fuzzy returns an integer between -1 and 1 describing
|
||||
// the comparison of floats a and b. 0 will be returned if the
|
||||
// absolute difference between a and b is less than Epsilon.
|
||||
func CompareFloat64Fuzzy(a, b float64) int {
|
||||
// CompareApprox returns an integer between -1 and 1 describing the comparison of floats a and b. 0 will be returned if
|
||||
// the absolute difference between a and b is less than Epsilon.
|
||||
func CompareApprox(a, b float64) int {
|
||||
delta := a - b
|
||||
|
||||
if Abs(delta) < Epsilon {
|
||||
@ -37,14 +36,14 @@ func CompareFloat64Fuzzy(a, b float64) int {
|
||||
// Abs returns the absolute value of a. It is a less CPU intensive version of the standard library math.Abs().
|
||||
func Abs(a float64) float64 {
|
||||
if a < 0 {
|
||||
return a * -1
|
||||
return -a
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// ClampFloat64 returns a clamped to min and max.
|
||||
func ClampFloat64(a, min, max float64) float64 {
|
||||
// Clamp returns a clamped to min and max.
|
||||
func Clamp(a, min, max float64) float64 {
|
||||
if a > max {
|
||||
return max
|
||||
} else if a < min {
|
||||
|
@ -4,6 +4,15 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
//nolint:gochecknoglobals // These variables are assigned to in benchmark functions to avoid compiler optimisations
|
||||
// lowering the runtime of the benchmark. See: https://dave.cheney.net/2013/06/30/how-to-write-benchmarks-in-go (A note
|
||||
// on compiler optimisations)
|
||||
var (
|
||||
outFloat float64
|
||||
outBool bool
|
||||
outInt int
|
||||
)
|
||||
|
||||
func TestEqualsApprox(t *testing.T) {
|
||||
subEpsilon := Epsilon / 3
|
||||
|
||||
@ -22,12 +31,21 @@ func TestEqualsApprox(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompareFloat64Fuzzy(t *testing.T) {
|
||||
func BenchmarkEqualsApprox(b *testing.B) {
|
||||
x := 1.0
|
||||
y := 2.0
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
outBool = EqualsApprox(x, y)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompareApprox(t *testing.T) {
|
||||
subEpsilon := Epsilon / 3
|
||||
|
||||
want := 0
|
||||
a, b := 1+subEpsilon, 1.0
|
||||
got := CompareFloat64Fuzzy(a, b)
|
||||
got := CompareApprox(a, b)
|
||||
|
||||
if got != want {
|
||||
t.Errorf("compare %.2f and %.2f: wanted %d: got %d", a, b, want, got)
|
||||
@ -35,7 +53,7 @@ func TestCompareFloat64Fuzzy(t *testing.T) {
|
||||
|
||||
want = 1
|
||||
a, b = 2, 1.0
|
||||
got = CompareFloat64Fuzzy(a, b)
|
||||
got = CompareApprox(a, b)
|
||||
|
||||
if got != want {
|
||||
t.Errorf("compare %.2f and %.2f: wanted %d: got %d", a, b, want, got)
|
||||
@ -43,17 +61,52 @@ func TestCompareFloat64Fuzzy(t *testing.T) {
|
||||
|
||||
want = -1
|
||||
a, b = -2, 1.0
|
||||
got = CompareFloat64Fuzzy(a, b)
|
||||
got = CompareApprox(a, b)
|
||||
|
||||
if got != want {
|
||||
t.Errorf("compare %.2f and %.2f: wanted %d: got %d", a, b, want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClampFloat64(t *testing.T) {
|
||||
func BenchmarkCompareApprox(b *testing.B) {
|
||||
x := 1.0
|
||||
y := 2.0
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
outInt = CompareApprox(x, y)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAbs(t *testing.T) {
|
||||
want := 1.0
|
||||
x := -1.0
|
||||
got := Abs(x)
|
||||
|
||||
if got != want {
|
||||
t.Errorf("absolute value of %.2f: want %.2f: got %.2f", x, want, got)
|
||||
}
|
||||
|
||||
want = 1.0
|
||||
x = 1.0
|
||||
got = Abs(x)
|
||||
|
||||
if got != want {
|
||||
t.Errorf("absolute value of %.2f: want %.2f: got %.2f", x, want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAbs(b *testing.B) {
|
||||
x := -1.0
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
outFloat = Abs(x)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClamp(t *testing.T) {
|
||||
want := 0.5
|
||||
a := 0.5
|
||||
got := ClampFloat64(a, 0, 1)
|
||||
got := Clamp(a, 0, 1)
|
||||
|
||||
if got != want {
|
||||
t.Errorf("clamped %.2f between 0 and 1: wanted %.2f: got %.2f", a, want, got)
|
||||
@ -61,7 +114,7 @@ func TestClampFloat64(t *testing.T) {
|
||||
|
||||
want = 0.0
|
||||
a = -1.0
|
||||
got = ClampFloat64(a, 0, 1)
|
||||
got = Clamp(a, 0, 1)
|
||||
|
||||
if got != want {
|
||||
t.Errorf("clamped %.2f between 0 and 1: wanted %.2f: got %.2f", a, want, got)
|
||||
@ -69,13 +122,21 @@ func TestClampFloat64(t *testing.T) {
|
||||
|
||||
want = 1.0
|
||||
a = 2.0
|
||||
got = ClampFloat64(a, 0, 1)
|
||||
got = Clamp(a, 0, 1)
|
||||
|
||||
if got != want {
|
||||
t.Errorf("clamped %.2f between 0 and 1: wanted %.2f: got %.2f", a, want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkClamp(b *testing.B) {
|
||||
f := 0.5
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
outFloat = Clamp(f, 0, 1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSign(t *testing.T) {
|
||||
want := 1
|
||||
a := 0.5
|
||||
@ -102,6 +163,14 @@ func TestSign(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSign(b *testing.B) {
|
||||
f := 0.5
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
outInt = Sign(f)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLerp(t *testing.T) {
|
||||
want := 3.0
|
||||
x := 0.3
|
||||
@ -116,6 +185,16 @@ func TestLerp(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkLerp(b *testing.B) {
|
||||
x := 1.0
|
||||
y := 1000.0
|
||||
interp := 1.01
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
outFloat = Lerp(x, y, interp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnlerp(t *testing.T) {
|
||||
want := 0.3
|
||||
x := 3.0
|
||||
@ -130,6 +209,16 @@ func TestUnlerp(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnlerp(b *testing.B) {
|
||||
x := 1.0
|
||||
y := 2.0
|
||||
lerp := 1.5
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
outFloat = Unlerp(x, y, lerp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrapInt(t *testing.T) {
|
||||
want := 50
|
||||
a, b := 1050, 100
|
||||
@ -165,3 +254,12 @@ func TestWrapInt(t *testing.T) {
|
||||
t.Errorf(d, a, b, want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkWrapInt(b *testing.B) {
|
||||
x := 10
|
||||
y := 2
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
outInt = WrapInt(x, y)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user